Built-in directives

Directives are functions that can extend Lit by customizing the way an expression renders. Lit includes a number of built-in directives to help with a variety of rendering needs:

DirectiveSummary

Styling

classMap

Assigns a list of classes to an element based on an object.

styleMap

Sets a list of style properties to an element based on an object.

Loops and Conditionals

when

Renders one of two templates based on a condition.

choose

Renders one of many templates based on a key value.

map

Transforms an iterable with a function.

repeat

Renders values from an iterable into the DOM, with optional keying to enable data diffing and DOM stability.

join

Interleave values from an iterable with a joiner value.

range

Creates an iterable of numbers in a sequence, useful for iterating a specific number of times.

ifDefined

Sets an attribute if the value is defined and removes the attribute if undefined.

Caching and change detection

cache

Caches rendered DOM when changing templates rather than discarding the DOM.

keyed

Associates a renderable value with a unique key, forcing the DOM to re-render if the key changes.

guard

Only re-evaluates the template when one of its dependencies changes.

live

Sets an attribute or property if it differs from the live DOM value rather than the last-rendered value.

Referencing rendered DOM

ref

Gets a reference to an element rendered in the template.

Rendering special values

templateContent

Renders the content of a <template> element.

unsafeHTML

Renders a string as HTML rather than text.

unsafeSVG

Renders a string as SVG rather than text.

Asynchronous rendering

until

Renders placeholder content until one or more promises resolve.

asyncAppend

Appends values from an AsyncIterable into the DOM as they are yielded.

asyncReplace

Renders the latest value from an AsyncIterable into the DOM as it is yielded.

Only bundle what you use. These are called "built-in" directives because they're part of the Lit package. But each directive is a separate module, so your app only bundles the directives you import.

You can also build your own directives. For more information, see Custom directives.

Sets a list of classes to an element based on an object.

Import
Signature
Usable location

class attribute expression (must be the only expression in the class attribute)

The classMap directive uses the element.classList API to efficiently add and remove classes to an element based on an object passed by the user. Each key in the object is treated as a class name, and if the value associated with the key is truthy, that class is added to the element. On subsequent renders, any previously set classes that are falsy or no longer in the object are removed.

The classMap must be the only expression in the class attribute, but it can be combined with static values:

Explore classMap more in the playground.

Sets a list of style properties to an element based on an object.

Import
Signature
Usable location

style attribute expression (must be the only expression in the style attribute)

The styleMap directive uses the element.style API to efficiently add and remove inline styles to an element based on an object passed by the user. Each key in the object is treated as a style property name, the value is treated as the value for that property. On subsequent renders, any previously set style properties that are undefined or null are removed (set to null).

For CSS properties that contain dashes, you can either use the camel-case equivalent, or put the property name in quotes. For example, you can write the CSS property font-family as either fontFamily or 'font-family':

Refer to CSS custom properties such as --custom-color, by placing the whole property name in quotes:

The styleMap must be the only expression in the style attribute, but it can be combined with static values:

Explore styleMap more in the playground.

Renders one of two templates based on a condition.

Import
Signature
Usable location

Any

When condition is true, returns the result of calling trueCase(), else returns the result of calling falseCase() if falseCase is defined.

This is a convenience wrapper around a ternary expression that makes it a little nicer to write an inline conditional without an else.

Chooses and evaluates a template function from a list of cases based on matching the given value to a case.

Import
Signature
Usable location

Any

Cases are structured as [caseValue, func]. value is matched to caseValue by strict equality. The first match is selected. Case values can be of any type including primitives, objects, and symbols.

This is similar to a switch statement, but as an expression and without fallthrough.

Returns an iterable containing the result of calling f(value) on each value in items.

Import
Signature
Usable location

Any

map() is a simple wrapper around a for/of loop that makes working with iterables in expressions a bit easier. map() always updates any DOM created in place - it does not do any diffing or DOM movement. If you need that see repeat. map() is smaller and faster than repeat(), so if you don't need diffing and DOM stability, prefer map().

Renders values from an iterable into the DOM, with optional keying to enable data diffing and DOM stability.

Import
Signature
Usable location

Child expression

