ScreenshotNeo

BlogGuides

CSSOM Explained: The CSS Object Model

Learn how CSSOM exposes stylesheets, rules, and declarations to JavaScript, with runnable examples for reading and changing CSS.

By the ScreenshotNeo team4 October 20269 min read

CSSOM, the CSS Object Model, is the set of browser APIs JavaScript uses to read and change CSS-related state. It exposes stylesheets as CSSStyleSheet objects, rules as objects such as CSSStyleRule, and declaration blocks as CSSStyleDeclaration. For a quick starting point, inspect document.styleSheets; to change one element’s appearance, use its style declaration or the CSS rule that controls it.

CSSOM is related to the DOM, but it is not simply a second tree that mirrors the DOM. The DOM represents document structure; CSSOM provides APIs for stylesheet, rule, and declaration state. The W3C describes its core features as providing scripts access to and manipulation of style-related state and processes. [W3C CSS Object Model specification]

1. CSSOM at a glance

CSSOM object or API What it represents Common use
document.styleSheets The document’s associated stylesheets Enumerate stylesheets available to the document
CSSStyleSheet A stylesheet and its rules Read or modify rules in a sheet
CSSRule and derived interfaces A stylesheet rule; a style rule is a CSSStyleRule Read selectors and access their declarations
CSSStyleDeclaration An ordered block of CSS declarations Read, set, or remove property values
CSSOM View APIs Visual view details such as geometry, viewport dimensions, and scrolling Inspect an element’s position or scroll a view

CSSOM View is a neighboring module, not another name for the core stylesheet and rule model. Its cited W3C publication is a Working Draft dated 16 September 2025, so treat that document as draft material. [W3C CSSOM View Working Draft]

2. Read and change an element’s inline styles

The quickest way to set CSS from JavaScript is to modify the element’s style property. This edits that element’s inline declaration block. It does not edit the stylesheet rule that may have originally styled the element.

<div id="notice" style="color: navy">Ready</div>
<script>
  const notice = document.querySelector("#notice");

  // Read an inline declaration.
  console.log(notice.style.color); // "navy"

  // Set a property. CSS property names use camelCase here.
  notice.style.backgroundColor = "#eef4ff";

  // setProperty accepts the CSS property spelling, including custom properties.
  notice.style.setProperty("border-radius", "0.5rem");
  notice.style.setProperty("--accent", "rebeccapurple");

  // Remove one inline declaration.
  notice.style.removeProperty("border-radius");
</script>

For names such as background-color, the JavaScript property form is backgroundColor. setProperty() and getPropertyValue() use CSS spelling, which is convenient for custom properties and dynamically supplied property names.

Reading element.style.color reads the inline declaration. To ask the browser for the resolved style currently applied after the cascade, use getComputedStyle():

const element = document.querySelector("#notice");
const inlineColor = element.style.color;
const resolvedColor = getComputedStyle(element).color;

console.log({ inlineColor, resolvedColor });

Computed style is a read view of the applied style; use a declaration block or stylesheet rule to make changes.

3. Find stylesheets and inspect rules

document.styleSheets is a practical entry point for stylesheets associated with a document. Stylesheets can be associated through mechanisms including <style> and <link> elements, @import, XML stylesheet instructions, and HTTP Link headers. Not every stylesheet-like resource is necessarily represented in this list; MDN documents exceptions, including user-agent sheets and CSS module imports. [MDN: Document.styleSheets]

// Run in a browser page or its developer console.
for (const sheet of document.styleSheets) {
  console.log("Stylesheet:", sheet.href || "<style> element");

  try {
    for (const rule of sheet.cssRules) {
      if (rule.type === CSSRule.STYLE_RULE) {
        console.log(rule.selectorText, rule.style.cssText);
      }
    }
  } catch (error) {
    console.warn("Could not read this sheet's rules:", sheet.href, error);
  }
}

