By Aaron J Spetner


2012-01-10 21:51:51 8 Comments

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?

7 comments

@Даниил Пронин 2020-06-03 17:25:28

You can use CSSStyleDeclaration API to do this:

element.style.setProperty('color', 'black')

@0b10011 2012-01-10 22:03:18

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>

@user663031 2012-12-08 03:50:15

This provides no cascading which is sort of the whole point. Better to "borrow" a valid CSS attribute which can take any value and has inheritable behavior.

@Matthew Dean 2015-03-04 22:01:31

"Better to "borrow" a valid CSS attribute which can take any value and has inheritable behavior" - Such as?

@Morten Hornbæk 2017-07-28 11:57:30

"content" would do the trick. It doesn't apply any styles, it cascades and it accepts any value.

@Dave F 2020-06-02 23:10:13

This would be useful for if you want to allow for a custom element to be modified through style sheets. getComputedStyle(your_el)["defined-property"] works well if you want to get CSS defined styles, such as 'color' and 'font'. However, it's great to know that custom properties can be accessed using: getComputedStyle(your_el).getPropertyValue("--my-custom-prop‌​erty")

@M.Adam 2016-04-13 21:08:56

CSS:

:root {
    --custom-property: #000000;
}

Javascript:

var custom_property = window.getComputedStyle(document.body).getPropertyValue('--custom-property').trim()

@Drenai 2017-08-30 17:11:44

Brilliant. Didn't know about the window.getComputedStyle method of accessing these via JS!! Thanks a mill

@TextGeek 2018-01-15 22:30:07

This definitely seems to be the right answer, because most of the alternatives requires changing the document (not just the CSS). However, is seems worth mentioning that (a) custom property names do have to start with hyphens; and (b) such values are inherited, which is why your example can get a root property from body.

@matsko 2015-04-30 23:41:23

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

@Aaron J Spetner 2015-05-01 07:55:27

Interesting, but as this is a (complex, to some) hack and not per spec, I still believe the "correct" answer is to not use CSS for custom properties and to instead use the data attribute. +1 for the tip though - always good to learn a new hack! :)

@yk77500 2012-01-10 22:08:09

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;

}

@Aaron J Spetner 2012-01-10 22:10:37

This is good, but would be prone to error in the event a semicolon was contained within quotes in the style attribute (e.g. as part of a url).

@Sven Bieder 2012-01-10 21:57:05

You can't use data-* attributes (html5)? That would at least be valid and not a strange hack.

@Rob W 2012-01-10 21:56:41

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");

Related Questions

Sponsored Content

17 Answered Questions

[SOLVED] How do I disable the resizable property of a textarea?

  • 2011-03-08 16:15:40
  • user549757
  • 1371906 View
  • 2694 Score
  • 17 Answer
  • Tags:   html css

43 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

63 Answered Questions

[SOLVED] How can I merge properties of two JavaScript objects dynamically?

23 Answered Questions

[SOLVED] Get the current URL with JavaScript?

  • 2009-06-23 19:26:45
  • dougoftheabaci
  • 2863162 View
  • 3045 Score
  • 23 Answer
  • Tags:   javascript url

95 Answered Questions

[SOLVED] How to validate an email address in JavaScript

3 Answered Questions

32 Answered Questions

[SOLVED] How can I change an element&#39;s class with JavaScript?

  • 2008-10-12 20:06:43
  • Nathan Smith
  • 2627643 View
  • 2817 Score
  • 32 Answer
  • Tags:   javascript html dom

39 Answered Questions

[SOLVED] How do you get a timestamp in JavaScript?

32 Answered Questions

[SOLVED] Transitions on the CSS display property

  • 2010-07-25 22:52:49
  • RichardTape
  • 1555650 View
  • 1490 Score
  • 32 Answer
  • Tags:   css css-transitions

Sponsored Content