Home > database >  getComputedStyle: how to get the height defined on CSS instead of the actual rendered height?
getComputedStyle: how to get the height defined on CSS instead of the actual rendered height?

Time:11-16

I have this code:

<style>

    #div {
        height: 100px;
        background-color: #A00;
    }

    .short {
        max-height: 0px;
    }
</style>

<div id="div" ></div>

<script>

    var div = document.getElementById("div");
    var computed = window.getComputedStyle(div);
    console.log(computed.height); //... I expected 100px instead of the value for max-height definition.

</script>

I know that the max-height limits the height, but how do I get the "height" definition instead of the rendered value?

CodePudding user response:

We can read the CSS stylesheet rules of the document (document.styleSheets, see MDN) and extract rules with the selector text of #div and then use the first height value. The first item should be the highest prioritized style.

We iterate through all of the styles until we get a result that isn't an empty string, otherwise the function could break in the sense that another #div style without a height property would still be prioritized over a previously defined #div style with a height property.

Using the function provided at: https://stackoverflow.com/a/22638396/20073186

function css(el) {
    var sheets = document.styleSheets, ret = [];
    el.matches = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector 
        || el.msMatchesSelector || el.oMatchesSelector;
    for (var i in sheets) {
        var rules = sheets[i].rules || sheets[i].cssRules;
        for (var r in rules) {
            if (el.matches(rules[r].selectorText)) {
                ret.push(rules[r]);
            }
        }
    }
    return ret;
}

We can look specifically for the #div styling, and if we can't find it (or a height value), use the computed styling:

function getStylesheetHeight(element, selectorText) {
    const rules = css(element);
    const selectorRules = rules.filter((rule) => rule.selectorText == selectorText);

    let height = null;

    for(let index = 0; index < selectorRules.length; index  ) {
        if(!selectorRules[index].style.height.length)
            continue;

        height = selectorRules[index].style.height;

        break;
    }

    return height ?? element.style.height;
};

And use it as such:

const element = document.getElementById("div");

function css(el) {
    var sheets = document.styleSheets, ret = [];
    el.matches = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector 
        || el.msMatchesSelector || el.oMatchesSelector;
    for (var i in sheets) {
        var rules = sheets[i].rules || sheets[i].cssRules;
        for (var r in rules) {
            if (el.matches(rules[r].selectorText)) {
                ret.push(rules[r]);
            }
        }
    }
    return ret;
};

function getStylesheetHeight(element, selectorText) {
    const rules = css(element);
    const selectorRules = rules.filter((rule) => rule.selectorText == selectorText);

    let height = null;

    for(let index = 0; index < selectorRules.length; index  ) {
        if(!selectorRules[index].style.height.length)
            continue;

        height = selectorRules[index].style.height;

        break;
    }

    return height ?? element.style.height;
};

console.log(getStylesheetHeight(element, "#div"));
#div {
    height: 100px;
    background-color: #A00;
}

.short {
    max-height: 0px;
}
<div id="div" ></div>

It's important to note that if the selector text would e.g. be body #div, then it would go uncaught by this function. You could work around this by replacing rules.filter((rule) => rule.selectorText == selectorText) with rules.filter((rule) => rule.selectorText.endsWith(selectorText)) but this could potentionally be misleading.

  • Related