# WrDensity

> Density scale — `sm` / `md` / `lg` / `touch` — applied as CSS-variable multipliers on per-component paddings. `md` is the default and resolves to `1` everywhere; `touch` enlarges hit areas for finger input. Persisted via WrStorage and overrideable per-subtree with the `[wrDensity]` directive.

Source: https://ngwr.dev/reference/services/density  
Kind: Service

## Install

```angular-ts
import { provideWrDensity, WrDensity } from 'ngwr/density';

bootstrapApplication(AppComponent, {
  providers: [
    provideWrDensity({ defaultDensity: 'sm' }),
  ],
});

// Switch it later:
const density = inject(WrDensity);
density.set('lg');
density.cycle();
```

## Live demo — global

Pick a density. Every densified component on this page updates in place.

## Per-subtree override

Drop `[wrDensity]` on any element to scope an override. The toolbar below stays sm regardless of the page's global density.

```html
<!-- Scope an override to a subtree — descendants get sm, the rest of the app keeps the global value. -->
<aside wrDensity="sm">
  <wr-list ...></wr-list>
</aside>
```

## Override the multipliers

Each level resolves to `--wr-density-y`, `--wr-density-x`, `--wr-density-text`, and `--wr-density-gap`. Components multiply their static paddings by these. Retune them by re-declaring the level you are on — `[data-wr-density='md']`, say — rather than on `:root`.

```scss
/* Override the multipliers in your own stylesheet. */
[data-wr-density='sm'] {
  --wr-density-y: 0.5;     /* even tighter vertical padding */
  --wr-density-x: 0.8;
}
```

**Why not `:root`.**`provideWrDensity()` writes `data-wr-density` on `<html>` — including the default `md` — and the library's own `[data-wr-density='md']` block re-declares all four multipliers to `1`. That block and your `:root` rule match the same element at the same specificity, so the one that comes later in the cascade wins, and the library's stylesheet is normally later. The symptom is a retune that half applies: whatever is inside a subtree carrying its own `[wrDensity]` picks the new number up, everything under `<html>` keeps the shipped one. Declare on the attribute selector and the question does not arise.

## Where the provider goes

`WrDensity` is root-provided — one instance per application, holding one active level — and it reads `WR_DENSITY_CONFIG` from the root injector. So `provideWrDensity()` belongs in the application's own providers: put it in a lazy route and the service never sees it, leaving `defaultDensity`, `storageKey` and a renamed `attribute` at their bootstrap values with nothing reported. To vary density by feature, use the `[wrDensity]` directive on the subtree, which is what it is for — it writes the attribute on its own element and needs no provider at all.

## Why ngwr provides this

Compact/comfortable spacing usually ends up as ad-hoc CSS overrides per screen. Density tokens flip the whole catalog (or a subtree) through one provider switch.

## API

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `WrDensity` | Injectable service. | `service` | `—` |
| `current` | Active density signal. Read-only — use `set(d)` / `cycle()` to write. | `Signal<WrDensityValue>` | `'md'` |
| `set(density)` | Switch the active density. Ignores unknown values. | `(d: WrDensityValue) => void` | `—` |
| `cycle()` | Cycle `sm`, `md`, `lg`, `touch`, then back to `sm`. | `() => void` | `—` |
| `[wrDensity]` | Attribute directive — scope a density override to one subtree. | `Directive` | `—` |
| `CSS tokens` | `--wr-density-y`, `--wr-density-x`, `--wr-density-text`, `--wr-density-gap` — multipliers components apply to their paddings via `calc()`. | `CSS custom property` | `1` |

## CSS variables

Custom properties `ngwr/density` publishes. Each default below is declared on the component's own selector, so a `:root` override is shadowed by it — set them on that selector, on a wrapper you scope yourself, or inline on the element. Unlike the BEM class names, these are the supported way to restyle the component.

| Variable | Default | Declared on |
| --- | --- | --- |
| `--wr-density-x` | `1` | `:root` +4 variant overrides |
| `--wr-density-y` | `1` | `:root` +4 variant overrides |

## See also

- [Theming](https://ngwr.dev/guides/theming) — How density fits alongside palette, dark mode, and design-token overrides.
- [WrTheme](https://ngwr.dev/reference/services/theme) — Sibling — light / dark / auto. Pair both for a full appearance API.
