
DOM and CSSOM are two core structures the browser builds before rendering a page. The DOM represents document content and structure. The CSSOM represents parsed CSS rules. Together, they help the browser build the render tree, calculate layout, paint pixels, and display the page.
Understanding them makes performance advice such as "batch DOM updates" and "avoid forced layout" more concrete.
What the DOM is
The Document Object Model represents HTML as a tree of nodes:
- element nodes such as
div,p, anda - text nodes
- attributes
- parent-child relationships
JavaScript can read and modify that tree:
const element = document.getElementById("demo")
element.textContent = "Hello, World!"
const paragraph = document.createElement("p")
paragraph.textContent = "A new paragraph"
document.body.appendChild(paragraph)
Common DOM APIs include:
getElementByIdquerySelectorquerySelectorAllcreateElementappendChildclassListaddEventListener
What the CSSOM is
The CSS Object Model represents parsed CSS rules and computed style information. The browser parses CSS files, style tags, and inline style information into structures it can use for rendering.
JavaScript can affect CSSOM-related behavior:
document.getElementById("demo").style.color = "red"
document.getElementById("demo").classList.add("is-active")
Prefer class changes for repeated visual states. Direct inline style edits are fine for dynamic values, but they can become hard to maintain when used everywhere.
Rendering in simplified steps
The browser roughly does this:
- Parse HTML into the DOM.
- Parse CSS into the CSSOM.
- Combine visible DOM nodes and style information into a render tree.
- Calculate layout: positions and sizes.
- Paint pixels.
- Composite layers and display.
The real browser pipeline is more complex, but this model is enough to reason about many performance problems.
For animation-specific rendering costs, read Reflow and Repaint: Why CSS Animations Get Janky.
Batch DOM updates
Many small DOM writes can be expensive. Build a fragment and insert once:
const fragment = document.createDocumentFragment()
for (let index = 0; index < 1000; index += 1) {
const item = document.createElement("li")
item.textContent = `Item ${index}`
fragment.appendChild(item)
}
document.querySelector("ul").appendChild(fragment)
Modern frameworks batch much of this for you, but direct DOM code still benefits from this pattern.
Avoid forced synchronous layout
Reading layout values after writing layout-affecting styles can force the browser to calculate layout immediately:
element.style.width = "200px"
const height = element.offsetHeight
When possible, group reads before writes:
const height = element.offsetHeight
element.style.width = "200px"
This is especially important in scroll, resize, drag, and animation code.
Use class changes for visual state
Instead of repeatedly setting many inline styles, define CSS and toggle classes:
.positioned {
position: absolute;
}
element.classList.add("positioned")
This keeps style rules centralized and easier to inspect.
Use requestAnimationFrame for visual updates
function animate() {
element.style.transform = `translateX(${x}px)`
requestAnimationFrame(animate)
}
requestAnimationFrame(animate)
requestAnimationFrame schedules work with the browser's rendering cadence. It does not automatically make heavy work cheap, but it is a better fit for visual updates than arbitrary timers.
Related FreeMac guides
- For CSS animation costs, read Reflow and Repaint: Why CSS Animations Get Janky.
- For visibility-based triggers, read IntersectionObserver Guide: Lazy Loading and Scroll Triggers.
- For the JavaScript event loop, read JavaScript Event Loop: Tasks, Microtasks, and Rendering.
Continue reading
CSS 3D: perspective and transform-style Explained
Understand CSS 3D transforms through perspective, transform-style: preserve-3d, translateZ, rotateY, flattening, and parent-child 3D scene setup.
9 min readCSS align-items, align-self, justify-items, and justify-self
Understand the difference between align-items, align-self, justify-items, and justify-self in Flexbox and Grid, including container vs item scope and axis direction.
7 min readReflow and Repaint: Why CSS Animations Get Janky
Understand browser rendering steps, reflow, repaint, compositing, and why transform and opacity are usually better animation targets than width, height, top, or left.
Subscribe to FreeMac
Weekly picks: free Mac software reviews, trusted source updates, alternatives, and low-friction guides.