Skip to content
JavaScript js dom 4 min read

Styling Elements

Sometimes you need to change how an element looks at runtime: animate a value, position a tooltip under the cursor, or react to data that CSS alone can’t express. JavaScript gives you direct write access to an element’s inline styles through the style property, plus a read-only window into its final, rendered appearance via getComputedStyle. Knowing which one to reach for — and when to skip both in favor of a CSS class — is the difference between maintainable UI code and a tangle of inline rules.

The style property

Every element exposes a style object that maps to its inline style attribute. Setting a property here writes a declaration directly onto the element, which means it wins over almost everything in your stylesheets (short of !important). CSS property names become camelCase, since hyphens aren’t valid in JavaScript identifiers: background-color becomes backgroundColor, font-size becomes fontSize.

const box = document.querySelector("#box");

box.style.backgroundColor = "rebeccapurple";
box.style.fontSize = "1.5rem";
box.style.padding = "1rem 2rem";
box.style.borderRadius = "8px";

Values are always strings, and most length-based properties require their unit — box.style.width = "200px" works, but box.style.width = 200 is silently ignored.

Gotcha: element.style only reflects styles set inline (via the attribute or via JavaScript). It does not see rules coming from your stylesheets. Reading box.style.color returns an empty string unless color was set inline, even if the element is clearly colored by a CSS rule.

setProperty and CSS variables

The camelCase API can’t express custom properties (CSS variables) because --my-var isn’t a valid identifier. For those — and any time you want to set a property by its real CSS name — use setProperty, getPropertyValue, and removeProperty:

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

// Set a CSS custom property
card.style.setProperty("--accent", "#0ea5e9");

// Set a standard property, optionally with priority
card.style.setProperty("color", "white", "important");

// Read back an inline property
card.style.getPropertyValue("--accent"); // "#0ea5e9"

// Remove it
card.style.removeProperty("color");

Driving a CSS variable from JavaScript is a powerful pattern: you set one value in JS, and your stylesheet decides how to consume it. This keeps the heavy styling in CSS while letting JS supply just the dynamic number.

<style>
  .swatch {
    --hue: 200;
    width: 120px;
    height: 120px;
    border-radius: 12px;
    background: hsl(var(--hue) 80% 55%);
    transition: background 0.15s ease;
  }
  input { width: 240px; }
</style>

<div class="swatch" id="swatch"></div>
<p><input type="range" id="hue" min="0" max="360" value="200" /></p>

<script>
  const swatch = document.getElementById("swatch");
  const slider = document.getElementById("hue");

  slider.addEventListener("input", () => {
    swatch.style.setProperty("--hue", slider.value);
  });
</script>

Reading computed values with getComputedStyle

When you need to know what an element actually looks like — after stylesheets, inheritance, the cascade, and the browser’s defaults have all been applied — use window.getComputedStyle(element). It returns a read-only CSSStyleDeclaration of fully resolved values.

const el = document.querySelector("#box");
const styles = getComputedStyle(el);

styles.color;       // e.g. "rgb(102, 51, 153)"
styles.fontSize;    // e.g. "24px"
styles.display;     // e.g. "flex"

// Custom properties resolve too
styles.getPropertyValue("--accent").trim();

A few things to keep in mind: computed values are resolved, so colors come back as rgb()/rgba() and relative units like em are converted to px. The object is live-ish but read-only — assigning to it throws in strict mode and is otherwise ignored. To change a value, write to element.style; to read the truth, read from getComputedStyle.

const el = document.querySelector("#box");
const lineHeightPx = parseFloat(getComputedStyle(el).lineHeight);
console.log(lineHeightPx);

Output:

28.8

Performance tip: Reading getComputedStyle (or layout properties like offsetWidth) right after writing styles forces the browser to recalculate layout synchronously — a “layout thrash.” Batch your reads together, then your writes, instead of interleaving them in a loop.

style vs. getComputedStyle

Aspectelement.stylegetComputedStyle(element)
DirectionRead and writeRead-only
SourceInline styles onlyFull cascade (stylesheets + inline + inherited)
ReturnsInline value or ""Resolved final value
UnitsAs you set themNormalized (often px, rgb())
Use it toApply dynamic stylesInspect actual appearance

Prefer class toggles for non-dynamic styling

Reach for inline styles only when the value is genuinely dynamic — a computed position, a slider-driven color, a width that depends on data. For everything else, define the look in CSS and flip a class with classList. This keeps presentation in your stylesheet, plays nicely with media queries and pseudo-classes, and avoids dozens of inline declarations that are hard to override.

<style>
  .panel {
    padding: 1rem 1.5rem;
    border-radius: 8px;
    font-family: system-ui, sans-serif;
    background: #1e293b;
    color: #cbd5e1;
    transition: all 0.2s ease;
  }
  .panel.is-active {
    background: #0ea5e9;
    color: white;
    box-shadow: 0 8px 24px rgba(14, 165, 233, 0.4);
  }
</style>

<div class="panel" id="panel">Click me to toggle styling</div>

<script>
  const panel = document.getElementById("panel");
  panel.addEventListener("click", () => {
    panel.classList.toggle("is-active");
  });
</script>

The inline-style version of that effect would need you to set and reset six properties by hand on every click. The class version expresses the whole state in CSS and toggles it with a single line.

Best Practices

  • Use element.style only for truly dynamic values; express static looks as CSS classes you toggle.
  • Remember property names are camelCase (backgroundColor), and use setProperty for CSS variables and hyphenated names.
  • Always include units on length values — strings without them are ignored.
  • Use getComputedStyle to read resolved appearance; never expect element.style to reflect stylesheet rules.
  • Drive a CSS custom property from JS and let your stylesheet consume it, keeping styling logic in CSS.
  • Batch DOM reads and writes to avoid forced synchronous layout (layout thrashing).
  • Reset a single inline property by assigning "" (e.g. el.style.color = "") or calling removeProperty.
Last updated June 1, 2026
Was this helpful?