render method is called.
Expressions can only be placed in specific locations in the template, and how an expression is interpreted depends on where it appears. Expressions inside the element tag itself affect the element. Expressions inside the element's content, where child nodes go, render child nodes or text.
Valid values for expressions differ based on where the expression occurs. Generally all expressions accept primitive values like strings and numbers, and some expressions support additional value types. In addition, all expressions can accept directives, which are special functions that customize the way an expression is processed and rendered. See Custom directives for more information.
Here's a quick reference followed by more detailed information about each expression type.
This basic example shows a variety of different kinds of expressions.
The following sections describe each kind of expression in more detail. For more information about the structure of templates, see Well-formed HTML and Valid expression locations.
Child expressionsPermalink to “Child expressions”
An expression that occurs between the start and end tags of an element can add child nodes to the element. For example:
Expressions in the child position can take many kinds of values:
- Primitive values likes strings, numbers, and booleans.
TemplateResultobjects created with the
htmlfunction (or the
svgfunction, if the expression is inside an
- DOM nodes.
- The sentinel values
- Arrays or iterables of any of the supported types.
Primitive valuesPermalink to “Primitive values”
Lit can render almost all primitive values and converts them to strings when interpolated into text content.
Numbers values like
5 will render the string
'5'. Bigints are treated similarly.
A boolean value
true will render
false will render
'false', but rendering a boolean like this is uncommon. Instead booleans are typically used in conditionals to render other appropriate values. For more on conditionals, see Conditionals.
The empty string
undefined are specially treated and render nothing. See Removing child content for more information.
Symbol values cannot be converted to strings and throw when placed in child expressions.
Sentinel valuesPermalink to “Sentinel values”
Lit supplies a couple of special sentinel values that can be used in child expressions.
noChange sentinel value does not change the expression's existing value. It is typically used in custom directives. See Signaling no change for more information.
nothing sentinel renders nothing. See Removing child content for more information.
TemplatesPermalink to “Templates”
Since an expression in the child position can return a
TemplateResult, you can nest and compose templates:
For more on conditionals, see Conditionals.
DOM nodesPermalink to “DOM nodes”
Any DOM node can be passed to a child expression. Typically DOM nodes should be rendered by specifying a template using
html, but a DOM node can be directly rendered like this when needed. The node is attached to the DOM tree at that point, and so removed from any current parent:
Arrays or iterables of any of the supported typesPermalink to “Arrays or iterables of any of the supported types”
map method to create repeating templates and lists. For examples, see Lists.
Removing child contentPermalink to “Removing child content”
undefined, the empty string
'', and Lit's nothing sentinel value remove any previously rendered content and render no node.
Setting or removing child content is often done based on a condition. See Conditionally rendering nothing for more information.
Rendering no node can be important when an expression is a child of an element with Shadow DOM that includes a
slot with fallback content. Rendering no node ensures the fallback content is rendered. See fallback content for more information.
Attribute expressionsPermalink to “Attribute expressions”
In addition to using expressions to add child nodes, you can use them to set an elements's attributes and properties, too.
By default, an expression in the value of an attribute sets the attribute:
Since attribute values are always strings, the expression should return a value that can be converted into a string.
If the expression makes up the entire attribute value, you can leave off the quotes. If the expression makes up only part of the attribute value, you need to quote the entire value:
Note, some primitive values are handled specially in attributes. Boolean values are converted to strings so, for example,
null render to an attribute as an empty string.
Boolean attributesPermalink to “Boolean attributes”
To set a boolean attribute, use the
? prefix with the attribute name. The attribute is added if the expression evaluates to a truthy value, removed if it evaluates to a falsy value:
Removing an attributePermalink to “Removing an attribute”
Sometimes you want to set an attribute only under certain conditions, and otherwise remove the attribute. For common "boolean attributes" like
hidden where you want to set the attribute to an empty string for a truthy value and remove it otherwise, use a boolean attribute. Sometimes, however, you might require a different condition for adding or removing an attribute.
For example, consider:
this.imageFile is not defined, the
src attribute should not be set or an invalid network request will occur.
Lit's nothing sentinel value addresses this by removing the attribute when any expression in the attribute value evaluates to
In this example both the
this.imageFile properties must be defined for the
src attribute to be set. The
?? nullish coalescing operator returns the right-hand value if the left-hand value is
Lit also provides an ifDefined directive which is sugar for
value ?? nothing.
You might also want to remove the attribute if the value is not truthy so that values of
false or empty string
'' remove the attribute. For example, consider an element that has default value for
this.ariaLabel of empty string
In this example the
aria-label attribute is rendered only if
this.ariaLabel is not an empty string.
Setting or removing an attribute is often done based on a condition. See Conditionally rendering nothing for more information.
Property expressionsPermalink to “Property expressions”
. prefix and the property name:
You can use this syntax to pass complex data down the tree to subcomponents. For example, if you have a
my-list component with a
listItems property, you could pass it an array of objects:
Note that the property name in this example—
listItems—is mixed case. Although HTML attributes are case-insensitive, Lit preserves the case for property names when it processes the template.
For more information about component properties, see Reactive properties.
Event listener expressionsPermalink to “Event listener expressions”
Templates can also include declarative event listeners. Use the prefix
@ followed by the event name. The expression should evaluate to an event listener.
This is similar to calling
addEventListener('click', this.clickHandler) on the button element.
The event listener can be either a plain function, or an object with a
handleEvent method — the same as the
listener argument to the standard
In a Lit component, the event listener is automatically bound to the component, so you can use the
this value inside the handler to refer to the component instance.
For more information about component events, see Events.
Element expressionsPermalink to “Element expressions”
You can also add an expression that accesses an element instance, instead of a single property or attribute on an element:
Element expressions only work with directives. Any other value type in an element expression is ignored.
One built-in directive that can be used in an element expression is the
ref directive. It provides a reference to the rendered element.
See ref for more information.
Well-formed HTMLPermalink to “Well-formed HTML”
Lit templates must be well-formed HTML. The templates are parsed by the browser's built-in HTML parser before any values are interpolated. Follow these rules for well-formed templates:
Templates must be well-formed HTML when all expressions are replaced by empty values.
Templates can have multiple top-level elements and text.
Templates should not contain unclosed elements—they will be closed by the HTML parser.
Because the browser's built-in parser is very lenient, most cases of malformed templates are not detectable at runtime, so you won't see warnings—just templates that don't behave as you expect. We recommend using linting tools and IDE plugins to find issues in your templates during development.
Valid expression locationsPermalink to “Valid expression locations”
Expressions can only occur where you can place attribute values and child elements in HTML.
Element expressions can occur inside the opening tag after the tag name:
Invalid locationsPermalink to “Invalid locations”
Expressions should generally not appear in the following locations:
Where tag or attribute names would appear. Lit does not support dynamically changing values in this position and will error in development mode.
<template>element content (attribute expressions on the template element itself are allowed). Lit does not recurse into template content to dynamically update expressions and will error in development mode.
<textarea>element content (attribute expressions on the textarea element itself are allowed). Note that Lit can render content into textarea, however editing the textarea will break references to the DOM that Lit uses to dynamically update, and Lit will warn in development mode. Instead, bind to the
.valueproperty of textarea.
Similarly, inside elements with the
contenteditableattribute. Instead, bind to the
.innerTextproperty of the element.
Inside HTML comments. Lit will not update expressions in comments, and the expressions will instead be rendered with a Lit token string. However, this will not break subsequent expressions, so commenting out blocks of HTML during development that may contain expressions is safe.
<style>elements when using the ShadyCSS polyfill. See Expressions and style elements for more details.
Note that expressions in all the invalid cases above are valid when using static expressions, although these should not be used for performance-sensitive updates due to the inefficiencies involved (see below).
Static expressionsPermalink to “Static expressions”
Static expressions return special values that are interpolated into the template before the template is processed as HTML by Lit. Because they become part of the template's static HTML, they can be placed anywhere in the template - even where expressions would normally be disallowed, such as in attribute and tag names.
To use static expressions, you must import a special version of the
svg template tags from Lit's
static-html module contains
svg tag functions which support static expressions and should be used instead of the standard versions provided in the
lit module. Use the
literal tag function to create static expressions.
You can use static expressions for configuration options that are unlikely to change or for customizing parts of the template you cannot with normal expressions - see the section on Valid expression locations for details. For example, a
my-button component might render a
<button> tag, but a subclass might render an
<a> tag, instead. This is a good place to use a static expression because the setting does not change frequently and customizing an HTML tag cannot be done with a normal expression.
Changing the value of static expressions is expensive. Expressions using
literal values should not change frequently, as they cause a new template to be re-parsed and each variation is held in memory.
In the example above, if the template re-renders and
this.active change, Lit updates the template efficiently, only changing the affected expressions. However, if
this.activeAttribute change, since they are static values tagged with
literal, an entirely new template is created; the update is inefficient since the DOM is completely re-rendered. In addition, changing
literal values passed to expressions increases memory use since each unique template is cached in memory to improve re-render performance.
For these reasons, it's a good idea keep changes to expressions using
literal to a minimum and avoid using reactive properties to change
literal values, since reactive properties are intended to change.
Template structurePermalink to “Template structure”
After static values have been interpolated, the template must be well-formed like normal Lit templates, otherwise the dynamic expressions in the template might not function properly. See the Well-formed HTML section for more information.
Non-literal staticsPermalink to “Non-literal statics”
In rare cases, you may need to interpolate static HTML into a template that is not defined in your script, and thus cannot be tagged with the
literal function. For these cases, the
unsafeStatic() function can be used to create static HTML based on strings from non-script sources.
Only for trusted content. Note the use of unsafe in
unsafeStatic(). The string passed to
unsafeStatic() must be developer-controlled and not include untrusted content, because it will be parsed directly as HTML with no sanitization. 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.
Note that the behavior of using
unsafeStatic carries the same caveats as
literal: because changing values causes a new template to be parsed and cached in memory, they should not change frequently.