Styling from JavaScript

Advanced · 18 min read · ▶ live playground · ✦ checkpoint

Changing text changes what the page says. Changing style changes what the page means: active, disabled, full, empty, close, far away. JavaScript can touch CSS directly, but the professional default is clear: use classes for state, and save inline values for numbers that really come from code.

Classes are the state switch

classList is an element's class controller. It gives you methods like add, remove, toggle, and contains so JavaScript can switch CSS states without rewriting the whole class string.

Think of classes as badges on an element. CSS decides what each badge means; JavaScript only pins on the right badge at the right moment.

web page — live previewsandboxed
Run rebuilds the page

The CSS owns the visual details: border color, background, weight. JavaScript owns the state choice: this card is boarding, not delayed. That split keeps your code readable because you do not have color values scattered through your JavaScript.

classList.toggle(name, force) is the sharp version of the same move. The second argument forces the class on for true and off for false, which is perfect when state comes from data.

Inline styles are for real dynamic values

An inline style is a style written directly on one element's style attribute. JavaScript can set it with element.style.propertyName, but that should not become your everyday styling tool.

Use inline styles when the value is genuinely dynamic: a progress percent, a measured pixel value, or a user-selected theme color. If the value is a named state like "selected" or "error", prefer a class.

web page — live previewsandboxed
Run rebuilds the page

That example uses a CSS custom property, a CSS variable whose name starts with --. JavaScript sets --completion, and CSS uses it in width: var(--completion, 0%).

Custom properties are useful because they keep the shape of the style in CSS while letting JavaScript supply one changing number. The code does not know how the meter is drawn. It only knows the value is 72%.

dataset stores small element facts

A data-* attribute is a custom HTML attribute for small app-specific facts, like data-plan="pro" or data-count="3". dataset is the JavaScript object that reads and writes those attributes.

Attribute names convert to camelCase:

  • data-plan becomes element.dataset.plan
  • data-player-id becomes element.dataset.playerId

Use dataset like a sticky note on one element, not like a database. It is good for small state that belongs to that element and can help CSS or later event code understand it.

web page — live previewsandboxed
Run rebuilds the page

Every dataset value is a string because HTML attributes are text. If you need a number for math, convert it with Number(...) before calculating.

Measure after layout

getBoundingClientRect() measures an element after layout and returns a DOMRect, an object with viewport-relative position and size fields like width, height, top, and left. Viewport-relative means the numbers are measured from the visible browser window, not from the whole document file.

Measurement is for questions CSS cannot answer alone: "how wide did this label actually render?" or "is this card taller than its container?" It is a read from the finished layout.

web page — live previewsandboxed
Run rebuilds the page

The rounded widths are stable because the CSS sets fixed widths. On real pages, font loading, responsive layout, and viewport size can change measurements, so measure at the moment you need the answer.

Other measurement tools exist, but they ask slightly different questions: offsetWidth gives a rounded layout width, clientWidth gives inner width without borders, and scrollWidth tells you how wide the content wants to be. Start with getBoundingClientRect() when you need the element's current box in the viewport.

The decision rule

When JavaScript changes presentation, choose the smallest honest tool:

  1. Use classList for named states: selected, hidden, expanded, invalid.
  2. Use inline styles or custom properties for values that come from data or measurement.
  3. Use dataset for small element-specific facts, especially facts CSS or later event code can read.
  4. Use measurement when you need the layout the browser actually produced.

You now have the full DOM toolkit for static scripts: find nodes, change nodes, style states, and measure layout. Next, those changes stop being automatic and start responding to people: Section 15 turns clicks, keys, and form input into page behavior.

Checkpoint

Answer all three to mark this lesson complete

+50 XP on completion