What exactly is the CSSOM?
Get to know what is the CSSOM and what led to its creation as a separate specification going back in time.
Back in time
Back in time, when JavaScript was first released to the public in the Netscape Navigator 2.0 browser, in 1995, CSS was still a thing to be formally specified. It was in 1996 that the world got the first ever specification of CSS.
During this time, the idea of Dynamic HTML (DHTML) was gaining traction. Basically it was a combination of technologies to dynamically change the content of an HTML document. DHTML made it possible to also modify the styles of HTML elements because they were given via HTML attributes, such as color, bg-color, border, and so on.
Soon, the (legacy) DOM API was extended to allow for programmatically changing the styles of HTML elements by modifying these attributes' values. And later, as CSS became pervasively used, certain CSS-specific interfaces also got introduced into the DOM API to allow for programmatic access of CSS styles.
The DOM Level 2 specification included two separate documents to formally define stylesheets and CSS-specific interfaces in the DOM API.
Most importantly, note that all CSS-specific interfaces at this point are, more or less, part of the overarching DOM API. They don't yet exist as a completely separate specification.
For a pretty long time, this mixing of CSS-specific APIs within the DOM API continued. However, as CSS was expanding — with work already begun on CSS 2.0, anticipated to introduce a plethora of new features into the language — it became apparent that the current ideology of addressing CSS-specific features via the DOM specification wasn't going to suffice for long.
With the continuously rising complexity of CSS, specification writers and implementors of CSS-specific interfaces in the DOM API felt the need for a complete rewrite. There were a couple of issues that needed to fixed such as the following:
- Some (CSS-specific) interfaces were poorly named.
- Some interfaces were poorly designed from the ground up with extremely inconsistent behavior across implementations.
It was crucial to transition to a much more cleanly designed set of APIs to address all concerns of programmatically interfacing with CSS. The outcome of this sequence of events was the CSSOM specification, published in 2011 by the W3C.
Let's see what exactly is the CSSOM.
What is CSSOM?
If the understand the DOM, then making intuition of the CSSOM won't be difficult for you. The CSS Object Model (CSSOM) is a set of APIs meant to programmatically work with the styles of HTML documents.
It [the CSSOM] is much like the DOM, but for the CSS rather than the HTML.
As stated before, the sole purpose behind the CSSOM is to separate styling concerns from the DOM into a completely separate set of specifications. So, as it works today:
- The WHATWG DOM standard defines DOM functionality.
- The WHATWG HTML standard further extends the DOM with HTML-specific features.
- The W3C CSSOM standard defines interfaces to work with the styles of elements in HTML (and XML) documents.
I find this ramification quite necessary and well-articulated. It really helps to address these disparate concerns in their own right.
The CSSOM tree
The CSSOM is more than just a specification. Akin to the DOM, the browser builds a CSSOM tree, albeit for the CSS instead of the HTML (as is the case for the DOM tree).
Modifications to the styles of an HTML document show up in its corresponding CSSOM tree just like how modifications to the structure and/or the content of the document show up in the DOM tree.
Important CSSOM interfaces
Now that you know what exactly is the CSSOM, let's turn our attention to consider some of its most important interfaces.
Starting with the most obvious thing, a stylesheet (internal or external) in an HTML document is represented by the base abstract class StyleSheet. StyleSheet is inherited by CSSStyleSheet, an interface meant to only model CSS stylesheets.
Recall that a CSS stylesheet is comprised of various rules, i.e. style rules (a selector list followed by a style declaration block), import rules, keyframe rules, and so on. Following this idea, CSSStyleSheet defines a property called cssRules that returns back a CSSRuleList instance.
As the name suggests, CSSRuleList is a list of CSS rules. Each item of this list is an instance of a subclass of CSSRule, which generically represents any kind of a rule in a CSS stylesheet. Some subclasses of CSSRule are CSSStyleRule, CSSImportRule, CSSKeyframesRule, and so on.
Focusing on CSSStyleRule, it represents a style rule — comprised of a selector list followed by a style declaration block.
For example, shown below is a CSS style rule, whose selector is body and whose style block consists of just one style declaration, which is that of background-color:
/* A style rule */
body {
background-color: blue;
}The CSSStyleRule interface models this entire style rule. It defines a property selectorText to access the set of selectors, as a string, and another property style to access the style declaration block of the rule, as an object.
In particular, style is based off the CSSStyleDeclaration interface which is perhaps the most important interface of the CSSOM API since it's used to represent the style property of element nodes in the HTML DOM.
Moving on, the styleSheets property of an HTML document returns back a StyleSheetList instance, which denotes an ordered list of stylesheets. StyleSheetList, like almost all list-like interfaces in JavaScript, provides indexed access for its items.
The styleSheets property is surely a quick way to obtain a collection of all the stylesheets in an HTML document and then select a given stylesheet from that collection but it isn't the only way to obtain a given stylesheet.
You can also directly access a <link> element whose rel attribute is set to "stylesheet" or access a <style> element, and then retrieve the value of its sheet property.
The sheet property of both the HTMLLinkElement (representing <link>) and the HTMLStyleElement (representing <style>) interfaces returns the underlying CSS stylesheet or null if the element doesn't have an underlying stylesheet (for e.g. a <link> element representing the favicon of the document).