import { Component } from '@angular/core';
import { WrDensity, WrDensityDirective, wrDensityPrePaintScript } from 'ngwr/density';
@Component({ imports: [WrDensityDirective] })
export class MyComponent {}WrDensity
Switch control spacing between sm, md, lg and touch.
Installation
Import the class, and @use the entry point in your global styles: without it the component renders unstyled.
Live demo — global
set() changes the density for the whole app, and the choice is stored.
private readonly density = inject(WrDensity);
this.density.set('touch');
this.density.cycle();
this.density.current(); // 'sm' | 'md' | 'lg' | 'touch'Per-subtree override
Put [wrDensity] on an element to give its subtree its own density.
<aside wrDensity="sm">
<wr-list ...></wr-list>
</aside>Override the multipliers
Re-declare them on the level's [data-wr-density] selector; on :root the shipped values win.
[data-wr-density='sm'] {
--wr-density-y: 0.5;
--wr-density-x: 0.8;
}Configure
Add withDensity() to the app's own provideWr(); in a route's providers it is ignored.
import { provideWr } from 'ngwr';
import { withDensity } from 'ngwr/density';
providers: [provideWr(withDensity({ defaultDensity: 'sm' }))],SSR: no jump after boot
Put this script in <head>, next to the theme one, so a stored density applies before the first paint. New in v15.
<script>(function(){try{var m=null,r=null;try{r=window.localStorage.getItem("wr-density");}catch(e){}if(r!==null){try{var p=JSON.parse(r);if(p!==null&&typeof p==="object"&&"v" in p){if(p.e===undefined||p.e>=Date.now())m=p.v;}else{m=p;}}catch(e){m=r;}}if(["sm","md","lg","touch"].indexOf(m)<0)m="md";document.documentElement.setAttribute("data-wr-density",m);}catch(e){}})();</script>import { wrDensityPrePaintScript } from 'ngwr/density';
// Pass the values you gave withDensity() and withStorage():
wrDensityPrePaintScript({ defaultDensity: 'sm', storageKey: 'app-density', storagePrefix: 'myapp:' });API
| Name | Description | Type | Default |
|---|---|---|---|
WrDensity | Injectable service. | service | — |
current | Active density. Write it with set() or cycle(). | 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] | Give one subtree its own density. | Directive | — |
wrDensityPrePaintScript(options?) | Source of the script that applies a stored density before the first paint. Takes the withDensity() and withStorage() values. | (options?: WrDensityPrePaintOptions) => string | — |
CSS tokens | --wr-density-y and --wr-density-x scale control padding, --wr-density-gap the gaps in layout components. --wr-density-text is for your own calc(). | CSS custom property | 1 |
CSS variables
Set these on the component's selector or a wrapper, not on :root: the defaults are declared on ngwr/density's own element.
| Variable | Default | Declared on |
|---|---|---|
--wr-density-gap | 1 | :root +4 variant overrides |
--wr-density-x | 1 | :root +4 variant overrides |
--wr-density-y | 1 | :root +4 variant overrides |
Dependencies
| Built on | WrStorage |
|---|
See also
Guide ThemingLoad the theme, switch light and dark, and rebrand the palette.Service WrThemeSwitch between light, dark and auto, and keep the choice.Guide DensityMake every control tighter or roomier with one setting.Docs ConfigurationSet app-wide options at bootstrap.Guide Mobile & responsiveMake ngwr layouts work on touch screens and narrow containers.Guide SizingSize and round your own controls with ngwr's tokens.Service WrStorageTyped, reactive key-value storage over localStorage or any engine, safe under SSR.Component BadgeA small label for a count or a status.