A while back I wrote about an amazing discovery I’d made in which I learned that stylesheets are part of the DOM. I mentioned some properties to play with for fun and profit, and then heartily went on my way. Today I’d like to explore the CSSOM with a little more discipline, and also explain how I made a small debugger using the Table API.
Some Corrections and Whatnots
I did get some more technical facts wrong when I wrote my previous post. While content of the message was accurate, getting the technical issues right is a big deal if you want to actually build something based on this information. Sorry.
document.styleSheets is an Object
Previously, I’d said that this was an array. It is not. A simple
document.styleSheets is made with the
StyleSheetList() function to produce an object, not an array.
There is an Object Model for CSS
Another, slightly more glaring mistake that I’d made was saying that CSS was part of the DOM (Document Object Model). I should have done some more research. There’s a whole specification for the CSS Object Model. We’re actually dealing with the CSSOM, not the DOM. Therefore, a more accurate thing to say is that the CSSOM is linked to the DOM.
Getting into the CSSOM
Firstly, let’s get a list of some of the objects we’re dealing with in the CSSOM:
- A list of all the stylesheets. Its properties are just a collection of
- A single stylesheet. Contains some properties which are objects, boolean values, and strings that give us information about the stylesheet.
- A list of all the style rules. The properties are the
- an object which is a single style rule. Contains some properties that are objects, boolean values, and strings that give us information about the style rule.
- An object which defines the medium to which a
Let’s review the hierarchy. The outermost object is
StyleSheetList. It contains a list of
CSSStyleSheet objects. The
CSSStyleSheet object contains
CSSRuleList which contains
Step one: grab the object
We’d start by accessing the
document.styleSheets object. Easy enough. Just remember that it’s an object — not an array.
Step two: watch your loops
document.styleSheets object is simple enough. Since this isn’t an array, that means we can’t
.forEach. We’re going to have to use the looping syntax for objects (
for (var item in items)).
This object has nine properties attached to it. If you’ve read my previous post, then some of this will be a review.
CSSRuleListobject. A list of all the style rules. Its properties are primarily a collection of
CSSStyleRuleobjects. You could find other objects such as
- A boolean value for whether or not a particular stylesheet is disabled. You can set this value.
- String value. A fully qualified URL for the stylesheet
MediaListobject. Media information for this stylesheet. Specifically, if this stylesheet is targeted towards a medium (print or screen) or a specific window size, you’ll find it here.
- DOM object. HTML element where this stylesheet gets called. Most likely it’s a
LINKnode, but it could be a
- If this stylesheet was imported from another one, then this is the parent.
CSSRuleListobject. Seems to be identical as
- String value. The
titleattribute in the node of the stylesheet. This is a getter, not a setter.
- String Value. Just what it sounds like, the type of styles.
Step three: loop more objects
We've accessed the
document.styleSheets object. We've looped through the objects. We're now accessing a single
cssStyleSheet object. If we want to grab
cssRules, we're going to have to do a second
for (var item in items) loop.
- A string value which is the entire rule set — the selector and the properties
- Not entirely sure on this one. Specifications say it's a "context object" which makes it ironically difficult to explain.
CSSStyleSheetobject which contains this rule. Open it up and you'll entire a world of recursion that would make Christopher Nolan jealous.
- A string which is the text of the selector.
CSSStyleDeclarationobject. Open it up and you'll see it's a collection of properties and their values.
CSSStyleRule is where, if we were building a super robust analyzer, we'd list out the properties of each object. Having the style and selector as separate properties could be really useful — especially if you wanted to build a tool that determined which style rules were getting applied.
The CSSOM Debugger
Using the Analyzer
I make a single object attached to the window (
You just need to run
If there isn't a
div on the page with your
Check out what a live example would like like over on JSFiddle.
The Big Idea
This makes a great way to get some quality information about how the browser is parsing your stylesheets. Understanding that you're dealing with an entire object model, which includes objects attached to other objects, is key to building tools to manipulate and analyze styles.