ServiceUpdated in v15

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.

import { Component } from '@angular/core';
import { WrDensity, WrDensityDirective, wrDensityPrePaintScript } from 'ngwr/density';

@Component({ imports: [WrDensityDirective] })
export class MyComponent {}

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'

Active density: md

ngwrdensity

Per-subtree override

Put [wrDensity] on an element to give its subtree its own density.

scoped
<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

NameDescriptionTypeDefault
WrDensityInjectable service.service—
currentActive 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 property1

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.

VariableDefaultDeclared on
--wr-density-gap1:root +4 variant overrides
--wr-density-x1:root +4 variant overrides
--wr-density-y1:root +4 variant overrides

Dependencies

Built onWrStorage

See also