Overview

attr(map) and style(map) are element directives that apply a record of attributes or CSS properties and update only what changed.

Both accept plain values and tuple forms: [condition, value] (apply when truthy) and [condition, a, b] (ternary). style also accepts CSS custom properties like "--token".

attr / style vs native bindings

API
Use when
Notes
attr=${val} / ?attr One attribute Native lit-html bindings — great for single attrs.
${attr({…})} Many attrs / conditionals Boolean false removes the attribute (never sets the string 'false').
style="…${x}…" Simple inline String rebuild each render.
${style({…})} Dynamic map Merges properties; clears previously owned keys that become null/undefined.

attr and style directives

attr sets HTML attributes (including boolean ones like disabled) and style applies inline CSS properties — both update incrementally on every render.

import { html, atom, attr, style, renderApp } from 'mates';

const App = () => {
const disabled = atom(false);
const color = atom('#00b3a8');
const size = atom(18);

return () => html`
<div class="m-col m-gap">
<p class="label">attr directive</p>
<input
${attr({
type: 'text',
placeholder: 'Type something…',
disabled: disabled(),
'aria-label': 'Demo input',
})}
/>
<label>
<input
type="checkbox"
.checked=${disabled()}
@change=${e => disabled.set(e.target.checked)}
/>
Disable input
</label>

<p class="label m-t-5">style directive</p>
<div
${style({
color: color(),
fontSize: size() + 'px',
fontWeight: '700',
transition: 'color .2s, font-size .2s',
})}
>

Conditional attr tuple

Use [cond, value] to apply or remove an attribute.

import { html, atom, attr, renderApp } from 'mates';

const App = () => {
const busy = atom(false);
return () => html`
<div class="m-col m-gap">
<button
${attr({ 'aria-busy': [busy(), 'true'], disabled: busy() })}
@click=${() => busy.set(v => !v)}
>${busy() ? 'Busy…' : 'Idle'}</button>
</div>
`;
};
renderApp(App, document.getElementById('app'));