When working with calc()ulated properties in CSS, is it possible to access their expanded (i.e., actually calculated) values through Javacsript?
For instance, consider the following CSS:
:root {
--ratio: calc(16 / 9);
--width: 100px;
--height: calc(var(--width) / var(--ratio));
}
And Javascript:
const computedStyle = window.getComputedStyle(document.documentElement);
console.info(computedStyle.getPropertyValue('--height'));
One would expect to see 56px being printed; instead, the string "calc(var(--width) / var(--ratio))" is returned.
Even if you try applying it to some CSS class property and reading from the class declaration instead, it won't work:
.rectangle {
height: var(--height);
}
Javascript:
const rectangleClassDeclaration = /* find it through document.styleSheets */
console.info(rectangleClassDeclaration.style.getPropertyValue('height'));
And the console shows "var(--height)".
So, is there a way to access the final, calculated value through Javascript?
One hack that I could think of is applying the value to some DOM element and them reading from it instead.
CSS:
.rectangle {
height: var(--height);
}
HTML:
<div class="rectangle"></div>
Javascript:
const rectangle = document.querySelector('.rectangle');
const computedStyle = window.getComputedStyle(rectangle);
console.info(computedStyle.getPropertyValue('height'));
And then you would see 56px as the result. But this is kinda hacky, so it would be good to find out some way of accessing the variable's computed value directly. It works, anyway.
See my CodePen with working code.
Related
I have the following code:
$(".element").css("background-position","center");
For some reason, it does not create a new attribute in CSS called background-position: center and just adds it to the background property like so:
background: center center rgb(251, 251, 251);
How do I make it so that changing the background-position will result in (like you can do in inspect element or pure css) in Javascript/jQuery:
background-position: center;
That's why sometimes we face compatibility issue among different browsers. Before, they used to be more strict of displaying non valid HTML or CSS. Nowdays, they have more tolerance to non-standard coding but they could also provide unexpected code to force their standards.
What you see is simply the way your browser is rendering your code. I think center center is the default value that the browser uses to distinguish from
center top
center bottom
Besides, Chrome inspector could be the one playing smart sometimes. This is an example of what's been "computed" after clicking the button in the following snippet :
$('#styler').on('click',function(){
$("#element").css({"background-position":"center","background-color": "transparent","background-repeat": "no-repeat","custom":"nonvalid"});
var posTxt = $('#element').css('background-position');
var pos = $('#element').css('backgroundPosition');
console.log('Text: '+posTxt);
console.log('Like Javascript: '+pos);
//It's the same value displayed using pure Javascript
var elem = document.getElementById('element');
var tab = window.getComputedStyle(elem,null).backgroundPosition.trim();
console.log('Javascript: '+tab);
});
/*already used style */
#element{
background-color: rgba(201,76,76);
width:500px;
height:500px;
padding:10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="styler">Change Style</button>
<div id="element">...</div>
[UPDATE] I added a line to this code to show how is jQuery reading the new background position value after setting it to "center". It's being displayed "50% 50%" which is the same value displayed by window.getComputedStyle().
Just to show you that with different methods even jQuery is not displaying the same property name but prefers to retrieve the computed numerical value.
which could be useful for animations, translations...
jQuery also validates those Css Properties before applying them. The code checks for any available custom jQuery.cssHooks (like these), if not it will get ignored.
To conclude, we can't control how these different programs display these properties. I think what matters is how we Set them properly.
Using jQuery to define each Background property could help you get them separated in the Inspector or override existing properties being mixed up with the one you are creating.
You can do it with css variables https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
sample code
const Root = document.documentElement;
var h_Pos = ['center','right','left'] , nPH = 0
, v_Pos = ['center','bottom','top'] , nPV = 0
btH.onclick=_=> { nPH = ++nPH %3; Root.style.setProperty('--PosH', h_Pos[nPH]) }
btV.onclick=_=> { nPV = ++nPV %3; Root.style.setProperty('--PosV', v_Pos[nPV]) }
:root {
--PosH : center;
--PosV : center;
}
html {
height: 100%;
background: orange no-repeat var(--PosH) var(--PosV) url(https://i.picsum.photos/id/926/200/200.jpg);
}
<button id="btH"> change horizontal Position</button>
<button id="btV"> change vertical Position</button>
Got another basic question that I couldn't seem to find the answer for online. I can change the CSS property of an element easily using javascript,
document.getElementById("ExampleID").style.height="30px";
however whenever I try printing a property to the console, with
console.log(document.getElementById("ExampleID").style.height);
it prints a blank line instead of the property. How can I print a style property value of the desired element? Thank you very much
You can use getComputedStyle
let elem = document.getElementById('test');
let ht = window.getComputedStyle(elem, null).getPropertyValue("height");
console.log(ht)
.test {
height: 300px;
width: 300px;
border: 1px solid red;
}
<div class="test" id="test">Test</div>
Make sure you are testing with an actual element that will be returned from your selection (see example below). Otherwise your code is fine.
const elem = document.getElementById('elemId');
elem.style.height = '30px';
console.log(elem.style.height);
<div id="elemId"></div>
document.getElementById("ExampleID").style.height="30px";
console.log(document.getElementById('ExampleID').clientHeight);
console.log(document.getElementById('ExampleID').offsetHeight);
<div id="ExampleID">
clientHeight includes padding.<br>
offsetHeight includes padding, scrollBar and borders.
</div>
clientHeight includes padding.
offsetHeight includes padding, scrollBar and borders.
You need to check HTML part in this case.
If you are setting from javascript then Your code is working fine.
In case Styles defined in CSS use window.getComputedStyle()
The window.getComputedStyle() method returns an object that reports 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 simply indexing with CSS property names.
Here is working snippet:
var divEle=document.getElementById("ExampleID");
console.log("Before:height::"+divEle.style.height);
console.log("Before:color::"+divEle.style.color);
var heightCss = window.getComputedStyle(divEle, null).getPropertyValue("height");
var colorCss = window.getComputedStyle(divEle, null).getPropertyValue("color");
console.log("Before:height from css::"+heightCss)
console.log("Before:color from css::"+colorCss)
function changeCss(){
divEle.style.height="30px";
divEle.style.color="blue";
console.log("After:height::"+divEle.style.height);
console.log("After:color::"+divEle.style.color);
}
.divClass {
height: 40px;
color: red;
width: 40px;
border: 2px solid black;
}
<div class="divClass" id="ExampleID">test</div><div><input type="button" onClick="changeCss();" value="Change Css"/></div>
It was my understanding that [some elem].style.maginTop would return a string with the element's top margin.
Instead, I'm always getting a blank string. I want to use this with the body, but I also tried on a div, and that didn't work either.
console.log(document.body.style.marginTop); // logs ""
console.log(typeof(document.body.style.marginTop)); // logs "String"
var elem = document.getElementById("testDiv");
console.log(elem.style.marginTop); // logs ""
body {
margin-top:100px;
}
#testDiv {
margin-top:50px;
}
hi!
<div id="testDiv">test</div>
I'm not sure what I'm doing wrong... Does anybody have a non-jQuery solution to this?
The HTMLElement.style only returns inline styles:
The HTMLElement.style property returns a CSSStyleDeclaration object that represents the element's style attribute.
To access the styles from stylesheets use Window.getComputedStyle(element):
The Window.getComputedStyle() method gives the values of all the CSS properties of an element after applying the active stylesheets and resolving any basic computation those values may contain.
var elem = document.getElementById("testDiv");
var style = window.getComputedStyle(elem);
//output
document.body.innerHTML = style.marginTop;
body {
margin-top:100px;
}
#testDiv {
margin-top:50px;
}
hi!
<div id="testDiv">test</div>
You can use getComputedStyle and getPropertyValue to get top margin.
console.log(document.body.style.marginTop); // logs ""
console.log(typeof(document.body.style.marginTop)); // logs "String"
var elem = document.getElementById("testDiv");
//console.log(elem.style.marginTop); // logs ""
console.log(getComputedStyle(elem).getPropertyValue("margin-top"));
alert(getComputedStyle(elem).getPropertyValue("margin-top"));
body {
margin-top:100px;
}
#testDiv {
margin-top:50px;
}
hi!
<div id="testDiv">test</div>
Tested and working.
I don't know why, but I got it working by implicitly assigning the margin-top by JS first. I know why my answer works (it's been over 2 years so I better know why). By setting the values of div#test and body to 50px and
100px like this:
document.getElementById("testDiv").style.marginTop = '50px';
document.body.style.marginTop = '100px';
I'm actually setting the CSS property/value of the elements inline:
<body style='margin-top: 100px'>
<div id='testDiv' style='margin-top: 50px'>test</div>
</body>
Whenever the .style property is used, the CSS property/value that follows it is always inline. One important thing to remember about inline CSS styles is that they have a higher priority than the other 2 means of CSS Declaration: external stylesheets (ex. <link href="file.css"...) and inline stylesheet (ex. <style>...</style>). The only way to override an inline style is to use !important (unless of course the inline style has !important as well.)
So if the.style property is used to read a property/value of an element, it'll only return the inline style value if it actually exists which in OP's case it never did and in my case it did because I used .style to assign the property/values. While my solution is correct, the answers by Nicolo and Mr. Karlsson are better since you'll get the values from all CSS stylesheets.
document.getElementById("testDiv").style.marginTop = '50px';
document.body.style.marginTop = '100px';
console.log(document.getElementById("testDiv").style.marginTop);
console.log(document.body.style.marginTop);
body {
margin-top: 100px;
}
#testDiv {
margin-top: 50px;
}
hi!
<div id="testDiv">test</div>
Hm, I tried it as well with the same result as you did. A quick google search turned up Using JavaScript to read html / body tag margin-top which uses style.getPropertyValue() to return the information you're looking for.
instead of using core javascript, let you use js library jQuery. Then use this syntaxt to get its value.:
console.log($('body').css('margin-top'));
for pure javascript use this
var element = document.body,
style = window.getComputedStyle(element),
margin_top = style.getPropertyValue('margin-top');
console.log(margin_top);
http://jsfiddle.net/hAw53/726/
This question already has answers here:
Get a CSS value from external style sheet with Javascript/jQuery
(5 answers)
Closed 9 years ago.
I am trying to access css property like this:
.box {
position: absolute;
background-color: red;
height: 10px;
width: 10px;
}
JS:
var height = $('.box').css('height');
I know, the above code is wrong and this actually doesn't work as .box is not available in the DOM.
Another thing that i tried:
var height = $("<span class='box'></span>").css('height');
My question is: how can I get the height of .box without having any element in the DOM with class box ?
On a modern browser you could use document.stylesheets, and the stylesheet would need to be in the original HTML and the source needs to match the Same Origin Policy, i.e. you can't inject the stylesheet from say a Chrome extension as it does not show in document.stylesheets
CSS
.box {
position:absolute;
background-color:red;
height:10px;
width:10px;
}
Javascript
function propertyFromStylesheet(selector, attribute) {
var value;
[].some.call(document.styleSheets, function (sheet) {
return [].some.call(sheet.rules, function (rule) {
if (selector === rule.selectorText) {
return [].some.call(rule.style, function (style) {
if (attribute === style) {
value = rule.style.getPropertyValue(attribute);
return true;
}
return false;
});
}
return false;
});
});
return value;
}
console.log(propertyFromStylesheet(".box", "height"));
Output
10px
On jsfiddle
The only way you can get then without using a DOM element is by downloading the stylesheet and parsing the contents. You can also access the compiled stylesheet by going to document.stylesheets and finding the rule. You can also use window.getComputedStyle(element) and create an element such as document.createElement('div') and attach the '.box' className to it.
Keep in mind that doing any of this implies that the stylesheet is on the same domain and port of where your html file is.
To get the computed height of an element as set in a stylesheet, it has to exists in the DOM. You solve this by creating an element, positioning it way off the visible screen, and appending it to the body (or anywhere really).
To get the height you can use .height(), or .innerHeight() to get the height without margins and borders, but including padding :
var elem = $('<span />', {'class':'box',
style:'position:fixed;top:-9999px'}).appendTo('body');
var height = elem.innerHeight();
elem.remove();
FIDDLE
There's usually no need to access and parse the stylesheet for this, except in really special cases, where you're not looking for something like an elements height, but for instance trying to check if some special style is set in a specific stylesheet etc.
If I have:
#em {
opacity:0.5;
}
How do I get #em's opacity using javascript? :D
I've got troubles with the following (it returns nothing):
return document.getElementById("em").style.opacity;
var em = document.getElementById("em");
var temp = window.getComputedStyle(em).getPropertyValue("opacity");
Now, the variable temp will have the value of opacity of "em".
Setting a CSS value in a stylesheet is not the same as setting it through the style property. You need to look at the getComputedStyle method to obtain this (and also currentStyle for older IE).
document.getElementById("em").style.opacity;
it will work fine if you use inline style .eg.
<div id="em" style="width: 50px; height: 50px; opacity: 0.5;">