Bug Tracker

Opened 8 years ago

Closed 8 years ago

Last modified 7 years ago

#9036 closed bug (wontfix)

$(..).hide(XX) -- unexpected behavior for elem with either 0px width or height

Reported by: shadedecho Owned by:
Priority: low Milestone: 1.next
Component: effects Version: 1.5.1
Keywords: Cc:
Blocked by: Blocking:



If an element either has a 0px width or height (or both), but it has contents that are visible (via overflow), the expectation would be that the element would still have some sort of reasonable hiding behavior, such as the alpha fading.

However, by virtue of the fact that clipping occurs immediately, all the contents are hidden (since the 0px width or height will show nothing if overflow:hidden is applied) immediately, effectively making any smooth animation (of alpha) of the hiding of the element moot.

So, I would request one or more of the following:

  1. jQuery *not* apply the clipping to an element (and thus not do the animation of the width/height shrinking) if either dimension of the element is already 0px. By not applying the overflow:hidden clipping, it would leave the alpha animation hiding to still work, which I think is the most default expectation.
  1. Change the .hide() method to allow some option/param to tell jQuery not to try and animate the dimensions (only the alpha), and thus not apply the overflow:hidden clipping.
  1. Have jQuery discover the actual overflow dimensions of the element, first change the dimensions to match that measurement, and THEN do the animated hiding.
  1. Add some note to the documentation for .hide(), in the section where it talks about width/height being animated during hide, to call out the fact that an element with smaller dimensions that its visible content (even 0px) will get clipped immediately (not animated), and the result can be either partial or full hiding of the content immediately, without animation.

Change History (9)

comment:1 Changed 8 years ago by timmywil

Component: unfiledeffects
Keywords: needsdocs added
Priority: undecidedlow
Resolution: wontfix
Status: newclosed

Hiding the overflow is required for animation to run smoothly. And discovering the overflow dimensions would be far too costly. If you fix the dimensions of the element you are hiding, the animation will run smoothly. This occurs most often when you have floated elements within the element you are animating. There are several resources for doing a clearfix so that the dimensions of the main element are automatically fixed without having to set them manually. Nevertheless, we could add a note in the documentation clarifying that hidden overflow occurs.

comment:2 Changed 8 years ago by shadedecho

There are legitimate, if a bit niche, reasons why an element would have a 0px dimension, while taking advantage of its ability to still show content via its overlay. For instance, I use the technique of centering a position:fixed element by having a container div of 0x0 dimensions, which is fixed at 50%/50% (direct center of viewport), and then I locate elements (like modal popins, ajax loading spinner messages, etc) inside that container, so that those elements appear relative to the full center of the viewport, in a 'fixed' fashion regardless of scrolling or browser window changing.

In any case, I think it's inappropriate to say "just *fix* your dimensions", because it's not a mistake, it's intentional that my element has 0px dimensions. And even if it had 1x1 dimensions (still centerable in the viewport), the overflow:hidden clipping that is applied would still hide my content immediately rather than in a graceful animated way.

Moreover, I do not understand why my #1 suggestion above couldn't easily be done? Just simply detect if an element has either 0px width or height, and just don't do the animating of its width/height in that case, instead ONLY do the animating of the alpha. You surely don't need the overflow:hidden clipping to animate the alpha in the hide effect.

comment:3 Changed 8 years ago by shadedecho

FYI: Another example, which I've done a few times, is to have a 0x0 dimension container, not position:fixed, but position:absolute, which has several elements positioned inside it that are visible (like parts of a game character avatar, etc), and animating the whole collection of elements by changing the position/rotation of only the container. By having the container be 0x0 in size, it effectively makes it easy to create a different "registration point" for coordinates mapping, which makes coding things like moving an object around by its center coordinate, rotating it, etc, MUCH easier.

In any case, if I have a 0x0 dimension container, with perfectly valid and visible elements inside it, and I say hide(300) on that container, my expectation would be that it could animate the alpha of the container to 0 (thus hiding everything inside it too), without BEING REQUIRED to also animate the width/height of the container (which is what creates the problem).

Sure, I could accomplish this with a custom animation effect. But the point is, why couldn't hide() simply not animate the dimensions if either dimension is already 0? There's no sensible reason for hide() to try to animate the dimensions if one is already 0, because ostensibly, that element (its children elements notwithstanding) isn't really "visible" anyway, and certainly animating from 0 down to 0 is silly.

