Why does a transition occur when showing an element after setting a property while the element is hidden? - css

A live example can be seen here.
A red square (showing) is directly above a green square (hidden as overflow). Click on the square, and both colored squares are instantly made fully transparent. Additionally, the height of the red square is set to 0; this fires a transition, but the transition goes unseen because the red square is now transparent.
Before clicking the square again, examine the toggle function. Looking at the JavaScript, I would expect the height of the red square to be reset to its original value without firing a transition. The transition should be suppressed, because the transition property is temporarily set to none while the height is changed.
Now click on the square again. Both colored squares are instantly made fully opaque, but the red square slides down as its height transitions from 0 to the original value. It's as though the height set by the inline style wasn't removed by the toggle function until the element was visible, and by then the transition property had also been reset.
Triggering a reflow seems to force the change in height to be applied. (Uncomment the line containing offsetParent to test.) This behavior occurs across browsers (at least Chrome and Safari, Firefox, and Opera), so I'm wondering if it isn't part of some spec. I've checked the CSS Transitions Module without success. Any ideas why this behavior occurs, and why it's so consistent across implementations?

This really is a bizarre problem. I don't think you're doing anything wrong in your code—the current browser implementations are just buggy.
I've run into these kind of seemingly-obvious bugs before with CSS transitions, and they're a huge pain to deal with without resorting to byzantine hacks that are sure to break once the bug they're working around is fixed (in this case, my WebKit fix).
I really dug into this, but couldn't come up with a clean solution that worked in the three main transitions-supporting layout engines (WebKit, Gecko, and Presto). That said, here's what I did figure out—hopefully someone smarter than me (or just coming at this with fresh eyes) can take this answer and turn it into true solution.
Gecko and Presto (but not WebKit!)
It looks like (and I am not a browser engineer or familiar with the spec) that any current or previous value of a transition-property will continue to be rendered regardless of whether or not it needs to be. So even though you've changed the value of transition-property, the browser is still rendering the height transition in the background, and when you change the height back, you get the trailing end of that.
There is a solution though: create the transition in JavaScript (don't put it anywhere in the style sheet), remove it (after which there are no transition rules applied to #upper anywhere in the DOM), change the height, and then re-add it. Not perfect, but not a bug-reliant hack either.
http://jsfiddle.net/grantheaslip/e3quW/
JavaScript
upper.style.removeProperty('transition');
upper.style.removeProperty('-o-transition');
upper.style.removeProperty('-moz-transition');
upper.style.removeProperty('-webkit-transition');
upper.style.removeProperty('height');
// force a reflow
// if (upper.offsetParent) { /* empty */ }
upper.style['transition'] = 'height 1000ms';
upper.style['-o-transition'] = 'height 1000ms';
upper.style['-moz-transition'] = 'height 1000ms';
upper.style['-webkit-transition'] = 'height 1000ms';
Style sheet
#upper {
background-color: red;
}
WebKit (but not Gecko or Presto!)
Anything that only works because of a 1ms timeout probably should never go anywhere near production, but I think this is worth pointing out in case it helps someone get to the bottom of this problem.
My guess is that WebKit doesn't have the same issue as Presto or Gecko, but instead includes an optimization that gathers style changes applied in the same function and applies them all at once. Again, pure speculation from someone who's never gone near the WebKit source or CSS3 spec.
http://jsfiddle.net/grantheaslip/DFcg9/
JavaScript
window.setTimeout(function() {
upper.style.removeProperty('transition-property');
upper.style.removeProperty('-o-transition-property');
upper.style.removeProperty('-moz-transition-property');
upper.style.removeProperty('-webkit-transition-property');
upper.style.removeProperty('opacity');
lower.style.removeProperty('opacity');
}, 1);
Gecko, Presto, and WebKit
Here's both solutions combined. Again, because of the timeout hack, this really shouldn't be used.
http://jsfiddle.net/grantheaslip/N3NrB/

Related

Paradoxical css rule `.myClass:hover { display:none; }` has no effect

Preamble: This is a somewhat 'academic' question. I'm looking for an explanation and intelligent conjecture, not a practical solution (there is no real problem to "solve").
So, I notice that if I make a :hover selector set its display property to none, it has no discernible effect in Chrome (v23). In fact, no other properties in the selector are applied. It's as if the entire selector is ignored.
e.g.
<div class="myElement">Hover over this. Nothing happens!</div>
...
.myElement:hover {
display:none;
color:red;
}
(Check out the jsFiddle of this)
Obviously, since an element with display:none cannot be hovered, the element is instantly no longer becomes selected by the :hover selector, so loses the display:none property (and becomes eligible for selection again).
The paradoxical nature of this rule leads me to wonder why (for example) the display property doesn't toggle rapidly (every frame, or mouse move) as it does in other browsers (ie9, firefox). Although I think I prefer Chrome's implementation, I wonder why the other properties (e.g. color:red) aren't applied.
The question: is there some official documented reason why Chrome chooses to bail on this silly selector, or is this some kind of bug?
The question: is there some official documented reason why Chrome chooses to bail on this silly selector, or is this some kind of bug?
After looking at the render events that occur when you hover the link, it looks like Chrome actually renders this change in display (I originally thought Chrome was ignoring it for performance reasons). In 1.65s, it captured 11360 events recalculating style and layout because of this change in display.
So why don't you see a flicker? Chrome is rendering the change at such a fast rate you won't see the change (or the browser just doesn't render it). When you switch to visibility: hidden, you see that flickr because the item is still in the render tree, just hidden (plus, it's slower, a lot less render events are firing).
I wonder why the other properties (e.g. color:red) aren't applied.
It's cascading, so the display: none is applied, then the red color. The same reason why you never see the hover state is the same reason why you don't see the color change.
Hope that helps!
I think display:none and hover at same time is causing the confusion to the browser. It works with visibility:hidden though.
display:block;
visibility:hidden;
color:red;
you can check it here: http://jsfiddle.net/MnZyx/2/

