You can style page elements directly from C++ by setting inline styles and reading computed styles. Writing inline styles is fast enough to run every frame— native code can update animations and interface elements directly.

To measure an element or scroll its contents, see [Element Geometry and Scrolling](/docs/2.0/element-geometry-and-scrolling).

## Setting Styles

Once you find an element (see [Finding and Modifying Elements](/docs/2.0/finding-and-modifying-elements)), set inline styles by assigning directly to members of its `style` property. Values parse the same as in JavaScript— anything that doesn't parse is ignored and the old value stays:

```cpp
panel.style.display = "none";
panel.style.border = "1px solid white";
```

### Numbers and Units

Use helpers like `dom::StyleValue::Px()` and `Pct()` for computed values without string formatting (plain numbers work for unitless properties like `opacity`). Number literals like `"50%"` are checked when you compile— a typo like `"50pxx"` won't compile.

```cpp
bar.style.width = dom::StyleValue::Pct(health * 100);
bar.style.opacity = 0.8;
```

> 🚧 Properties Ignore Unsupported Units
>
> Assigning a number that a property doesn't accept has no effect— the previous value stays (such as setting a unitless `5` on `width` or a pixel value on `opacity`). Use a unit the property expects, like `dom::StyleValue::Px(5)`. When DOM diagnostics are on, the library logs a warning for each ignored write.

### Colors

Pass `Color(r, g, b, a)` for colors from your data (channels range from 0 to 1, and alpha defaults to 1). Wrapping a hex or `rgb()` literal in `Color("...")` checks it when you compile (unlike a bare string), while named colors and runtime text use `Color::Parse()` (see [Working with Colors](/docs/2.0/working-with-colors)).

```cpp
bar.style.backgroundColor = Color(1.0f, 0.2f, 0.2f, 0.8f);
bar.style.color = Color("#ff3366");
```

#### Colors from Text

Call `Color::Parse()` to read CSS color text at run time (eg, from a theme file or a user setting). It accepts any CSS color format (including named colors and `hsl()`), and returns an invalid `Color` if the text didn't parse, so you can check it first.

```cpp
Color accent = Color::Parse(settings.accent);
if (accent)
  hud.style.color = accent;
```

### Custom Properties

You can set a custom property (`--name`) by indexing `style` with its property name. Descendant elements inherit the assigned value (text or a `Color`). Pass numbers as text like `"8px"` since `dom::StyleValue` does nothing on a custom property.

```cpp
hud.style["--accent"] = Color(0.2f, 0.8f, 1.0f);
hud.style["--radius"] = "8px";
```

#### Theming the Whole Page

To theme the whole page, set a custom property on the root element. Every rule that uses it (`var(--accent)`) updates.

```cpp
document.documentElement().style["--accent"] = Color(0.2f, 0.8f, 1.0f);
```

### Names in Strings

You can set any property by name in a string using either its CSS name (`background-color`) or its JavaScript name (`backgroundColor`). When you know the name as you write the code, use the member instead (`hud.style.backgroundColor`) since the compiler checks it.

```cpp
for (const auto& [name, value] : theme)
  hud.style[name] = value;
```

`cssText` reads or replaces the whole inline declaration (as on the web).

#### Marking a Value `!important`

Pass `true` as the third argument to `setProperty()` to mark a value `!important`. Like the web, `setProperty()` takes the CSS name only (`"background-color"`, not `"backgroundColor"`):

```cpp
hud.style.setProperty("background-color", "navy", true);
```

#### Removing Properties

Calling `removeProperty()` removes a property and returns its old value (CSS name only, like the web). You can also remove the property by assigning an empty string, an empty `dom::StyleValue()`, or an unset `Color` (eg, a value copied from an element that had none):

```cpp
std::string old = hud.style.removeProperty("background-color");
bar.style.width = "";
```

## Reading Styles

Reading an `el.style` member returns only the value set inline (it reads as empty when a stylesheet sets it). Call `dom::getComputedStyle(el)` to inspect the style that applies— it has the same named members as JavaScript's `getComputedStyle(el)`:

```cpp
auto computed = dom::getComputedStyle(bar);
std::string width = computed.width;
```

> 🚧 Reads Can Trigger Layout
>
> Reading a computed style applies pending style changes first. Any property that depends on layout (eg, `width`, `margin`, or `top`) also runs a layout pass— make all changes first and then read. Measuring an element follows the same rule (see [Element Geometry and Scrolling](/docs/2.0/element-geometry-and-scrolling)).

### Reading Numbers and Colors

Computed properties return text like `"300px"` or `"rgb(255, 51, 119)"`, just like JavaScript. Call `AsStyleValue()` to parse a number with a unit (lengths return in pixels), or `AsColor()` to parse a `Color`. A property that isn't set returns an empty value, and a value that isn't a single number or color (like `auto`) returns an invalid one— both evaluate to false so you can check the result before using it:

```cpp
if (dom::StyleValue width = computed.width.AsStyleValue())
  PlaceMinimap(width.value);

Color accent = computed.color.AsColor();
```

### Keeping a Computed Style

A computed style is live— each read sees the element's current styles. You can get it once and read it whenever you need (eg, every frame).

```cpp
dom::ComputedStyle computed = dom::getComputedStyle(hud);

// Later: sees the current styles.
std::string opacity = computed.opacity;
```