A sheet can also be reached through its owner element when it has one, and imported sheets through their import rules. Checking each sheet individually is useful because associated sheets can have different origins or access conditions. Catch errors around access to cssRules and handle the sheet you could not inspect; do not let one unreadable sheet stop processing the rest.

Some collection-like CSSOM interfaces expose indexed entries rather than ordinary JavaScript arrays. Use iteration supported by the target interface, or index entries explicitly if needed. Check the specific interface documentation and target browser when compatibility matters.

4. Read and edit a stylesheet rule

A style rule is represented by CSSStyleRule. It exposes the selector text and a style declaration object. This example locates a rule and changes one declaration:

// Example page stylesheet: .status { color: gray; }
const sheet = [...document.styleSheets].find((item) => item.href === null);

if (!sheet) {
  throw new Error("No inline stylesheet was found");
}

const statusRule = [...sheet.cssRules].find(
  (rule) => rule.type === CSSRule.STYLE_RULE && rule.selectorText === ".status"
);

if (!statusRule) {
  throw new Error("The .status rule was not found");
}

statusRule.style.setProperty("color", "seagreen");
console.log(statusRule.style.getPropertyValue("color"));

The example assumes the matching sheet and rule are readable and that the selector is unique in that sheet. In production code, choose the sheet deliberately, account for a missing rule, and avoid relying on a selector being unique across all stylesheets.

Stylesheets expose rule-list operations such as inserting or deleting rules. Inserting a rule changes the stylesheet in memory for the current document; it does not rewrite the original CSS file on the server. If the goal is persistent source editing, change the source stylesheet or the build input instead.

5. Choose the right style-reading API

Goal Use What it tells you
Read or change a particular element’s inline declarations element.style Declarations on that element’s style attribute
Read the style currently applied after CSS resolution getComputedStyle(element) Resolved values for the element’s properties
Inspect or change a stylesheet rule sheet.cssRules and a rule’s style Rules and declarations in a readable stylesheet
Inspect position, dimensions, or scrolling Relevant CSSOM View and element geometry APIs Visual-view information rather than stylesheet source

Keep the question precise: inline declaration, computed value, stylesheet rule, or visual geometry. These APIs answer different questions, and a computed value does not tell you which source rule supplied it.

6. CSSOM View: geometry and scrolling

CSSOM View groups APIs for information about a document’s visual view, including layout box positions, viewport dimensions, and scrolling. For example, getBoundingClientRect() is commonly used to read an element’s rectangle, while scrolling APIs control the visible position. These operations complement stylesheet inspection; they do not replace the stylesheet, rule, and declaration objects described above. [W3C CSSOM View Module]

const card = document.querySelector(".card");
const rect = card.getBoundingClientRect();

console.log({
  left: rect.left,
  top: rect.top,
  width: rect.width,
  height: rect.height,
  viewportWidth: window.innerWidth,
  viewportHeight: window.innerHeight
});

card.scrollIntoView({ behavior: "smooth", block: "center" });

Geometry is useful for layout-dependent behavior, but it describes the current visual state. If styles, fonts, content, or viewport dimensions change, measurements can change too. Read support details for each API you depend on; CSSOM features were added at different times, so browser support cannot be summarized by one uniform CSSOM compatibility claim. [MDN: CSS Object Model]

7. Practical patterns and edge cases

Use custom properties for values shared with CSS

document.documentElement.style.setProperty("--brand-color", "#1769aa");
const current = getComputedStyle(document.documentElement)
  .getPropertyValue("--brand-color")
  .trim();

Remove a declaration instead of assigning an empty value

Use removeProperty("property-name") when the intention is to remove an inline declaration. This makes the operation explicit and lets the rest of the cascade determine the applied value.

Do not confuse rule edits with source-file edits

CSSOM changes affect the live document’s style state. They do not save edits back to a remote stylesheet, your repository, or a build system.

Handle absent elements, sheets, and rules