Css3 perspective-property not working in IE10

I try to make a flip-page effect in IE10.
Because IE10 doesn't support transform-style: preserve-3d;
i have to flip each side seperately. It works well in recent browsers but there is no perspective in IE10.
If i write perspective: 1000px; in the container(.flipper), backface-visibility/z-index is not working correctly.
Have a look at tis jsfiddle:
http://jsfiddle.net/wG6gk/2/
I have no clue why you have xpersepective in your CSS, IE10 is unprefixed in CSS, however the perspective property must have some kind of unit for the depth, perspective: 1000 won't be applied because the browser doesn't know what unit it is in, similarly like width and height, etc, you have to apply px, em, etc. The only browsers that assume units (and in pixels) on the perspective property are Webkit browsers, and only when it is inside the transform property.
If you do a little research you, Microsoft states:
The W3C specification defines a keyword value of preserve-3d for this property, which indicates that flattening is not performed. At this time, Internet Explorer 10 does not support the preserve-3d keyword. You can work around this by manually applying the parent element's transform to each of the child elements in addition to the child element's normal transform.
So for now, you'll just have to implement the advised fix, if you want to go down that road.
If not, you're lucky. I spent time trying to make it transition smoothly over. Originally in your fiddle, you were transforming it very awkwardly and had too many styles, in my opinion, so the techniques in this JSfiddle should help: http://jsfiddle.net/NAy2r
Explained fiddle
So basically the front content exists in the container div, while the back content exists in the back div, which exists inside the container div. This is very similar to Apple's HTML5 Card flip demo, however there is a twist when it comes to backface-visibility.
At the time that Apple relased that demo, backface-visibiity didn't work on Chrome or Firefox. Chrome had some concept of perspective, but none of backface-visibility, so when you flipped an element, you'd still see through to the back and the content of the back would show through both sides as well; However on Safari, it'd be perfect because it initially understood these concepts.
In further updates of Chrome in the months afterwards, Chrome understood the property, however it was applied literally and the back was hidden completely, regardless if you flipped it or not! What would be the point of having this property if it was going to hide the back completely no matter what? You could just apply display:none, etc, to show the back if you wanted!!
And that is where IE stands as of today, it as well doesn't recognize the 'back' of the element (an element with transform:rotateY(180deg) is considered to be the backside) like other modern browsers do. So when the element is flipped, backface-visibilty: hidden is taken literally as it was in Chrome!
So this fiddle listens on an AnimationStart event on the container div, and on the animation start, it finds the duration of the animation and it uses that to calculate halfway though the animation, so when the animation is halfway, it changes backface-visibility to visible, that way the animation smoothly transitions like it's supposed to.
This was a pain to develop, IE10 is somewhat inconsistent, as it needs time to process it the first time (probably the jQuery). Notice the relief, lack of headache and fiery red eyes. The air around you has become cooler and you can finally breathe, because now you're not alone.
Edit: I forgot to add, that if your animation or transition has a different timing, the timing in this script will have to be adjusted, as it only works with linear transitions, as of now...

CSS3 rotateY transition not correctly rotating about y-axis

I have the following code:
http://jsfiddle.net/RFMxG/1/
When the transition runs, you can see a padding of about 20-30 pixels on the left hand side. Despite the fact I have set the transform-origin to be 0,0,0, it is still not correctly rotating about the y-axis. The left edge of the blue box should be flush against the left hand edge at all times during the animation.
Can anyone tell me what I've done incorrectly?
Okay, there are whole bunch of issues here:
1) CSS transforms aren't animatable using transitions. If you look at the W3C list of transitionable properties, you'll notice that transform isn't there.
2) -webkit-perspective only affects the children of the element it is applied to, not the element itself. Read the Safari blog on this:
The interesting thing about -webkit-perspective is that it does not
affect the element directly. Instead, it affects the appearance of the
3D transforms on the transformed descendants of that element; you can
think of it as adding a transform that gets multiplied into the
descendant transforms. This allows those descendants to all share the
same perspective as they move around.
3) It's awesome that you posted a fiddle, but since this is a CSS problem, for future reference it would have been a lot easier if you cleaned out all the javascript, and used one set of browser prefixes only. Help us help you!
4) What you probably want to use is an animation. Here's a highly modified version of your fiddle that works on hover:
http://jsfiddle.net/RFMxG/4/
5) If javascript is your skill set, and you're at all concerned about browser compatibility (which of course you are!), I highly recommend doing these kinds of animations with jstween.
Right, so the solution was actually due to the fact the transform origin needs to be set prior to the animation starting (it cannot be set at the same time the -webkit-transform property is set).
I've updated the fiddle to demonstrate this now works correctly.
http://jsfiddle.net/RFMxG/5/