comment:4 Changed 8 years ago by timmywil

I did not mean to insult. I simply provided the solution for what I thought was the most common use case for when this occurs. Your first solution would not be plausible because show and hide not only animate width and height, but opacity as well. In order to animate opacity, filters must be used as you said in IE6-8. In IE6-7, applying any filter results in the same effect as overflow:hidden. So at least in order to provide consistency, we must do overflow:hidden in all browsers. If we were to detect a width or height of zero, it would not really help you with the animation. You would get exactly the same effect in IE6-7 whether we do the overflow or not, and even if we didn't animate opacity, what you would see is a pause for whatever the duration is, then an immediate hide just as before. This is a feature creep. You can easily write your own custom animation, but animating opacity is not an option for IE6-7 when you have overflow.

comment:5 Changed 8 years ago by shadedecho

OK, that's fine information, that IE6 and 7 wouldn't have smooth opacity animation in my use case. I didn't know that.

But IE 8 and 9, and every other modern browser on the planet, WOULD have smooth opacity animation in this case, right? I mean, *I* frankly don't care that much that IE6 and 7 would be slightly less graceful, if everyone else could benefit from the more smooth opacity animation.

And isn't this a perfect use-case argument for "progressive enhancement" (or "graceful degradation")? By definition, we have a case here where very old browsers can't get the smooth animation, but can at least get the full-stop hiding (the most important part), and *all other modern (or even remotely modern) browsers* can get a more "enhanced" experience with the animation of the opacity.

I recognize that I could write my own animation easily. I could also hack my copy of the jquery source code to make hide(XX) do the more sensible thing. That's not really the point of this ticket.

The point of this ticket is that there's a case where a more sensible thing could (fairly easily) be done with hide(XX), for all modern browsers (and would only fail to be sensible in really old browsers like IE6 and 7). But even in that "failure case", the important part, the hiding, would still work just fine.

So I don't see the downside in this being an example of progressive enhancement baked into jQuery, to make hide(XX) more sensible, other than maybe a half-dozen extra lines of code at the most?

comment:6 Changed 8 years ago by shadedecho

To be clear, the "algorithm" I'm suggesting is this:

  1. upon a call of hide(XX) on an element, detect if the element has either 0px width or height
  2. if both are non-zero dimensions, continue as would normally be done
  3. if either are 0px, do NOT apply the overflow:hidden cropping, do NOT do any animating of the dimensions, and simply do an animation of the opacity ONLY.
  4. for IE6 and 7, the animation of opacity won't work, because the filter will automatically and immediately crop the content. Note this in the documentation as a "graceful degradation" for old IE6 and IE7.
  5. alternatively, ONLY for IE6 and IE7 in the 0px dimension case, go ahead and apply the overflow:hidden, just for completeness sake. But only for IE6 and 7.

Other than you claiming this is "feature creep" or just an ignorable "corner case", what's the downside to that approach?

comment:7 Changed 8 years ago by timmywil

Well, I do think this is a feature creep and an edge case that should not be included in core. Nevertheless, right now it is consistent. Treating IE6/7 differently would break that consistency. I understand wanting to eventually veer away from IE6/7 (believe me I love the idea of progressive enhancement), but their market shares are still too high.

comment:8 Changed 8 years ago by shadedecho

It's true, you do have consistency: consistenly broken for my types of use-cases. I'm suggesting that other than IE6/7, you *could* improve things for all other browsers, such that modern browsers wouldn't be broken anymore.

Breaking consistency is justifable if it's creating an improvement as a positive outcome for more modern browsers (while not making things worse for older browsers)... which is *exactly* what this would be.

And if you want to talk about "feature creep", IMHO whoever specified that hide(XX) should animate the dimensions in the first place was guilty of that. hide(XX) in the core should only have ever been about hiding the element with opacity animation... doing the dimension animation should always have been an additional custom effect, not the default (and non-overridable).

comment:9 Changed 8 years ago by addyosmani

Keywords: needsdocs removed

Updated: http://api.jquery.com/animate/ We should probably also cross-reference with .hide()

Note: See TracTickets for help on using tickets.