I am looking for a way to retrieve the style from an element that has a style set upon it by the style tag.
<style>
#box {width: 100px;}
</style>
In the body
<div id="box"></div>
I'm looking for straight javascript without the use of libraries.
I tried the following, but keep receiving blanks:
alert (document.getElementById("box").style.width);
alert (document.getElementById("box").style.getPropertyValue("width"));
I noticed that I'm only able to use the above if I have set the style using javascript, but unable to with the style tags.
The element.style property lets you know only the CSS properties that were defined as inline in that element (programmatically, or defined in the style attribute of the element), you should get the computed style.
Is not so easy to do it in a cross-browser way, IE has its own way, through the element.currentStyle property, and the DOM Level 2 standard way, implemented by other browsers is through the document.defaultView.getComputedStyle method.
The two ways have differences, for example, the IE element.currentStyle property expect that you access the CCS property names composed of two or more words in camelCase (e.g. maxHeight, fontSize, backgroundColor, etc), the standard way expects the properties with the words separated with dashes (e.g. max-height, font-size, background-color, etc).
Also, the IE element.currentStyle will return all the sizes in the unit that they were specified, (e.g. 12pt, 50%, 5em), the standard way will compute the actual size in pixels always.
I made some time ago a cross-browser function that allows you to get the computed styles in a cross-browser way:
function getStyle(el, styleProp) {
var value, defaultView = (el.ownerDocument || document).defaultView;
// W3C standard way:
if (defaultView && defaultView.getComputedStyle) {
// sanitize property name to css notation
// (hypen separated words eg. font-Size)
styleProp = styleProp.replace(/([A-Z])/g, "-$1").toLowerCase();
return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
} else if (el.currentStyle) { // IE
// sanitize property name to camelCase
styleProp = styleProp.replace(/\-(\w)/g, function(str, letter) {
return letter.toUpperCase();
});
value = el.currentStyle[styleProp];
// convert other units to pixels on IE
if (/^\d+(em|pt|%|ex)?$/i.test(value)) {
return (function(value) {
var oldLeft = el.style.left, oldRsLeft = el.runtimeStyle.left;
el.runtimeStyle.left = el.currentStyle.left;
el.style.left = value || 0;
value = el.style.pixelLeft + "px";
el.style.left = oldLeft;
el.runtimeStyle.left = oldRsLeft;
return value;
})(value);
}
return value;
}
}
The above function is not perfect for some cases, for example for colors, the standard method will return colors in the rgb(...) notation, on IE they will return them as they were defined.
I'm currently working on an article in the subject, you can follow the changes I make to this function here.
I believe you are now able to use Window.getComputedStyle()
Documentation MDN
var style = window.getComputedStyle(element[, pseudoElt]);
Example to get width of an element:
window.getComputedStyle(document.querySelector('#mainbar')).width
In jQuery, you can do alert($("#theid").css("width")).
-- if you haven't taken a look at jQuery, I highly recommend it; it makes many simple javascript tasks effortless.
Update
for the record, this post is 5 years old. The web has developed, moved on, etc. There are ways to do this with Plain Old Javascript, which is better.
Use getComputedStyle function, Computed style contains all the CSS properties set to an element. Even if do not set a property to an element. You will still find that property in the computed styles.
Example:
<style>
#Body_element {
color: green;
}
</style>
<body id="Body_element">
<script>
alert(getComputedStyle(Body_element).color)
</script>
</body>
This is a helper function if you want to get multiple style rules from the same element.
You pass it the element and the styles you want as arguments, and it will return their values
const convertRestArgsIntoStylesArr = ([...args]) => {
return args.slice(1);
}
const getStyles = function () {
const args = [...arguments];
const [element] = args;
let stylesProps = [...args][1] instanceof Array ? args[1] : convertRestArgsIntoStylesArr(args);
const styles = window.getComputedStyle(element);
const stylesObj = stylesProps.reduce((acc, v) => {
acc[v] = styles.getPropertyValue(v);
return acc;
}, {});
return stylesObj;
};
Now, you can use this function like this:
const styles = getStyles(document.body, "height", "width");
OR
const styles = getStyles(document.body, ["height", "width"]);
Related
Given
<div></div>
<style>
body {
--var1: 3;
--var2: var(--var1);
}
div {
--var3: var(--var2);
width: var(--var3);
}
</style>
How can I obtain the reference list of css variables?
getReferenceList(divElement, 'width')
Would result in
['--var3', '--var2', '--var1', 3]
If you already know the property name, you can use getComputedStyle. For instance,
window.getComputedStyle(document.querySelector('body')).getPropertyValue('--var1');
This will return 3.
If you would like to get a list of all stylesheets, you can use CSSStyleSheet.cssRules.
The following example will give you the stylesheet of body:
document.styleSheets[0].cssRules[0].cssText
So the result of it will be "body { --var1: 3; --var2: var(--var1); }".
In your case, cssRules[0] = body and cssRules[1] = div.
You can also use selectorText to find out what tag it is. In this case document.styleSheets[0].cssRules[0].selectorText will return the string body.
If you prefer an array of properties and values, instead of a string, you can use this regex:
const regex = /(?<={)[ -a-zA-Z0-9\S][^}]+/gm
const str = document.styleSheets[0].cssRules[0].cssText.match(regex);
console.log(str[0].split(';'));
I want to convert my node style attribute value to a js object which contains all the CSS properties and its values.
Style attribute value
background-image:url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLEhYLDhAVDhkVDhEQFhUYFxMZGBYVFhUdKysjHR0oHR0WJDUlKC0vMjIyGSI4PTcwPCsxMi8BCgsLDg0OHBAQHDsoIh0vLy87Ozs7Oy87LzsvLy8vNS8vLy8vLzUvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL//AABEIABAAGAMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAADBQEEBwD/xAAeEAABBAIDAQAAAAAAAAAAAAAAAQIDIQQSExQxEf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAv/EABoRAAICAwAAAAAAAAAAAAAAAAECACEDETH/2gAMAwEAAhEDEQA/ANTbnMkpAvZaxLE2DGv30uzsXQlU7E0UyrTdhJc1rqOFnGuxIqioZGaf/9k=);background-color:#00cc7e;background-size:cover;opacity:1;transition:opacity 500ms 500ms;position:absolute;left:0;top:0;width:100%;height:100%
Convert it to JS Object
{
backgroundImage: url(data;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLEhYLDhAVDhkVDhEQFhUYFxMZGBYVFhUdKysjHR0oHR0WJDUlKC0vMjIyGSI4PTcwPCsxMi8BCgsLDg0OHBAQHDsoIh0vLy87Ozs7Oy87LzsvLy8vNS8vLy8vLzUvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL//AABEIABAAGAMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAADBQEEBwD/xAAeEAABBAIDAQAAAAAAAAAAAAAAAQIDIQQSExQxEf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAv/EABoRAAICAwAAAAAAAAAAAAAAAAECACEDETH/2gAMAwEAAhEDEQA/ANTbnMkpAvZaxLE2DGv30uzsXQlU7E0UyrTdhJc1rqOFnGuxIqioZGaf/9k=): undefined;
backgroundColor: #00cc7e;
backgroundSize: cover;
opacity: 1;
transition: opacity 500ms 500ms;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%
}
Any helpful answer will be appreciated.
You can try methods of CSSStyleDeclaration.
Here getStyles is of type CSSStyleDeclaration which will give list of inline style properties.
const getStyles = document.getElementById('img').style;
const properties = Array.from(getStyles).reduce((acc, curr) => {
acc[curr] = getStyles.getPropertyValue(curr)
return acc;
}, {})
console.log(properties)
<img id='img' style="background-image:url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLEhYLDhAVDhkVDhEQFhUYFxMZGBYVFhUdKysjHR0oHR0WJDUlKC0vMjIyGSI4PTcwPCsxMi8BCgsLDg0OHBAQHDsoIh0vLy87Ozs7Oy87LzsvLy8vNS8vLy8vLzUvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL//AABEIABAAGAMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAADBQEEBwD/xAAeEAABBAIDAQAAAAAAAAAAAAAAAQIDIQQSExQxEf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAv/EABoRAAICAwAAAAAAAAAAAAAAAAECACEDETH/2gAMAwEAAhEDEQA/ANTbnMkpAvZaxLE2DGv30uzsXQlU7E0UyrTdhJc1rqOFnGuxIqioZGaf/9k=);background-color:#00cc7e;background-size:cover;opacity:1;transition:opacity 500ms 500ms;position:absolute;left:0;top:0;width:100%;height:100%">
Well you can definitely do that by:
let element = document.querySelector("your-selector-here")
console.log(element.style)
But let me warn you that you'll get a very big object of css properties because your element has more css properties than what you define in you style-sheet.
Why you wanna do so ?
If its style of an element you can grab it by first selecting the element in your js and then getting style using element.style ,you can slect element by various methods such as by its ID, class etc. Tho this will give you all the element's style including the default one's.
console.log(document.querySelector('#test').style)
<div id="test"></div>
This shall be used in worst case scenario until you can filter the default one's.
If you have the style as a sting with you, and you want to convert it to object, you can use JSON.parse ,but before that you will have to convert you styles into object format, replace ';' with ',' and convert each individual key and value to string. This might not be easy.
const test = 'background-color:#00cc7e;background-size:cover;opacity:1;transition:opacity 500ms 500ms;position:absolute;left:0;top:0;width:100%;height:100%';
var afterReplace = test.replaceAll(";", '","').replaceAll(":", '":"');
objectForm = JSON.parse('{"' + afterReplace + '"}')
console.log(objectForm)
Here add string value of the style in test from which we replace all ';' to '";"' and ':' to '":"' then we add {" and "} to both start and end, and finally parse it into a json object.
Though I would suggest you not to use it.
This answer is incorrect but I thought it was important to leave here. While it works fine in Chrome, it doesn't work in Firefox, where the CSS2Properties object they return don't have enumerable property.
This method goes through the computed style of the element, so it has some browser-specific values. element.style has all possible style attributes, so this filters out the empty ones and returns the balance as a javascript notation style object
let element = document.querySelector('#element');
let styleobj = Object.fromEntries(Object
.entries(element.style)
.filter(e => isNaN(e[0]) && e[1].trim())
)
let element = document.querySelector('#element');
let styleobj = Object.fromEntries(Object.entries(element.style).filter(e => isNaN(e[0]) && e[1].trim()))
console.log(styleobj)
<div id='element' style='background-image:url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLEhYLDhAVDhkVDhEQFhUYFxMZGBYVFhUdKysjHR0oHR0WJDUlKC0vMjIyGSI4PTcwPCsxMi8BCgsLDg0OHBAQHDsoIh0vLy87Ozs7Oy87LzsvLy8vNS8vLy8vLzUvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL//AABEIABAAGAMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAADBQEEBwD/xAAeEAABBAIDAQAAAAAAAAAAAAAAAQIDIQQSExQxEf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAv/EABoRAAICAwAAAAAAAAAAAAAAAAECACEDETH/2gAMAwEAAhEDEQA/ANTbnMkpAvZaxLE2DGv30uzsXQlU7E0UyrTdhJc1rqOFnGuxIqioZGaf/9k=);background-color:#00cc7e;background-size:cover;opacity:1;transition:opacity 500ms 500ms;position:absolute;left:0;top:0;width:100%;height:100%'></div>
I have some code:
$("#" + this.id).css("border-radius",this.radius + "px");
$("#" + this.id).css("-moz-border-radius",this.radius + "px");
$("#" + this.id).css("-webkit-border-radius",this.radius + "px");
I am trying to improve lines like this by using JSON to apply them (as shown in jQuery's docs) or by removing the vendor prefix versions completely.
Does jQuery's .css() method automatically apply any required vendor prefixes when changing CSS properties on an element?
As #zeroflagL wrote it appears that since jQuery 1.8.0 .css() does add browser specific prefixes (see this).
In earlier versions this is not done automatically by jQuery's .css(). You will have to do it by yourself or you can use jQuery's .cssHooks() to add vendor prefixes.
Code example from here:
(function($) {
if ( !$.cssHooks ) {
throw("jQuery 1.4.3+ is needed for this plugin to work");
return;
}
function styleSupport( prop ) {
var vendorProp, supportedProp,
capProp = prop.charAt(0).toUpperCase() + prop.slice(1),
prefixes = [ "Moz", "Webkit", "O", "ms" ],
div = document.createElement( "div" );
if ( prop in div.style ) {
supportedProp = prop;
} else {
for ( var i = 0; i < prefixes.length; i++ ) {
vendorProp = prefixes[i] + capProp;
if ( vendorProp in div.style ) {
supportedProp = vendorProp;
break;
}
}
}
div = null;
$.support[ prop ] = supportedProp
return supportedProp;
}
// check for style support of your property
// TODO by user: swap out myCssPropName for css property
var myCssPropName = styleSupport("myCssPropName");
// set cssHooks only for browsers that
// support a vendor-prefixed border radius
if (myCssPropName && myCssPropName !== 'myCssPropName') {
$.cssHooks["myCssPropName"] = {
get: function(elem, computed, extra) {
// handle getting the CSS property
return $.css(elem, myCssPropName);
},
set: function(elem, value) {
// handle setting the CSS value
elem.style[myCssPropName] = value;
}
};
}
})(jQuery);
jQuery DOES add vendor prefixes. It first checks for the presence of the standard property and if it's not found for a vendor prefixed version. From the source:
// return a css property mapped to a potentially vendor prefixed property
function vendorPropName( style, name ) {
// shortcut for names that are not vendor prefixed
if ( name in style ) {
return name;
}
// check for vendor prefixed names
...
I don't know since which version, but I think 1.8.
This is now confirmed in the official docs: http://api.jquery.com/css/
Setter ( .css( propertyName, value ) )
As of jQuery 1.8, the .css() setter will automatically take care of prefixing the property name. For example, take .css( "user-select", "none" ) in Chrome/Safari will set it as -webkit-user-select, Firefox will use -moz-user-select, and IE10 will use -ms-user-select.
Getter ( .css( propertyName ) )
The .css() method is a convenient way to get a computed style property from the first matched element, especially in light of the different ways browsers access most of those properties (the getComputedStyle() method in standards-based browsers versus the currentStyle and runtimeStyle properties in Internet Explorer prior to version 9) and the different terms browsers use for certain properties. For example, Internet Explorer's DOM implementation refers to the float property as styleFloat, while W3C standards-compliant browsers refer to it as cssFloat. For consistency, you can simply use "float", and jQuery will translate it to the correct value for each browser.
It doesn't explicitly mention vendor prefixes in the getter context but it's easy to test. For example, $element.css('border-radius') on Chrome returns values set as border-radius or -webkit-border-radius and ignores values set as -moz-border-radius.
Just keep in mind that it's inconsistent across browsers for shorthand properties:
Retrieval of shorthand CSS properties (e.g., margin, background, border), although functional with some browsers, is not guaranteed. For example, if you want to retrieve the rendered border-width, use: $( elem ).css( "borderTopWidth" ), $( elem ).css( "borderBottomWidth" ), and so on.
Let us explain the question with an example. I have a text box. The textbox (every textbox) has a property called 'value'. I want to over ride that textbox.value and comeup with and
new thing. When the text in textbox is 'ranjan' then the textbox.VALUE property returns 'ranjan'. Now I want to thus overwrite this so that when you type textbox.VALUE you get a different thing say for example, RaNjAn or say, Mr. Ranjan or whatever.
We can over ride methods using Object.PROTOTYPE property. But how can we do it for non-function objects inside object for example the 'value' property in this case.
If i need to make the question more clear, please mention.
Regards - Ranjan.
You can define custom properties for your element using Object.defineProperty
If you have a case where you need to get the value of an element as Mr. <value> for example, then this approach will be useful. Overriding standard properties may not be such a good idea.
Demo: http://jsfiddle.net/zvCGw/2/
Code:
var foo = document.getElementById('foo');
Object.defineProperty(foo, "xvalue", {
get: function() {
return 'Mr. ' + foo.value;
},
set: function(_newValue) {
foo.value = _newValue;
}
});
foo.xvalue = 'Hello';
alert(foo.xvalue);
What you are trying to do is called type augmentation. In javscript there are types of things, such as the object type, array type, etc.
You can use the prototype to augment these built in types, for example, adding a new method that can be called on any object that is of the type array:
Array.prototype.myNewMethod = function() {
//the method logic
}
Then you can call your method on any array:
[0,1,2].myNewMethod();
There is no INPUT type in JavaScript, DOM elements are classed as Objects. But you could jerry-rig something together that kind of does what you need, like this
Object.prototype.changeValue = function(el) {
if (el.tagName === "INPUT") {
return "Mr " + el.value;
}
}
var testEl = document.getElementById("test");
document.write(testEl.changeValue(testEl))
Used in conjunction with this textbox:
<input id="test" value="Dan" />
You would then get the output 'Mr Dan'
However, this is not great, it's just to illustrate the point and is just something to get you started...
I made a fiddle so you can play around with it
You can redeclare value but it will do no good ;)
This example would do that if test is a textbox
var input = document.getElementById("test");
Object.defineProperty(input, "value", {
get : function () {
return "'" + this["value"] + "'";
},
set : function (val) {
this["value"] = val;
}
});
input.value = "Hello World";
alert(input.value);
Unfortunately, "this.value" will reference the getter causing infinite recursion.
Once redefined, the original value will no longer exist so you will have crippled the element object.
At least as far as I have been able to test.
If the property you're trying to override can also be represented by an HTML attribute (e.g. an input's value), then you can use getAttribute and setAttribute.
Object.defineProperty(myInputElement, 'value', {
get: function () {
return myInputElement.getAttribute('value');
},
set: function (value) {
myInputElement.setAttribute('value', value);
}
});
Note, however, that this override itself cannot be overridden without re-implementing it.
In an application where certain elements have custom CSS properties, is there any way to retrieve such a value via JavaScript?
e.g.
<div id="myDiv" style="color:#f00;-my-custom-property:upsidedown;" />
I can access the color attribute via these two methods:
document.getElementById('myDiv').style.getPropertyValue("color")
document.getElementById('myDiv').style.color
But these do not work for custom properties. Is this supported at all?
CSS values not understood by the browser are discarded, which explains why -my-custom-property was unavailable via .style.
In the past, you would have had to rely on storing the data with data attributes and dealing with inheritance yourself via JavaScript.
However, "custom properties", aka "CSS variables", have since been introduced into the standard and implemented by browsers, with ~92% support globally as of 2019-05-09. At a quick glance, Edge seems to have been the last major browser to implement, with version 16 on October 16, 2017.
Essentially, you need to set a custom property (eg, --my-custom-property: 'foobar';) on an element, and it can be accessed with something like getComputedStyle(your_el).getPropertyValue("--my-custom-property") which would return 'foobar' (with a leading space). Note the leading space and quotation marks. It will return the value exactly as it was provided.
Example:
console.log(getComputedStyle(document.getElementById("a")).getPropertyValue("--my-custom-property-1"))
console.log(getComputedStyle(document.getElementById("b")).getPropertyValue("--my-custom-property-2"))
#b-div { --my-custom-property-2: 'world' }
<div style="--my-custom-property-1: 'hello'"><h1 id="a">#a 'hello'</h1></div>
<div id="b-div"><h1 id="b">#b 'world'</h1></div>
Here's some testing using one and two leading hyphens, inheritance, and different methods of retrieving the value:
function log(computed, selector, prop, value) {
let method = computed ? "getComputedStyle(el)" : "el.style"
let method_id = computed ? "computed" : "raw"
// Build first level of list (tag name)
let first = document.querySelector("#" + selector)
if (!first) {
first = document.createElement("li")
first.appendChild(document.createTextNode(selector))
first.setAttribute("id", selector)
first.appendChild(document.createElement("ul"))
document.querySelector("ul").appendChild(first)
}
// Build second level of list (method of style retrieval)
let second = document.querySelector("#" + selector + "-" + method_id)
if (!second) {
second = document.createElement("li")
second.appendChild(document.createTextNode(method))
second.setAttribute("id", selector + "-" + method_id)
second.appendChild(document.createElement("ul"))
first.querySelector("ul").appendChild(second)
}
// Build third level of list (property accessed)
let third = document.querySelector("#" + selector + "-prop" + prop)
if (!third) {
third = document.createElement("li")
third.appendChild(document.createTextNode(prop + ": `" + value + "`"))
third.setAttribute("id", "prop" + prop)
second.querySelector("ul").appendChild(third)
if (value === "") {
third.classList.add("bad")
} else {
third.classList.add("good")
}
}
}
// Uses .style
function getStyleAttr(selector, prop) {
let value = document.querySelector(selector).style.getPropertyValue(prop)
log(false, selector, prop, value)
}
// Uses getComputedStyle()
function getStyleComputed(selector, prop) {
let value = getComputedStyle(document.querySelector(selector)).getPropertyValue(prop)
log(true, selector, prop, value)
}
// Loop through each property for each element and output the value
let selectors = ["article", "h1", "p"]
let props = ["--my-custom-property", "-my-custom-property"]
selectors.forEach(function(selector) {
props.forEach(function(prop) {
getStyleAttr(selector, prop)
getStyleComputed(selector, prop)
})
})
code {
background: #eee;
padding: .2em;
}
.bad {
color: #800;
}
.good {
color: #080;
}
<article class="custom-prop-inheritance" style="--my-custom-property: 'foobar'; -my-custom-property: 'foobar'">
<h1>Title</h1>
<p>Custom properties require two leading hyphens (<code>-my-custom-property</code> <em>never</em> works). Using <code>el.style</code> does not support inheritance. To support both inheritance and custom properties, you must use <code>getComputedStyle(<b>el</b>)</code> along with two leading hyphens on the custom property (eg, <code>--my-custom-property</code>).</p>
</article>
<ul></ul>
CSS:
:root {
--custom-property: #000000;
}
Javascript:
var custom_property = window.getComputedStyle(document.body).getPropertyValue('--custom-property').trim()
Non-recognised CSS properties will be ignored when put within the style attribute, or in the style.cssText property.
If you want to define a property at a specific element, I recommend data-attributes:
HTML:
<div id="myDiv" style="color:#f00;" data-custom-property="upsidedown" />
JavaScript:
//jQuery's method to retrieve value:
$("#myDiv").data("custom-property");
//jQuery, without parsing:
$("#myDiv").attr("data-custom-property");
// Modern browsers, native JS:
document.getElementById("myDiv").dataset["custom-property"];
// Older browsers, native JS:
document.getElementById("myDiv").getAttribute("data-custom-property");
This is actually now possible for all browsers using a specialized CSS hack via the CSS content tag. This article explains how to do it:
http://www.yearofmoo.com/2015/04/cross-browser-custom-css-properties.html
function getCustomCssProperty(elementID, propertyName){
var style = document.getElementById(elementID).getAttribute("style");
var entries = style.split(";");
for (var i=0; i<entries.length; i++){
var entry = entries[i].split(":");
if(entry[0] == propertyName){
return entry[1];
}
}
return null;
}
You can't use data-* attributes (html5)?
That would at least be valid and not a strange hack.