4

During a transition, is there a way to see what the target value is for a style rule which is under transition? window.getComputedStyle gets the interpolated value, and element.style only looks at the style attribute (I think).

Here's a demo of the problem; I'd like to retrieve the target height value of 1200px during the transition:

https://jsfiddle.net/EoghanM/xz5s3ua6/5/

setInterval(function() {
  document.body.children[0].innerHTML = getComputedStyle(document.body.children[0])['height']
}, 300)

setTimeout(function() {
  document.body.children[0].classList.toggle('changing')
}, 1000)
div {
  height: 400px;
  border: 1px solid red;
  width: 200px;
  transition: height 100s linear;
}

div.changing {
  height: 1200px;
}
<div></div>

0

2 Answers 2

1

How about using getComputedStyle on a new instance of changing class?

You can create a div with the class changing and then use getComputedStyle to get the class properties (considering that the height of changing class will be the final height after the transition of your div) like this:

<div class="changing" id="new-changing-div"></div>

and get it's properties:

const element = document.querySelector('#new-changing-div');
const heightAttribute = window.getComputedStyle(element).getPropertyValue('height');
Sign up to request clarification or add additional context in comments.

5 Comments

I am not getting the computed style of the transitioned element, but a new instance of a changing class div
Oh yes, I see now... But what about an element, that has an applying CSS declaration other than a class (e.g. .changing:first-child)?
I mean how would you create a second element (clone) for a custom selector?
Yep, it would defiantly be a problem. We might not use such of css declarations for the transitioned elements in the first place, but that makes the solution not the best practice.
This looks great too; maybe an idea would be to manually override the transition duration to be 0s on the cloned element? I'm a bit worried about the cost of creating a clone of the element too but would have to measure that.
1

I'm 99% sure all of the DOM properties and methods for requesting the element's height (clientHeight, offsetHeight, getBoundingClientRect, etc.) will only give you the interpolated value. Another solution may be to read the value from the CSS stylehseet itself using the CSSOM.

In the code below, we search through the document's stylesheets checking if the selector exists in a rule declaration and if it does, return the value of the property we're looking for. You can console.log() various parts of the stylesheets and rules below to see how the browser stores the information as objects.

Of course this is a simple example based on a simple test case. There could be multiple rules using the same selector, but this will only find the first occurrence. The solution would need to be more robust to find the exact rule you're looking for.

function getCssRuleValue(selector, property) {
  const styleSheets = document.styleSheets;

  let styleSheetsLen = styleSheets.length;

  while (styleSheetsLen--) {
    const styleSheet = styleSheets[styleSheetsLen];
    const rules = styleSheet.rules;
    
    let rulesLen = rules.length;
    
    while (rulesLen--) {
      const rule = rules[rulesLen];

      // The passed-in selector text is found in the rule text
      if (rule.cssText.indexOf(selector) > -1) {
        return rule.style[property];
      }
    }
  }

  // The selector/property was not found in any document stylesheets
  return -1;
}

setInterval(function() {
  document.body.children[0].innerHTML = 
    getComputedStyle(document.body.children[0])['height']
    + '<br>' +
    getCssRuleValue('.changing', 'height')
}, 300)

setTimeout(function() {
  document.body.children[0].classList.toggle('changing')
}, 1000)
div {
  height: 400px;
  border: 1px solid red;
  width: 200px;
  transition: height 100s linear;
}

div.changing {
  height: 1200px;
}
<div></div>

2 Comments

This looks like the right direction for a solution.. The only thing I'm worrying about is (as you mentioned) the precedence rules; I imagine that'd be a nightmare to do manually. (the browser already does this so I was hoping for an answer describing some API that I'd missed)
@EoghanM I don't think it's too bad, but largely depends on how coupled you want your JS and CSS. You could easily change the above solution to look for 'div.changing' and also check that the rule text has the same text length, then you know it's an exact match. But if you ever change your CSS to just .changing or something else, you also have to update the JS. At that point, I'd say maybe you should just be creating these CSS rules in JS and inserting them into a stylesheet (you can use the CSSOM to do that too). Then you could have a variable holding what you want the value to be.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.