I have noticed that (using jQuery in Chrome 43) transitions are disabled when the element has display: none. Is this standarized behavior on all browsers, a feature of jQuery, or is it something that cannot be relied on in production?
The transition is enabled when the CSS statements to be animated are changed in a deferred function. Take a look at this JSFiddle. Uncomment line 3 or 6 to see it for yourself.
SOLUTION:
This behavior cannot be relied upon in production as it seems to be a product of optimization/design choices rather than specification (as per #Andriy Horens answer). Instead you should turn on and off the animation (transition-property: none) with a class. Failing to use a class rendered it unreliable for me in Chrome 43. Chrome did also require separate frames (defer the code with a timeout of 0) to update some CSS statements. Just defer anything related to animations if you want to save development time.
According to MDN:
Display
In addition to the many different display box types, the value none lets you turn off the display of an element; when you use none, all descendant elements also have their display turned off. The document is rendered as though the element doesn't exist in the document tree.
So i think elements with display set to none will not be rendered at all across all browsers and therefore transition or any other visual effect won't be applied.
You can also test yourself by subscribing to transitionend event:
$(element).on("transitionend", function () {
console.log("transition ended");
});
Update:
It is also per w3c specification:
And some values (such as display:none, display: contents, and box-suppress: discard) cause the element and/or its descendants to not generate any boxes at all.
Where boxes are visual representations of element. And transition is definitely a part of visual representation as it also can affect layout e.g. when you change relative position of element with transition applied.
Here is one more example of how different are animations of elements with display : none and visibility : hidden in other words of rendered element and not-rendered one.
JSFiddle DEMO
Related
I'm developing a slide in/out panel using HTML and CSS.
I notice in some CSS code examples on the internet that they set the visibility property of the div to hidden once the div is completely out of view (via some negative margin-left index or some other), and obscured by overflow: hidden of its parent container. (and then back to visible when the user slides it out again)
However, in other examples they ignore this property, instead relying on the fact that it is completely hidden due to being out of view already.
I'm curious of the differences of these two approaches. One example I can think of is performance: I'm ignorant of whether or not browser rendering engines apply better optimizations to elements that are set to visibility: hidden, because it is guaranteed that they will not be seen.
Or is the browser smart enough to realize it is not being shown? Or does none of this matter, and the performance is identical regardless of whether it is visible to the user, hidden by overflow, or hidden by visibility: hidden?
Does anyone have any insight into this? Or can recommend the best practice?
There was an interesting study done on this actually which can be found here
To save you reading it, I'd say this is the main bit you're probably after:
The renderers correspond to the DOM elements, but the relation is not
one to one. Non visual DOM elements will not be inserted in the render
tree. An example is the "head" element. Also elements whose display
attribute was assigned to "none" will not appear in the tree (elements
with "hidden" visibility attribute will appear in the tree).
Basically saying, setting an element to have a visibilty of none will not stop it getting rendered but using display: none will.
In regards to the coding examples you spoke of, I'd say it's personal preference. Some people will set the visibility to none to maybe double-cover for themselves in the case that the hidden element gets put into view but doesnt need to show a particular element, maybe also to prevent the horizontal scroll bar from appearing too?
It's definitely not needed or required though and I'd personally leave the visibility property alone in this case.
In a complex web application, I have to check whether certain HTML elements are visible partly/completely on the screen.
There are various reasons why certain elements are not visible on the screen:
They have certain attributes, like display:none visibility:hidden width:0 height:0 opacity:0 and maybe others.
Other elements are in front of the element.
They are outside the parent's visible scroll area.
To a certain extent, some of their parents have one or more of the properties above (elements with absolute or fixed positioning break the chain).
They are outside the parent's visible area for other reasons, for instance the parent may be partly overlaid by other elements and they are only covering that part.
The things I found on stack overflow (like How to Check if element is visible after scrolling?, http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport and others) are doing simple checks for one or two of the reasons above, but do not even nearly try to detect all reasons I lined out.
Before I now start implementing everything manually, including all the corner cases: Is there a reason-agnostic check available through javascript, that will give me feedback on whether the element is visible in the rendered result?
For now, the easiest and most reliable thing I could come up with was the idea (didn't test it yet) to modify the background-color attribute of the element, use the html2canvas library before and after, and check whether the resulting images match.
Is there anything short of that "workaround"?
(Update: I have tested my html2canvas approach and not only is it slow, it also gives false positives because the images are not always the same, even if the element with changed background-color is not visible at all.)
This is really really weird:
Without anything in chrome buttons look like this:
<button>Test</button>
However when you throw in the slightest of border-curvature, the css dramatically shifts to
<button style="border-radius:1px">Test</button>
Event More noticeable is the button:active css changes....
How is it that so many properties can change by adding styling to an object?
is there even such a thing as a css selector based on styling?
ie. button:styled{}?
here's a jsfiddle https://jsfiddle.net/vya24rhw/
The reason that you are seeing a big difference is because when there is no border-radius set, the UA (WebKit) assigns the value for the -webkit-appearance property as button whereas when there is a border-radius set, it resets it to none. It seems like the button appearance has some specific style settings which are not applied when the appearance is set to none. This can be viewed from the Computed Styles tab in the Developer Console.
As stated in this WebKit blog article dated 7th October 2005, there are three appearance constants for buttons namely, push-button (which is used by <input type="submit" .../>), bevel-button and button (which is used by the <button> element). When an appearance constant is set, the element continues to use the pre-defined appearance settings unless we explicitly reset the appearance value to none or use our own background and/or border properties. In my opinion, this explains the reason for the difference that we are seeing.
Note: The blog article doesn't explicitly specify border-radius but I am considering border properties to cover the entire spectrum of all properties relating to border and its styling.
Introductory information:
I've made a fixed menu button to show the navigation menu when using a mobile device. For this application I'm using the Headroom.js script to make the button smaller when scrolling downwards to ensure that it doesn't block too much of the content. The animation/transition is applied by adding a class with the given changes.
In the original method i changed the size and look of the button by changing height/width of the parent element and padding of the child element with CSS (and css transition).
The new method, which I've read could/should be better according to various sites, is changing the size of the button by using transform: scale(). Note that i'm also moving the element a bit by also applying translate3d(20px,20px,0) in this method. However, it feels a bit smoother when scrolling using the transform: scale() method (could be a placebo effect though), but using chrome dev tools' timeline gives me seemingly inconclusive results.
Therefore a part of my question is also how I should evaluate the best method. Is timeline in Chrome Dev tools the best option, or is there a better way to do it? And which elements of the timeline should I base my choices on? and the other thing is, based on your interpretation of the images and/or tests combined with your knowledge, which method performs the best (or should perform the best in theory)?
Beneath you can see two examples of the timeline with each method.
Changing height/width and padding (original method):
Method using transform: scale() to change the size:
Also you can try the different methods in fiddles here:
link: Original method changing height/width and padding
link to new method: using transform:scale
Please ignore the poor layout of everything; especially the button. The ugly image inside the menu button is just to show, that there's an image included in the layout on my own page and to take that into performance considerations. The images in the back is also included since it's a webshop with a lot of images which could influence performance.
CSS for added class that makes the changes in the original method:
.mobile-nav.headroom--unpinned {
height: 40px;
width: 40px;
}
.headroom--unpinned .mobile-content{
padding-top:4px;
}
CSS for the added class using transform:scale():
.mobile-nav.headroom--unpinned {
transform:scale(.5) translate3d(20px,20px,0);
}
So to summarize my questions:
How do I evaluate which methods has the best performance, and which method would you say performs the best?
A final note: I know that the methods are different (animating different things and more elements in the original method) but these are the 2 options which i prefer as it is right now.
I believe you are missing the point, Chris: the reason why no other property but transform and opacity should ever be animated is because they don't trigger a repaint in anything else, even if the element is in the document flow (and because you can basically do anything with these two alone in like 95% of the cases).
From the "hit-on-performance" point of view, there are two types of animations:
those that trigger a repaint in other elements than the animated element
those that do not.
That's the main reason behind recommending animations by transform, opacity or position:relative;left|right|top|left. Because they don't actually move the element in flow, thus not triggering a repaint to every single other element in flow after the one being animated.
Now, if the said parent was positioned absolute (which I assume to be the case), it wouldn't have triggered a repaint to the rest of DOM anyway so the differences between that method and transform would have been minor. Inconclusive, as you put it. In theory, repainting two elements instead of one should be slower.
If you need to test, make 10k clones and trigger animation on all of them, with each method.
That will be conclusive.
If you really want to min-max this (as in spend absurd amounts of time on hardly noticeable improvements, as I do) you will find plenty of resources that will recommend:
replacing any .animate() with .velocity()
never animating anything but transform or opacity, although Velocity claims they animate anything without a hit on performance (i find that debatable/arguable, at best) - but it's a net improvement over .animate()
sticking to CSS transitions, if possible (basically if you don't need chains)
using Web Animations API
Personal advice: never count on synced CSS animations, especially when you have many of them. If you change tabs or the system does something extremely resource heavy for a while, your animations will be way off. If you need chains, chain.
If, for example, you put a CSS hover effect on an element, and also put a JS mouseenter event on it, which one will happen first? Is there any variance with this? Can you control it somehow? Is it possible to force them to execute in a particular order?
which one will happen first?
Notice that there is no such thing as a "CSS event". However, the behaviour is undefined; you could consider the CSS change and the JS event to happen at the same time. The relevant specs CSS Selectors 4, DOM 3 Events and HTML 5 point out the similarities between hover and mouseenter, but do not specify an order. Mouse event order is specified, but does not refer to CSS user action pseudo classes.
Is there any variance with this?
Yes, browsers are free to implement it either way. They could change the layout and redraw the page before they fire the JS events, or they could not. It should however not make much difference.
Is it possible to force them to execute in a particular order?
I personally would expect in the CSS to be applied already when the JS event handler is executed. Even if it was not yet computed, when querying styles (e.g. getComputedStyle(this)) a CSS recomputation is done so that you should always get the dynamic styles - see also When does reflow happen in a DOM environment?.
Try it out at http://jsfiddle.net/n4Z8H/. While most major browsers will yield the expected value (rgb(0, 0, 255), the blue :hover style), older IEs don't seem to do.
Depends a lot on how the browser works, and shouldn't be relied on. Most browsers should run the two at almost exactly the same time. If you want one to execute before/after the other, just control the CSS styling via JavaScript, for example on hover add a class and on not hover remove the class.
Although, if this is an actual issue you have, you're probably doing something wrong.