Repeats a series of values (usually TemplateResults) generated from an iterable, and updates those items efficiently when the iterable changes. When the keyFn is provided, key-to-DOM association is maintained between updates by moving generated DOM when required, and is generally the most efficient way to use repeat since it performs minimum unnecessary work for insertions and removals.

If you're not using a key function, you should consider using map().

If no keyFn is provided, repeat will perform similar to a simple map of items to values, and DOM will be reused against potentially different items.

See When to use map or repeat for a discussion of when to use repeat and when to use standard JavaScript flow control.

Explore repeat more in the playground.

Returns an iterable containing the values in items interleaved with the joiner value.

Import
Signature
Usable location

Any

Returns an iterable of integers from start to end (exclusive) incrementing by step.

Import
Signature
Usable location

Any

Sets an attribute if the value is defined and removes the attribute if undefined.

Import
Signature
Usable location

Attribute expression

For AttributeParts, sets the attribute if the value is defined and removes the attribute if the value is undefined (undefined or null). For other part types, this directive is a no-op.

When more than one expression exists in a single attribute value, the attribute will be removed if any expression uses ifDefined and evaluates to undefined/null. This is especially useful for setting URL attributes, when the attribute should not be set if required parts of the URL are not defined, to prevent 404's.

Explore ifDefined more in the playground.

Caches rendered DOM when changing templates rather than discarding the DOM. You can use this directive to optimize rendering performance when frequently switching between large templates.

Import
Signature
Usable location

Child expression

When the value passed to cache changes between one or more TemplateResults, the rendered DOM nodes for a given template are cached when they're not in use. When the template changes, the directive caches the current DOM nodes before switching to the new value, and restores them from the cache when switching back to a previously-rendered value, rather than creating the DOM nodes anew.

When Lit re-renders a template, it only updates the modified portions: it doesn't create or remove any more DOM than needed. But when you switch from one template to another, Lit removes the old DOM and renders a new DOM tree.

The cache directive caches the generated DOM for a given expression and input template. In the example above, it caches the DOM for both the summaryView and detailView templates. When you switch from one view to another, Lit swaps in the cached version of the new view and updates it with the latest data. This can improve rendering performance when these views are frequently switched.

Explore cache more in the playground.

Associates a renderable value with a unique key. When the key changes, the previous DOM is removed and disposed before rendering the next value, even if the value—such as a template—is the same.

Import
Signature
Usable location

Any expression

keyed is useful when you're rendering stateful elements and you need to ensure that all state of the element is cleared when some critical data changes. It essentially opts-out of Lit's default DOM reuse strategy.

keyed is also useful in some animation scenarios if you need to force a new element for "enter" or "exit" animations.

Only re-evaluates the template when one of its dependencies changes, to optimize rendering performance by preventing unnecessary work.

Import
Signature
Usable location

Any expression

Renders the value returned by valueFn, and only re-evaluates valueFn when one of the dependencies changes identity.

Where:

  • dependencies is an array of values to monitor for changes.
  • valueFn is a function that returns a renderable value.

guard is useful with immutable data patterns, by preventing expensive work until data updates.

In this case, the expensive calculateSHA function is only run when the value property changes.

Explore guard more in the playground.

Sets an attribute or property if it differs from the live DOM value rather than the last-rendered value.

Import
Signature
Usable location

Attribute or property expression

When determining whether to update the value, checks the expression value against the live DOM value, instead of Lit's default behavior of checking against the last set value.

This is useful for cases where the DOM value may change from outside of Lit. For example, when using an expression to set an <input> element's value property, a content editable element's text, or to a custom element that changes its own properties or attributes.

In these cases if the DOM value changes, but the value set through Lit expression hasn't, Lit won't know to update the DOM value and will leave it alone. If this is not what you want—if you want to overwrite the DOM value with the bound value no matter what—use the live() directive.

live() performs a strict equality check against the live DOM value, and if the new value is equal to the live value, does nothing. This means that live() should not be used when the expression will cause a type conversion. If you use live() with an attribute expression, make sure that only strings are passed in, or the expression will update every render.

Explore live more in the playground.

Renders the content of a <template> element.

Import
Signature
Usable location

Child expression