DOM queries can return null, and a dynamically loaded stylesheet or rule may not yet be present. Check query results and locate the intended rule at the time you use it. Avoid retaining a rule reference across changes that replace or rebuild stylesheets unless your application controls that lifecycle.

Check the exact interface you need

Support varies by interface and feature. Consult the specific MDN interface page and compatibility data for your target browsers rather than assuming every CSSOM method behaves identically everywhere. [MDN CSSOM overview]

8. Troubleshooting

Symptom Likely cause Fix
document.querySelector() returns null The element is absent, the selector is wrong, or the code ran before the element existed. Check the selector and run after the relevant markup is available.
element.style.color is empty even though the element looks colored The color comes from a stylesheet or another part of the cascade, not an inline declaration. Read getComputedStyle(element).color for the resolved color, or inspect the relevant stylesheet rule.
cssRules access throws or a sheet cannot be inspected The sheet is not readable in the current context, or access is otherwise restricted by the browser. Catch access errors per sheet, continue with readable sheets, and verify the applicable origin and browser rules for the page.
No matching CSSStyleRule is found The rule is in another sheet, loaded later, nested, or uses a different selector spelling. Inspect sheet URLs and rule contents, wait for the relevant stylesheet to load, and account for nested rules where appropriate.
A style change has no visible effect A later or more specific declaration, state change, or layout condition may determine the final appearance. Compare the inline value, rule declarations, and computed value; update the intended source of the style.
A change disappears after navigation or reload CSSOM modified only the live document. Persist the change in the stylesheet source, application state, or server-side content that creates the page.
Measurements differ across runs Viewport, content, fonts, or layout state changed. Measure after relevant content and layout are ready, and record the viewport and state used.

9. Performance, reliability, and support

CSSOM is a browser interface, not a remote service. A read or write is local to the page, while layout-dependent measurements describe the page’s current state. For reliable behavior, wait until the elements and stylesheets your code needs are available, check for missing objects, and isolate access failures to the specific sheet or operation.

When you both change styles and immediately measure geometry, the measurement depends on the resulting layout. Keep DOM and style work focused, and measure only when you need the geometry. The standards and MDN overview do not provide a single performance guarantee or a uniform support matrix for all CSSOM APIs. Verify compatibility for the exact interface and browser versions that matter to your application. [MDN CSSOM overview]

10. Capture a page after CSS changes

If the reason you are reading computed styles or geometry is to produce a visual record of a page, a screenshot is a useful end result. You can capture it yourself with browser automation, or use a screenshot API. ScreenshotNeo is a website screenshot API and MCP server for developers. Its documented options include full-page capture, element capture, viewport and device presets, dark mode, custom CSS and JavaScript, and configurable waits. Learn about ScreenshotNeo; see the API documentation.

11. Or skip the browser setup

Send one GET request with the page URL to capture a screenshot. This example saves the returned image as WebP; see the ScreenshotNeo API documentation for request options and response details.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write("shot.webp", res);
  • Cookie banners are accepted and removed before the shot; more than 60 known consent platforms, newsletter popups, and chat widgets can be handled, and each step can be turned off.
  • Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Response headers report the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients.
  • The Free plan includes 1,000 shots a month with no card. Paid plans start at $5 for 3,000 shots. All listed features are on every plan.

Sign up free for 1,000 screenshots a month, with no card required.

12. Frequently asked questions

Is CSSOM the same thing as CSS?

No. CSS is the styling language; CSSOM is the browser’s JavaScript-facing set of APIs for accessing and changing CSS-related state.

Does CSSOM mirror the DOM node for node?

No. The DOM represents document structure. CSSOM represents stylesheet, rule, and declaration state, with related view APIs for geometry and scrolling.

Can CSSOM save a change to a CSS file?

No. A script can change the live page’s CSS state. Persisting an edit requires changing the source or the system that generates the page.

Where should I check browser support?

Check compatibility for the specific CSSOM interface or method in the browsers you target. There is no single support answer for every API in the model.