Jump to content
Search Community

Dealing with "NS_ERROR_FAILURE"

se7en test
Moderator Tag

Go to solution Solved by OSUblake,

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hello,

 

I am animating some SVG graphics and I am getting the "NS_ERROR_FAILURE" error on firefox when the display is set to none on certain elements.

 

I searched the forum and I found a recommendation to use "visibility: hidden" instead, but that is a different effect since display:none removes the element from the normal flow, while visibility: hidden just hides it (but it still takes up space).

 

Any other recommendations for dealing with issue?

 

I tried to pause animations before "display:none" is applied on them and then play them again after they are shown, but this is a big hassle because what is shown and what is displayed and where is controlled by the user. It would require a lot of code to deal with this bug in this way.

See the Pen d45d6b305b8b4615a1d221779a1d6cde by osublake (@osublake) on CodePen

Link to comment
Share on other sites

Hello se7en, and Welcome to the GreenSock forum!

 

This is not a bug in GSAP or Firefox, but is how the SVG spec dictates SVG elements with display none. When an element is set to display none, especially if the element is an SVG element or SVG child element, it will throw that NS_ERROR_FAILURE. This happens because any SVG element with display none is not part of the render tree and thus will not exist in that render tree. The NS means namespace.

 

Please see this: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/display

  • A value of display="none" indicates that the given element and its children will not be rendered. Any value other than none or inherit indicates that the given element will be rendered by the browser.

  • When applied to a container element, setting display to none causes the container and all of its children to be invisible; thus, it acts on groups of elements as a group. This means that any child of an element with display="none" will never be rendered even if the child has a value for display other than none.

When the display attribute is set to none, then the given element does not become part of the rendering tree. It has implications for the <tspan>, <tref>, and <altglyph> elements, event processing, for bounding box calculations and for calculation of clipping paths:

  • If display is set to none on a <tspan>, <tref>, or <altglyph> element, then the text string is ignored for the purposes of text layout.
  • Regarding events, if display is set to none, the element receives no events.
  • The geometry of a graphics element with display set to none is not included in bounding box and clipping paths calculations.

So what you need to do is either use the SVG visibility attribute on the main SVG element. Or use the CSS visibility property to hide your SVG elements!

 

Resources:

SVG Display: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/display

SVG Visibility: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/visibility

 

Hope this helps! :)

  • Like 4
Link to comment
Share on other sites

I searched the forum and I found a recommendation to use "visibility: hidden" instead, but that is a different effect since display:none removes the element from the normal flow, while visibility: hidden just hides it (but it still takes up space).

 

 

Can you use "autoAlpha:0" instead of "visibility:hidden"?

Link to comment
Share on other sites

autoAlpha will use both visibility and opacity so that would work as well. You just cant use the display:none property since it will remove the element from the render tree, and then the error will be thrown! But this just happens with SVG elements and that SVG namespace within the DOM.

Link to comment
Share on other sites

Thanks, but as I mentioned "visibility:hidden" doesn't work for me since it still affects the layout. It is not the same as display:none.

 

Is there a way to target whatever animation exists inside an element with pause and play? e.g. pauseChildTweensOf and playChildTweensOf (similar to the existing killChildTweensOf). Such functionality would be helpful so I can pause the animation before I set display:none and prevent this from happening.

Link to comment
Share on other sites

se7en, I suggested visibility:hidden or the SVG visibility attribute because that is the only option due to display none removing SVG elements from the rendering tree. That is the nature of SVG elements when rendered based on the SVG spec. ;)

 

If you are using visibility:hidden you can also set the height to 0. I understand that opacity 0 and visibility hidden will still allow the element to take that space up in the DOM, But again you can also set the height to 0 along with autoAlpha 0.

 

Because technically in accessing the regular DOM (non SVG) display none will still be part of the render tree as far as checking the length of the DOM node/ element with JS, making sure it is not zero (0).

 

