DOM Styles and Classes
There are three layers to "styling" an element from JavaScript: setting inline styles directly, toggling classes the stylesheet already defines, and reading the actual styles the browser computed. Picking the right layer keeps your CSS where it belongs and your code small. This page walks through each.
Inline styles via element.style
element.style is a CSSStyleDeclaration — a JavaScript view of the element's style="…" attribute. Each CSS property maps to a camelCase property name.
const box = document.querySelector(".box");
box.style.color = "white";
box.style.backgroundColor = "tomato"; // background-color → backgroundColor
box.style.padding = "12px 16px";
box.style.borderRadius = "8px";Inline styles win against most stylesheet rules (specificity-wise they're high), which makes them powerful but heavy-handed. Use them for dynamic, calculated values — positions during a drag, colours derived from data, a width set from JavaScript.
Removing inline styles
box.style.color = ""; // empty string clears that property
box.style.removeProperty("padding");
// Read just what is inline (not what CSS does):
box.style.color; // "white"
box.style.fontSize; // "" if not set inlineCSS custom properties (variables)
CSS variables don't fit the camelCase mould — they keep their dashes. Use setProperty / getPropertyValue.
box.style.setProperty("--accent", "rebeccapurple");
box.style.getPropertyValue("--accent"); // "rebeccapurple"This is the standard way to drive a CSS-variable-based theme from JavaScript.
classList — the right tool for the job
Most of the time you don't want to set styles from JavaScript at all — you want to toggle a class that your stylesheet already defines. The classList API makes that easy:
const btn = document.querySelector(".btn");
btn.classList.add("active");
btn.classList.remove("disabled");
btn.classList.toggle("open"); // returns the new state
btn.classList.toggle("open", true); // force add
btn.classList.toggle("open", false); // force remove
btn.classList.contains("active"); // true
btn.classList.replace("size-sm", "size-lg");Each method is a no-op when it doesn't need to do anything (add on an already-present class, remove on a missing class), which keeps callers simple.
a tiny toggle pattern
document.querySelector(".menu-toggle").addEventListener("click", (e) => {
const open = document.body.classList.toggle("menu-open");
e.currentTarget.setAttribute("aria-expanded", String(open));
});className: bulk set or read
Before classList there was element.className — a plain string of all the classes. It is still useful when you want to replace the whole set at once:
btn.className; // "btn primary active" btn.className = "btn ghost"; // replaces everything
But for add/remove/toggle, classList is clearer and safer (no risk of duplicates, no string surgery).
Reading the styles the browser actually applied
element.style only sees what you set inline. To read the resolved value — what the browser actually used after applying every stylesheet — use getComputedStyle:
const box = document.querySelector(".box");
const cs = getComputedStyle(box);
cs.color; // "rgb(255, 255, 255)"
cs.fontSize; // "16px" — always in absolute units, computed
cs.display; // "flex" — even if your CSS says "var(--display)"
cs.getPropertyValue("--accent"); // CSS variables work here toocolor -> rgb(255, 255, 255) fontSize -> 16px display -> flex
Values are returned as strings, always in computed/absolute form ("16px", not "1em").
getComputedStyleis read-only. Setting a property on the returned object does nothing.It forces a style recalculation, so avoid calling it in tight loops or inside scroll handlers.
Measuring elements
Closely related, but not on style: every element has read-only size properties.
const r = box.getBoundingClientRect(); r.width; r.height; r.top; r.left; // position relative to the viewport box.offsetWidth; box.offsetHeight; // include padding and border box.clientWidth; box.clientHeight; // include padding only box.scrollWidth; box.scrollHeight; // including overflowed content
When to use each layer
Static look — write it in CSS, use a class.
State that has a name (open, active, error, loading) — toggle a class with
classList.Dynamic numeric value computed at runtime (a width, a position, a hue) —
el.style.left = "120px".Theme variables —
style.setProperty("--accent", …)on:rootor a wrapper.Reading what is on screen —
getComputedStyleorgetBoundingClientRect.