IE 7 / Quirks Mode and Background color?

This is going to be a vague and obscure question, which is probably due to the fact that even using IE Web Developer, I have no idea what is going on.
I have a utility which I am working on. It's mostly JavaScript, and it has a small floating DIV user interface that shows up on a page. So far, standard stuff. The problem is the background color of some DIVs in the UI. The colors are assigned by CSS, and (tired refrain:) it looks fine in Firefox, Chrome, and Opera, but of course IE is being difficult.
The background does not show up in IE in quirks mode or IE7 mode, but it does in IE8 mode. For the life of me, I can't seem to figure out why IE7 isn't showing the background.
The page you can see the offending code is here: Log Hound Demo. Floating DIV is in the upper-right-hand corner - click the "V" to open it up.
Looking at that page in IE and then in [any other browser on the planet] will show you the missing background colors easily enough. I swear, even Lynx renders it better... ahem. The offending DIV IDs are lhPlateHead, lhPlateCtrlPanel,lhPlateTagPanel - easy to find with Firebug at least. They should be heeding the .lhPlateColor class with a background color of #DFEAF8, but that color is never applied.
With IE web developer up, I tried removing the CSS classes and re-adding them. I tried every combination of browser and document mode - again, only IE8 browser mode in IE8 document mode had the background colors working.
If anyone is bored enough to take a look and figure something out, I'd be much obliged.
Well - I finally figured it out, and as far as I'm concerned, this is another reason IE will always suck.
The circumstances of the problem are:
You are creating an element programatically:
myelmt = document.createElement('DIV')
You are setting the styles of that element programatically:
myelmt.setAttribute('class', 'myclass');
You are then adding that element programatically to the DOM:
body.appendChild(myelmt);
You are using IE.
IE hates you.
In cases such as this, IE8 will honour the "myclass" css and style the element properly when it is added to the DOM. IE7 and I'm guessing below will blow off the CSS styling and leave you thinking that employment at McDonald's is probably a whole lot less stressful.
To recap for the impatient:
Works in IE8 and EVERY OTHER BROWSER ON THE PLANET
var myelmt= document.createElement('DIV');
myelmt.setAttribute('class', 'myclass');
body.appendChild(myelmt);
Works in IE7 and below:
var myelmt= document.createElement('DIV');
var attr = document.createAttribute('class');
attr.value = 'myclass';
myelmt.setAttributeNode(attr);
body.appendChild(myelmt);
If someone can expound on exactly why this is a problem for IE7, feel free as I revel in the minutiae. Otherwise, just remember that it's all fun and games until someone loses an object reference.
Try adding zoom:1 to whatever element the background color doesn't work on.
I believe the issue has to do with how IE paints table cells. Try putting in a IE only CSS rule that applies the background color explicitly to TD's. Like this:
.lhWarnMsg .logMsg td
{
* background-color: #fbffbf;
}
Hopefully that will work for you.

CSS Hover & onmouseover/out causing 15-20% CPU Usage in Internet Explorer

is there any reason why Internet Explorer (IE7 in my case) gets sluggish and eats up lots of CPU time when using the CSS :hover command or using onmouseover/onmouseout?
I'm really not doing anything complex, nor is my page particularly large.
When I move my mouse anywhere else on the page (where nothing is changing) iexplore.exe stays at 0%, but once I start moving across any element that has onmouseover/onmouseout or a CSS hover class attached to it, things get really slow and sluggish and CPU usage gets high.
The page works perfectly fine in Firefox, Chrome and Safari with not speed issues/sluggishness whatsoever.
Hints/Ideas?
Edit: The onmouseover/onmouseout is on <tr> tags (highlighting a row in a grid); the CSS:hover is used on <a> tags swapping a background-image url.
You need a non-flicker CSS rollover (which doesn't trigger continual 'hover' signals with every tiny mouse movement). Swapping images on hover generally doesn't work too well, especially in IE.
The best way to do this without a Javascript library is to have the desired 'hover' image as a background to the element beneath the one you're hovering over, and the non-hover image as a background to the element in front.
Then for the CSS :hover state of the element in front, set background-image: none; background-color: transparent; so that the desired 'hover' image in the underlying element is revealed.
Check the source code for this example non-flicker CSS rollover.
Depending on your markup, you may need to adjust the z-index value to get the top element 'in front' of the underlying one.
not doing anything complex
Well, what are you doing? I've seen this just from changing the background tr color. IE doesn't seem to be good at this.

Resources