Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getComputedStyle and transitions

Looking for a workaround while I consider submitting a bug to Chromium -

If an element has a transition, getComputedStyle does not return what you would expect it to return until after the transition is over.

Long and short - if I have an element with a height of 24px, and adding a class gives it a height of 80px (with a transition to and from), and both heights are defined in the stylesheet - if I set that class and check getComputedStyle, it still gives me the non-class height until the transition has ended.

A sample of what I'm talking about here:

<html>
    <head>
        <style>
            #foo {
                display: inline-block;
                background-color: red;
                height: 24px;
                padding: 4px 0;
                width: 200px;
                -webkit-transition-property: height;
                -webkit-transition-timing-function: linear;
                -webkit-transition-duration: 300ms;
            }
            #foo.changed {
                height: 80px;
            }
        </style>
    </head>
    <body>
        <div id="foo"></div>
        <p>before: <span id="before"></span></p>
        <p>after: <span id="after"></span></p>
        <script type="text/javascript">   
            var foo 
            function checkFoo(e) {
                foo.classList.toggle('changed');
                document.getElementById('before').innerText = window.getComputedStyle(foo, null).getPropertyValue("height");
            };

            window.addEventListener('load', function() {
                foo = document.getElementById('foo');

                foo.addEventListener('webkitTransitionEnd', function(e){
                document.getElementById('after').innerText = window.getComputedStyle(foo, null).getPropertyValue("height");
                });
    
                foo.addEventListener('click', checkFoo, false);
            });
        </script>
    </body>
</html>

Fiddle of this sample here: http://jsfiddle.net/bobbudd/REeBN/

(Note: This fiddle is only going to work in webkit, it's the one browser we're targeting believe it or not -- but I've also tested and get the same issue in Firefox)

Problem is, I have multiple cases where I need to know the final style (some might say the "computed" style) BEFORE the transitionEnd happens.

Or I guess it's part of a larger question - with so many different ways to know they height of an element as it is at a specific moment in time, should getComputedStyle not get what the stylesheet (or style attribute) says the property is supposed to be?

And before you ask if I can put the final number in the JS, the answer is (unfortunately) no.

Can anybody think of a way of getting this final value before the transition ends?

like image 335
borbulon Avatar asked Dec 01 '12 03:12

borbulon


People also ask

What does getComputedStyle do?

getComputedStyle() method returns an object containing the values of all CSS properties of an element, after applying active stylesheets and resolving any basic computation those values may contain. Individual CSS property values are accessed through APIs provided by the object, or by indexing with CSS property names.

What are computed styles?

The computed style is the style used on the element after all styling sources have been applied. Style sources: external and internal style sheets, inherited styles, and browser default styles.


1 Answers

This isn't a bug at all. getComputedStyle is meant to return the client rendered value of an attribute at the time you invoke it. If you invoke it during the transition you will get the value during the transition, as demonstrated here: http://jsfiddle.net/REeBN/1/

The way you can get the final values as set by a rule is by examining the rule itself, probably through the use of cssRules.

Here is an implementation using window.getMatchedCSSRules:

cssRules = window.getMatchedCSSRules(this);
var finalCssRule = "";
for(var i = 0; i < cssRules.length; i++){
    if(cssRules[i].selectorText == "#foo.changed"){
        finalCssRule = cssRules[i];
    }
}
document.getElementById('final').innerText = finalCssRule.cssText;

Here is a demonstration: http://jsfiddle.net/REeBN/2/

like image 99
Asad Saeeduddin Avatar answered Oct 13 '22 16:10

Asad Saeeduddin