Lit templates are encoded in Javascript, so that they can embed Javascript expressions that make them dynamic. If you have a static HTML <template> that you need to include in your Lit template, you can use the templateContent directive to clone the template content and include it in your Lit template. As long as the template element reference does not change between renders, subsequent renders will no-op.

Note, the template content should be developer-controlled and must not be created using an untrusted string. Examples of untrusted content include query string parameters and values from user inputs. Untrusted templates rendered with this directive could lead to cross-site scripting (XSS) vulnerabilities.

Explore templateContent more in the playground.

Renders a string as HTML rather than text.

Import
Signature
Usable location

Child expression

A key feature of Lit's templating syntax is that only strings originating in template literals are parsed as HTML. Because template literals can only be authored in trusted script files, this acts as a natural safeguard against XSS attacks injecting untrusted HTML. However, there may be cases when HTML not originating in script files needs to be rendered in a Lit template, for example trusted HTML content fetched from a database. The unsafeHTML directive will parse such a string as HTML and render it in a Lit template.

Note, the string passed to unsafeHTML must be developer-controlled and not include untrusted content. Examples of untrusted content include query string parameters and values from user inputs.

Untrusted content rendered with this directive could lead to cross-site scripting (XSS), CSS injection, data exfiltration, etc. vulnerabilities. unsafeHTML uses innerHTML to parse the HTML string, so the security implications are the same as innerHTML, as documented on MDN.

Explore unsafeHTML more in the playground.

Renders a string as SVG rather than text.

Import
Signature
Usable location

Child expression

Similar to with unsafeHTML, there may be cases when SVG content not originating in script files needs to be rendered in a Lit template, for example trusted SVG content fetched from a database. The unsafeSVG directive will parse such a string as SVG and render it in a Lit template.

Note, the string passed to unsafeSVG must be developer-controlled and not include untrusted content. Examples of untrusted content include query string parameters and values from user inputs. Untrusted content rendered with this directive could lead to cross-site scripting (XSS) vulnerabilities.

Explore unsafeSVG more in the playground.

Retrieves a reference to an element rendered into the DOM.

Import
Signature
Usable location

Element expression

Although most DOM manipulation in Lit can be achieved declaratively using templates, advanced situations may required getting a reference to an element rendered in the template and manipulating it imperatively. Common examples of when this may be useful include focusing a form control or calling an imperative DOM manipulation library on a container element.

When placed on an element in the template, the ref directive will retrieve a reference to that element once rendered. The element reference may be retrieved in one of two ways: either by passing a Ref object or by passing a callback.

A Ref object acts as a container for a reference to the element, and can be created using the createRef helper method found in the ref module. After rendering, the Ref's value property will be set to the element, where it can be accessed in post-render lifecycle like updated.

A ref callback can also be passed to the ref directive. The callback will be called each time the referenced element changes. If a ref callback is rendered to a different element position or is removed in a subsequent render, it will first be called with undefined, followed by another call with the new element it was rendered to (if any). Note that in a LitElement, the callback will be called bound to the host element automatically.

Explore ref more in the playground.

Renders placeholder content until one or more promises resolve.

Import
Signature
Usable location

Any expression

Takes a series of values, including Promises. Values are rendered in priority order, with the first argument having the highest priority and the last argument having the lowest priority. If a value is a Promise, a lower-priority value will be rendered until it resolves.

The priority of values can be used to create placeholder content for async data. For example, a Promise with pending content can be the first (highest-priority) argument, and a non-promise loading indicator template can be used as the second (lower-priority) argument. The loading indicator renders immediately, and the primary content will render when the Promise resolves.

Explore until more in the playground.

Appends values from an AsyncIterable into the DOM as they are yielded.

Import
Signature
Usable location

Child expression

asyncAppend renders the values of an async iterable, appending each new value after the previous. Note that async generators also implement the async iterable protocol, and thus can be consumed by asyncAppend.

Explore asyncAppend more in the playground.

Renders the latest value from an AsyncIterable into the DOM as it is yielded.

Import
Signature
Usable location

Any expression

Similar to asyncAppend, asyncReplace renders the values of an async iterable, replacing the previous value with each new value.

Explore asyncReplace more in the playground.