I have this code:
<style>
#div {
height: 100px;
background-color: #A00;
}
.short {
max-height: 0px;
}
</style>
<div id="div" class="short"></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?
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" class="short"></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.