Get an Element's Applied Styles

By Rob Gravelle

WEBINAR: On-demand webcast

How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017 REGISTER >

In order for browsers to render an element, they compile all CSS rules — possibly from different stylesheet files, STYLE blocks, as well as inline style — and apply them to the element. This is what you see with Firebug or the WebKit Inspector: the full CSS inheritance tree for an element. Of course, these may be overridden at runtime using JavaScript, but doing so often requires being able to determine what rules are being applied at any given moment, especially in the case of media queries. In today's article, we'll be using one of Erhan Karakaya's MeJsX JavaScript Extension Functions to retrieve an element's applied styles as defined in a variety of CSS rules.

Goodbye to getMatchedCSSRules()

It was not so long ago that Chrome had a function called getMatchedCSSRules() that did pretty much what this article describes. Sadly, it was deprecated in 2014 and has not seen the light of day since. Here's a thread with more details.

Regardless of getMatchedCSSRules's fate, we would still need to come up with a cross-browser solution.

Introducing the getCustomCssRulesOnElement() Function

I wrote a basic function for the Customizing Bootstrap Modals article that determined the applied CSS on a dialog's width. The search for a better and more flexible function lead me to Erhan Karakaya's getCustomCssRulesOnElement() function, which is part of his MeJsX JavaScript Extension Functions library. This function is useful for accessing CSS style rules applied by the document at the time that the function is invoked. It includes rules from internal & external stylesheets, as well as from the inline style attribute. The elements' default CSS properties are not reported. The function then returns an array of elementRules, each having the following three properties:

  • elementRule.order => Ordering number of the rule
  • elementRule.content => CSS content
  • elementRule.media => Media query

Rules are sorted in this order:

  1. External stylesheets, load order into the document
  2. Internal styles, written order in the document
  3. Style attributes on the element

Invoking the Function

The getCustomCssRulesOnElement() is a static method of the global MEJSX object. Therefore, you have to prefix the function with that namespace in order to use it. That's a standard practice of third-party libraries that avoids the possibility of clobbering existing global functions.

I recommend referencing the element using the getElementById() function because it only ever returns one element. Passing a NodeList to getCustomCssRulesOnElement() will result in an "Invalid object type" error.

The following code fetches the CSS rules on an element with an ID of "lorem":

var $lorem = document.getElementById('lorem');
var rules  = MEJSX.getCustomCssRulesOnElement($lorem);

Before we get to the output of the function, it might be useful to examine the document CSS:

p { color: #cccccc; }
 
#lorem { font-weight: bold; }

@media (min-width: 300px), (min-device-width: 350px) {
  p { margin: 0; }
  #lorem { border: 1px solid #000000; }
  h1 { color: #000000; }
}

@media (max-width: 600px) {
  #lorem { border: 1px solid #000000; }
}

Notice the inclusion of the "max-width: 600px" media query. Since I am running the code on a desktop, we should expect this rule to be omitted from the results.

There are also some inline styles on the element that need to be considered:

<p id="lorem" style="line-height: 20px;">
    Lorem ipsum dolor sit amet...
</p>

Here is the resulting array of elementRules. These are sorted from most generalized to most specific (the order property). The inline rule(s) may be identified by the "style" prefix:

[
  0: {
     content: "p { color: rgb(204, 204, 204); }",
     media: "all",
     order: 0
  },
  1: {
     content: "#lorem { font-weight: bold; }",
     media: "all",
     order: 1
  },
  2: {
     content: "p { margin: 0px; }",
     media: "all and (min-width:300px), all and (min-device-width:350px)",
     order: 2
  },
  3: {
     content: "#lorem { border: 1px solid rgb(0, 0, 0); border-image: none; }",
     media: "all and (min-width:300px), all and (min-device-width:350px)",
     order: 3
  },
  4: {
     content: "style {line-height: 20px;}",
     media: "all",
     order: 4
  },
  length: 5
]

Working with the elementRules Array

Here's an example that shows what you can do with the elementRules Array. It iterates over the results and prints each elementRule's three properties:

document.getElementById('showStyles').onclick = function() {
  var $lorem = document.getElementById('lorem');
  var $code  = document.getElementById('code');
  var rules  = MEJSX.getCustomCssRulesOnElement($lorem);

  for (var i=0; i<rules.length; i++) {
    $code.innerText += '\n\n//Order: ' + rules[i].order 
                     + ' | Media:'     + rules[i].media + '\n' 
                                       + rules[i].content;
  }
}

That produces the following useful information for the #lorem paragraph element above:

//Order: 0 | Media:all
p { color: rgb(204, 204, 204); }

//Order: 1 | Media:all
#lorem { font-weight: bold; }

//Order: 2 | Media:all and (min-width:300px), all and (min-device-width:350px)
p { margin: 0px; }

//Order: 3 | Media:all and (min-width:300px), all and (min-device-width:350px)
#lorem { border: 1px solid rgb(0, 0, 0); border-image: none; }

//Order: 4 | Media:all
style {line-height: 20px;} 

Conclusion

In the next installment, we'll delve into the getCustomCssRulesOnElement() function code. In the meantime, I created a demo in Codepen. Feel free to inspect and even play around with the code. That's what it's there for!



Rob Gravelle

Rob Gravelle resides in Ottawa, Canada. His design company has built web applications for numerous businesses and government agencies. Email him.

Rob's alter-ego, "Blackjacques", is an accomplished guitar player, who has released several CDs and cover songs. His band, Ivory Knight, was rated as one of Canada's top hard rock and metal groups by Brave Words magazine (issue #92).



Make a Comment

Loading Comments...

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.
  •  
  •  
  •  
Thanks for your registration, follow us on our social networks to keep up-to-date