There are other possible workarounds, but to better help you it would be better if you showed us the code you are trying, so we can help you better by seeing your code in context. Here is a video tut on how to create a codepen demo example:

 

 

Thanks! :)

  • Like 4
Link to comment
Share on other sites

Yep Jack your right, elements inside dont affect the outside of the <svg> root element. I believe he might mean the layout for his root <svg> element. In Chrome you can see the layout scope under the timeline tab and view the layout events. There you can see a blue rectangle box around the element, and see the layout boundry. But I have found, that I can only debug and view a layout boundry in only Chrome.

 

But I believe the <svg> element, the SVG root element gets a layout, when it's display property is other than inline-block or inline. The SVG element default display is inline, so you need to add the appropriate CSS display property, some finicky height property guidelines, and an explicit overflow property for SVG to gain a layout boundry.

 

Great discussion guys! :)

Link to comment
Share on other sites

I had the same thought. SVG elements (inside the <svg>) don't affect document flow at all unless I'm completely misinformed. 

 

Probably we are talking about different things.

 

Here is a super basic example that demonstrates the difference:

 

See the Pen ZQoeLy by se7en (@se7en) on CodePen

 

display:none - Turns off the display of an element (it has no effect on layout); all descendant elements also have their display turned off. The document is rendered as though the element did not exist.

https://developer.mozilla.org/en-US/docs/Web/CSS/display

 

visibility:hidden - The box is invisible (fully transparent, nothing is drawn), but still affects layout.

https://developer.mozilla.org/en-US/docs/Web/CSS/visibility

 

My exact situation is a bit too complicated to create a pen for it. I am not "display:none" the svg directly, but a div that contains (among other things) inline SVGs. In the codepen above setting the height to 0 has the same visible effect as display:none (you don't even need to set visibility to hidden) but in my more complicated structure setting visibility:hidden, height:0 and width:0, does not have the same effect as display:none. Some other things inside that div prevent it from totally collapsing.

Link to comment
Share on other sites

True. An easy way around that is to position it absolute or set it's size to 0 when you don't want it to affect the layout.

 

Adding position absolute together with visibility hidden and width:0 seems to work on my initial testing!

 

I will try it tomorrow morning. (it is very late here!)

 

Still, a bit of a hassle because I am using angular and the ng-show directive which uses "display:none". I will have to ditch that and use a custom function.

Link to comment
Share on other sites

Just make your own directive.

function gsHide($animate) {
  return {
    restrict: "A",
    link: function(scope, element, attrs) {      
      scope.$watch(attrs.gsHide, function(value) {
        $animate[value ? "addClass" : "removeClass"](element, "gs-hide");
      });
    }
  };
}
.gs-hide {
  position: absolute;
  visibility: hidden;
  opacity: 0;
}
<svg gs-hide="expression"></svg>

It even has a hook for animation modules

See the Pen 873ee0ebce96a9aa87206a9b00db1f5e by osublake (@osublake) on CodePen

  • Like 4
Link to comment
Share on other sites

I tried out OSUblake's solution and it almost worked.

 

Only issue was that I was getting scrollbars under certain circumstances and setting the width/height to 0 didn't eliminate the problem. Adding "overflow:hidden" seems to sort the problem.

 

Thanks for your help

  • Like 1
Link to comment
Share on other sites

To add my measly two cents, if you want to cover your bases cross browser for your hidden element than i would also add the following to your element. Also accounting for IE that has issues with children and grandchildren not to inherit their parents opacity:

.gs-hide {
   position: absolute;
   visibility: hidden;
   opacity: 0;

   overflow:hidden;
   font-size: 0;
   line-height: 0;
   height: 0;   
   width: 0;
   display:inline;
   text-indent:-9999999px; /* optional but helps in odd browser behavior */
}

.gs-hide *{
   opacity: inherit; /* due to IE bug that does not allow opacity to be inherited */
}

Also make sure you have at least one of your parents with position relative, so your absolutely positioned element will be relative to it.

  • Like 3
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...