# Technical Documentation: lit/lit-element

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/lit/lit-element)

### Overview (`README.md`)

# LitElement

LitElement is simple base class for creating fast, lightweight web components with [lit-html](https://lit-html.polymer-project.org/).

[](https://github.com/lit/lit-element/actions/workflows/tests.yml?query=branch%3Amaster)
[](https://www.npmjs.com/package/lit-element)
[](https://lit.dev/slack-invite/)
[](https://github.com/web-padawan/awesome-lit)

## Looking for Lit?

LitElement is now part of the [Lit library monorepo](https://github.com/lit/lit). Lit 2 includes lit-html 2.x and LitElement 3.x. 

This repo contains the code for LitElement 2.x.

## Documentation

For LitElement 2.x documentation, see the [legacy documentation site](https://lit-element.polymer-project.org).

For Lit 2, the next version of LitElement and lit-html, see the [Lit site](https://lit.dev). 

## Overview

LitElement uses [lit-html](https://lit-html.polymer-project.org/) to render into the
element's [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM)
and adds API to help manage element properties and attributes. LitElement reacts to changes in properties
and renders declaratively using `lit-html`. See the [lit-html guide](https://lit-html.polymer-project.org/guide)
for additional information on how to create templates for lit-element.

```ts
import {LitElement, html, css, customElement, property} from 'lit-element';

// This decorator defines the element.
@customElement('my-element')
export class MyElement extends LitElement {

  // This decorator creates a property accessor that triggers rendering and
  // an observed attribute.
  @property()
  mood = 'great';

  static styles = css`
    span {
      color: green;
    }`;

  // Render element DOM by returning a `lit-html` template.
  render() {
    return html`Web Components are <span>${this.mood}</span>!`;
  }

}
```

```html
<my-element mood="awesome"></my-element>
```

Note, this example uses decorators to create properties. Decorators are a proposed
standard currently available in [TypeScript](https://www.typescriptlang.org/) or [Babel](https://babeljs.io/docs/en/babel-plugin-proposal-decorators). LitElement also supports a [vanilla JavaScript method](https://lit-element.polymer-project.org/guide/properties#declare) of declaring reactive properties.

## Examples

  * Runs in all [supported](#supported-browsers) browsers: [Glitch](https://glitch.com/edit/#!/hello-lit-element?path=index.html)

  * Runs in browsers with [JavaScript Modules](https://caniuse.com/#search=modules): [Stackblitz](https://stackblitz.com/edit/lit-element-demo?file=src%2Fmy-element.js), [JSFiddle](https://jsfiddle.net/sorvell1/801f9cdu/), [JSBin](http://jsbin.com/vecuyan/edit?html,output),
[CodePen](https://codepen.io/sorvell/pen/RYQyoe?editors=1000).

  * You can also copy [this HTML file](https://gist.githubusercontent.com/sorvell/48f4b7be35c8748e8f6db5c66d36ee29/raw/67346e4e8bc4c81d5a7968d18f0a6a8bc00d792e/index.html) into a local file and run it in any browser that supports [JavaScript Modules]((https://caniuse.com/#search=modules)).

## Installation

From inside your project folder, run:

```bash
$ npm install lit-element
```

To install the web components polyfills needed for older browsers:

```bash
$ npm i -D @webcomponents/webcomponentsjs
```

## Supported Browsers

The last 2 versions of all modern browsers are supported, including
Chrome, Safari, Opera, Firefox, Edge. In addition, Internet Explorer 11 is also supported.

Edge and Internet Explorer 11 require the web components polyfills.

## Forward Compatibility With Lit 2 

Lit 2 (LitElement 3.0) has a few breaking changes and deprecations that have been back-ported to LitElement 2.5 in order to ease upgrading.

To prepare for Lit 2, update these APIs:

| LitElement 2.4         | LitElement 2.5/Lit 2  |
|------------------------|-----------------------|
| Decorator imports:<br>`import {customElement} from 'lit-element';` | `import {customElement} from 'lit-element/decorators.js';`
| `@internalProperty() foo;`  | `@state() foo;`            |
| Override `_getUpdateComplete()` | Override `getUpdateComplete()` |
| Shadow root options:</br> Override `createRenderRoot()`. | Add `static shadowRootOptions`.
| `import {UpdatingElement} from 'lit-element';` |  `import {ReactiveElement} from 'lit-element';`  |
## Contributing

Please see [CONTRIBUTING.md](./CONTRIBUTING.md).

---

### Overview (`docs/README.md`)

## lit-element Documentation 

This folder holds the source for the lit-element documentation site. Guides are written in Markdown, and the site is built using the Jekyll static site generator. 
 
This section describes how to build the documentation site.

### Prerequisites

To build the documentation site, you need Jekyll, Node, npm, and Polymer CLI.

If you already have Ruby and the gem pacakge manager, run the following command to install Jekyll:

`gem install bundler jekyll`

For more information, see [the Jekyll website](https://jekyllrb.com/).

To install Polymer CLI: 

`npm install polymer-cli`

Previewing the docs requires the [App Engine Standard Environment for Python 2.7](https://cloud.google.com/appengine/docs/standard/python/quickstart). 

### Setup

1. Clone or download a copy of this repo.

2. Install npm dependencies for the docs site.

    ```
    cd lit-element/docs
    npm install
    ```

### Building and previewing

To build the documentation site and preview it from a local server:

```
cd docs
npm run build
npm run serve
```

Point a browser at [localhost:8080](localhost:8080) to preview the site.
To use a different port, run:

```
npm run serve -- --port <PORTNUMBER>
```

The generated API docs are checked in, so you don't need to build the 
API docs unless you're making changes to the doc comments in the lit-element source.

To regenerate the API docs and rebuild the  site, run the following command:

`npm run build-all`

### Deployment

To build and deploy a new version of the site:

```bash
npm run deploy
```

(You must have permission to update the App Engine project to deploy the site.)

The site is staged at a new URL (for example, `https://20181207t151022-dot-polymer-lit-element.appspot.com`). When ready, use the App Engine console to migrate traffic to the new version.

Sometimes it's useful to stage to a specific, named version. For example, when 
iterating on a new doc or design change, you may want to stage to an easily-to-remember
version name, like `new-tooling-section`. 

To push to a named App Engine version, specify the version on the command line:

```bash
npm run deploy -- --version=<VERSION>
```

This command stages the docs at `https://<VERSION>-dot-polymer-lit-element.appspot.com`.

By specifying the version on the command line,  you can update an existing staged version.

To make a staged version live, migrate traffic in the App Engine console or from the 
command line:

```bash
gcloud app services set-traffic --splits <VERSION>=1
```

---

### Overview (`docs/_api/api-readme.md`)

# LitElement API Documentation

## Modules

### [lit-element](/api/modules/_lit_element_.html)

The main LitElement module, which defines the [`LitElement`](/api/classes/_lit_element_.litelement.html) base class and related APIs.

LitElement components can define a template and a set of observed properties. Changing an observed property triggers a re-render of the element.

Import [`LitElement`](/api/classes/_lit_element_.litelement.html) and [`html`](https://lit-element.polymer-project.org/api/modules/_lit_element_.html#html) from this module to create a component:

```js
import {LitElement, html} from 'lit-element';

class MyElement extends LitElement {

  // Declare observed properties
  static get properties() {
    return {
      adjective: {}
    }
  }
 
  constructor() {
    this.adjective = 'awesome';
  }

  // Define the element's template
  render() {
    return html`<p>your ${adjective} template here</p>`;
  }
}

customElements.define('my-element', MyElement);
```

`LitElement` extends [`UpdatingElement`](/api/classes/_lib_updating_element_.updatingelement.html) and adds lit-html templating.

### [lit-element/lib/updating-element.js](/api/modules/_lib_updating_element_.html)

```js
import {UpdatingElement} from 'lit-element/lib/updating-element.js';
```

Custom Element base class that supports declaring observable properties, reflecting attributes to properties, and the core update lifecycle methods.

If you want to build a custom element base class that includes these features but **not** lit-html templating, extend `UpdatingElement`.

---

### Index (`docs/index.md`)

---
layout: default
---

<header class="hero blm" markdown="0">
{% include topnav.html %}
<div class="blm-banner">
<p>
<a href="https://blacklivesmatter.com" target="_blank" rel="noopener noreferrer">Black Lives Matter.</a> Support the 
<a href="https://eji.org/" target="_blank" rel="noopener noreferrer">Equal Justice Initiative</a> and 
<a href="https://www.joincampaignzero.org/" target="_blank" rel="noopener noreferrer" >Campaign Zero</a>.</p> 
</div>
<div class="wrapper">
<div class="hero-title">{{ site.name }}</div>
<p class="hero-caption">{{ site.description }}</p>
<a class="hero-link link-with-arrow" href="{{ site.baseurl }}/guide">Get Started</a>
</div>
</header>

<section id="section-snippet">
<div class="wrapper">
<h1 class="title">
Easily Create Fast, Lightweight Web Components
</h1>

<div class="responsive-row">

<div class="fixed-width-caption">
<h3 class="description">LitElement makes it easy to define Web Components – ideal for sharing elements across your organization or building a UI design system.</h3>
<h3 class="description">Use your components anywhere you use HTML: in your main document, a CMS, Markdown, or a framework like React or Vue.</h3>
</div>


<div>
```js
{% include projects/index-typescript/simple-greeting.ts %}
```
```html
<simple-greeting name="Everyone"></simple-greeting>
```
</div>
</div>

<div class="inline-action-buttons">
{% include project.html label="Launch Code Editor (TypeScript)" folder="index-typescript" openFile="simple-greeting.ts" %}
{% include project.html label="Launch Code Editor (JavaScript)" folder="index" openFile="simple-greeting.js" %}
</div>

</div>
</section>

<section>
<div class="wrapper">

<h1 class="title">Why use LitElement?</h1>

<div class="responsive-row">
<div style="flex: 1">

<h2 class="caption">Delightfully declarative</h2>

LitElement's simple, familiar development model makes it easier than ever to build Web Components.

Express your UI declaratively, as a function of state. No need to learn a custom templating language – you can use the full power of JavaScript in your templates. Elements update automatically when their properties change.

</div>
<div style="flex: 1">

<h2 class="caption">Fast and light</h2>

Whether your end users are in emerging markets or Silicon Valley, they’ll appreciate that LitElement is extremely fast.

LitElement uses [lit-html](https://github.com/Polymer/lit-html) to define and render HTML templates. DOM updates are lightning-fast, because lit-html only re-renders the dynamic parts of your UI – no diffing required.

</div>
<div style="flex: 1">

<h2 class="caption">Seamlessly interoperable</h2>

LitElement follows the [Web Components standards](https://developer.mozilla.org/en-US/docs/Web/Web_Components), so your components will work with any framework.

LitElement uses Custom Elements for easy inclusion in web pages, and Shadow DOM for encapsulation. There’s no new abstraction on top of the web platform.

</div>
</div>
</div>
</section>


<section style="margin-bottom: 60px;">
<div class="wrapper">
<h1 class="title">Next Steps</h1>

<div class="responsive-row">

<div style="flex:1">
<h2 class="caption">One.</h2>
<p>[Try LitElement]({{ site.baseurl }}/try) in our live tutorial. You don’t need to install anything.</p>
</div>

<div style="flex:1">
<h2 class="caption">Two.</h2>
<p>When you’re ready to dive in, [set up LitElement locally]({{ site.baseurl }}/guide/start) and start building components!</p>
</div>

<div style="flex:1">
</div>

</div>
</div>
</section>

<section>
<div class="wrapper">

<h1 class="title">Browser Compatibility</h1>
<h2 class="description">LitElement works in all major browsers (Chrome, Firefox, IE, Edge, Safari, and Opera). </h2>
<div id="browser-thumbnails" style="margin-bottom: 20px;">
<img width="56" width="56" src="{{ site.baseurl }}/images/browsers/chrome_128x128.png" alt="chrome logo">
<img width="56" width="56" src="{{ site.baseurl }}/images/browsers/firefox_128x128.png" alt="firefox logo">
<img width="56" width="56" src="{{ site.baseurl }}/images/browsers/internet-explorer_128x128.png" alt="internet explorer logo">
<img width="56" width="56" src="{{ site.baseurl }}/images/browsers/edge_128x128.png" alt="edge logo">
<img width="56" width="56" src="{{ site.baseurl }}/images/browsers/safari_128x128.png" alt="safari logo">
<img width="56" width="56" src="{{ site.baseurl }}/images/browsers/opera_128x128.png" alt="opera logo">
</div>

</div>
</section>

---

###  Guide Index (`docs/_guide/index.md`)

---
layout: guide
title: Introduction
permalink: /guide
lit_dev_path: /docs/
---

{::options toc_levels="1..3" /}
* ToC
{:toc}

## What is LitElement?

LitElement is a simple base class for creating fast, lightweight web components that work in any web page with any framework.

LitElement uses [lit-html](https://lit-html.polymer-project.org/) to render into shadow DOM, and adds API to manage properties and attributes. Properties are observed by default, and elements update asynchronously when their properties change.

## Next steps

* [Getting Started](/guide/start): Set up LitElement and create a component.
* [Templates](/guide/templates): Write templates with lit-html syntax.
* [Properties](/guide/properties): Manage properties and attributes.
* [Lifecycle](/guide/lifecycle): Work with the LitElement lifecycle API.

---

###  Try Index (`docs/_try/index.md`)

---
layout: try
title: Try LitElement
permalink: /try
---

Try LitElement in live-editable code without installing anything. Build your first component, use it in a web page, and add style with CSS. 

This tutorial has live code samples that you can edit, like this:

{% include project.html folder="try/create/after" openFile="my-element.js" %}

Click **Preview** at any time to see your code in action. 

{:.alert .alert-info}
<div>

**If you're doing the tutorial in your local development environment, you'll need to make some changes to the code on this page.** The code samples on this page are written for the live StackBlitz editor. To work locally, see the [Getting Started page](/guide/start). 

</div>

[Next: 1. Create a component](/try/create)

---

###  Config.Yml (`docs/_config.yml`)

name: LitElement
description: A simple base class for creating fast, lightweight web components
exclude: [package.json, polymer.json, src, node_modules, package-lock.json]
markdown: kramdown
kramdown:
  parse_block_html: true
google_analytics: UA-39334307-23
projects: includes/projects
collections:
  includes:
    output: true
  guide:
    output: true
    permalink: /:collection/:title
  try: 
    output: true
    permalink: /:collection/:title
include:
  - "_*_.html"
  - "_*_.*.html"

---

### App.Yaml (`docs/app.yaml`)

runtime: python27
api_version: 1
threadsafe: yes

libraries:
- name: jinja2
  version: "2.6"
- name: webapp2
  version: "2.5.2"

default_expiration: "1m"

handlers:
- url: /api
  static_dir: api
  secure: always
- url: /build
  static_dir: build
  secure: always
- url: /css
  static_dir: css
  secure: always
- url: /images
  static_dir: images
  secure: always
- url: /includes
  static_dir: includes
  secure: always
- url: /.*
  script: main.app
  secure: always

---

### Package.Json (`docs/package.json`)

{
  "private": true,
  "scripts": {
    "build": "rimraf build && rollup -c && jekyll build",
    "build-all": "(cd .. && npm run gen-docs) && npm run build",
    "serve": "dev_appserver.py _site/app.yaml",
    "deploy": "npm run build && gcloud app deploy _site/app.yaml --project polymer-lit-element --no-promote",
    "deploy-staging": "npm run build && gcloud app deploy _site/app.yaml --project polymer-lit-element-staging"
  },
  "dependencies": {
    "@stackblitz/sdk": "^1.3.0",
    "@webcomponents/webcomponentsjs": "^2.1.3",
    "core-js": "^3.6.5",
    "lit-element": "^2.1.0",
    "regenerator-runtime": "^0.13.5"
  },
  "devDependencies": {
    "@babel/core": "^7.9.0",
    "@babel/preset-env": "^7.9.5",
    "@rollup/plugin-node-resolve": "^7.1.3",
    "polymer-cli": "^1.9.11",
    "rimraf": "^3.0.2",
    "rollup": "^2.6.1",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-commonjs": "^10.1.0",
    "rollup-plugin-copy": "^3.3.0",
    "rollup-plugin-filesize": "^7.0.0",
    "rollup-plugin-minify-html-literals": "^1.2.3",
    "rollup-plugin-node-resolve": "^5.2.0",
    "rollup-plugin-terser": "^5.3.0"
  }
}

---

### Polymer.Json (`docs/polymer.json`)

{
  "npm": true,
  "moduleResolution": "node",
  "entrypoint": "src/index.html",
  "shell": "src/index.js",
  "extraDependencies": [
    "node_modules/@webcomponents/webcomponentsjs/**"
  ],
  "builds": [{
    "name": "gh-pages",
    "bundle": true,
    "js": {
      "minify": true
    }
  }]
}

---

###  Data Guide.Yml (`docs/_data/guide.yml`)

title: LitElement Documentation
toc:
  introduction: 
    title: Introduction
    url: /guide
    toplevel: true
  getting started: 
    title: Getting Started
    url: /guide/start
    toplevel: true
  components: 
    title: Writing components
    header: true
  templates: 
    title: Templates
    url: /guide/templates
  styles:
    title: Styles
    desc: Style your elements with CSS.
    url: /guide/styles
  properties: 
    title: Properties
    url: /guide/properties
  events:
    title: Events
    url: /guide/events
  lifecycle: 
    title: Lifecycle
    url: /guide/lifecycle
  decorators: 
    title: Using decorators
    url: /guide/decorators
  tools: 
    title: Tools
    header: true
  publish: 
    title: Publish a component
    url: /guide/publish
  use: 
    title: Use a component
    url: /guide/use
  build: 
    title: Build for production
    url: /guide/build
  resources:
    title: Resources
    header: true
  community:
    title: Community
    url: /guide/community
  lithtml:
    title: lit-html Guides
    url: https://lit-html.polymer-project.org

---

###  Data Try.Yml (`docs/_data/try.yml`)

title: LitElement Documentation
toc:
  introduction: 
    title: Try LitElement
    url: /try
  create: 
    title: 1. Create
    url: /try/create
  properties: 
    title: 2. Properties
    url: /try/properties
  logic: 
    title: 3. Logic
    url: /try/logic
  events: 
    title: 4. Events
    url: /try/events
  style: 
    title: 5. Style
    url: /try/style

---

###  Guide Build (`docs/_guide/build.md`)

---
layout: guide
title: Build for production
slug: build
lit_dev_path: /docs/tools/production/
---

{::options toc_levels="1..3" /}
* ToC
{:toc}

When building an app that includes LitElement components, you can use common JavaScript build tools like [Rollup](https://rollupjs.org/) or [webpack](https://webpack.js.org/). 

We recommend Rollup because it's designed to work with the standard ES module format.

For a set of sample build configurations using Rollup, see [Building with Rollup](#building-with-rollup).

If you're interested in building with a different tool, or integrating LitElement into an existing build system, see [Build requirements](#build-requirements).

## Building with Rollup {#building-with-rollup}

There are many ways to set up Rollup to bundle your project. This section describes a two basic builds: 

*   A modern build that runs on evergreen browsers.
*   A universal build that runs on browsers back to Internet Explorer 11.

If you only need to support evergreen browsers, you can use the modern build by itself. If you want to support the widest range of browsers with a single build, you can use the backwards-compatible build.

The last part of this section discusses ways to use the two builds together to provide the faster, smaller modern build to browsers that support it while also supporting older browsers.

The example configurations here use the Shop demo app as an example. You can find all of the configurations described here in a branch of the Shop repo:

*  [https://github.com/Polymer/shop/tree/rollup-examples-v2](https://github.com/Polymer/shop/tree/rollup-examples-v2)

### Modern browser build {#modern-browser-build}

The modern browser build uses the following npm packages:

*   [`rollup`](https://www.npmjs.com/package/rollup). The Rollup bundler.
*   [`@rollup/plugin-node-resolve`](https://www.npmjs.com/package/@rollup/plugin-node-resolve). For resolving bare module specifiers. (See [Bare module specifiers](#bare-module-specifiers) for more information.)
*   [`rollup-plugin-terser`](https://www.npmjs.com/package/rollup-plugin-terser). To minify JavaScript. This isn't strictly required, but if you're bundling for production, you probably want to minify JavaScript.
*   [`rollup-plugin-copy`](https://www.npmjs.com/package/rollup-plugin-copy). For copying static assets to the build folder.
*   [`rollup-plugin-minify-html-literals`](https://www.npmjs.com/package/rollup-plugin-minify-html-literals). An optional optimization.

The Rollup configuration file for this build looks like this: \

```js
import resolve from '@rollup/plugin-node-resolve';
import { terser } from 'rollup-plugin-terser';
import minifyHTML from 'rollup-plugin-minify-html-literals';
import copy from 'rollup-plugin-copy';

// Static assets will vary depending on the application
const copyConfig = {
  targets: [
    { src: 'node_modules/@webcomponents', dest: 'build-modern/node_modules' },
    { src: 'images', dest: 'build-modern' },
    { src: 'data', dest: 'build-modern' },
    { src: 'index.html', dest: 'build-modern' },
  ],
};

// The main JavaScript bundle for modern browsers that support
// JavaScript modules and other ES2015+ features.
const config = {
  input: 'src/components/shop-app.js',
  output: {
    dir: 'build-modern/src/components',
    format: 'es',
  },
  plugins: [
    minifyHTML(),
    copy(copyConfig),
    resolve(),
  ],
  preserveEntrySignatures: false,
};

if (process.env.NODE_ENV !== 'development') {
  config.plugins.push(terser());
}

export default config;
```

#### Even simpler starter {#even-simpler-starter}

The [rollup-starter-app](https://github.com/rollup/rollup-starter-app) repo is a bare-bones starter project for building an app with Rollup. Although the repo doesn't include LitElement, it includes everything you need to bundle a LitElement app. If you want to use this project as a model for your own project, the most important files to look at are [`package.json`](https://github.com/rollup/rollup-starter-app/blob/master/package.json) and [`rollup.config.js`](https://github.com/rollup/rollup-starter-app/blob/master/rollup.config.js).

Note that in addition to the required plugins, [rollup-starter-app](https://github.com/rollup/rollup-starter-app) includes the CommonJS plugin, [@rollup/plugin-commonjs](https://www.npmjs.com/package/@rollup/plugin-commonjs). This plugin **isn't** required for LitElement, but can be useful if you want to import packages that are only distributed as CommonJS modules.

### Universal build {#universal-build}

The universal build is compiled to ES5 for older browsers (primarily IE11), and uses System.js as a module system (because older browsers don't support native JavaScript modules).

The universal build requires all of the packages used by the modern build, plus the following:

Babel:

*   [`@babel/core`](https://www.npmjs.com/package/@babel/core) 
*   [`@babel/cli`](https://babeljs.io/docs/en/babel-cli) 
*   [`@babel/preset-env`](https://babeljs.io/docs/en/babel-preset-env)

Polyfills used by Babel:

*   [`corejs`](https://www.npmjs.com/package/core-js)
*   [`regenerator-runtime`](https://www.npmjs.com/package/core-js)

Rollup plugins:

*   [`rollup-plugin-babel`](https://www.npmjs.com/package/@rollup/plugin-babel)
*   [`rollup-plugin-commonjs`](https://www.npmjs.com/package/@rollup/plugin-babel)

SystemJS module loader:

*   [`systemjs`](https://www.npmjs.com/package/systemjs)

If you just want to look at the code, here are the most important parts of the universal build:

*   Rollup configuration: [https://github.com/Polymer/shop/blob/rollup-examples-v2/rollup-universal.js](https://github.com/Polymer/shop/blob/rollup-examples-v2/rollup-universal.js)
*   `index.html`: [https://github.com/Polymer/shop/blob/rollup-examples-v2/index-universal.html](https://github.com/Polymer/shop/blob/rollup-examples-v2/rollup-universal.js)

The following sections describe aspects of the build. 

#### Babel build and polyfill bundle {#babel-build-and-polyfill-bundle}

Unlike the modern build, this build produces two separate bundles: one for the application code, and one for the polyfills required by Babel. Many Babel configurations produce a single bundle, which includes the polyfills as well as the application code. However, this can cause problems with other polyfills, including the Web Components polyfills. Loading the Babel polyfills separately, prior to loading the Web Components polyfills, allows both sets of polyfills to work correctly. The Babel polyfills are supplied as separate Common JS modules. 

#### Babel configuration {#babel-configuration}

The Babel configuration for this build is fairly small. It tells Babel to use the `@babel/preset-env` plugin to compile to code compatible with Internet Explorer 11.

```js
import babel from 'rollup-plugin-babel';
...

const babelConfig = {
  babelrc: false,
  ...{
    presets: [
      [
        '@babel/preset-env',
        {
          targets: {
            ie: '11',
          },
        },
      ],
    ],
  },
};
```

#### Application bundle {#application-bundle}

The Rollup configuration for the application bundle looks similar to the configuration for the model build:

```js
const configs = [
  // The main JavaScript bundle for older browsers that don't support
  // JavaScript modules or ES2015+.
  {
    input: ['src/components/shop-app.js'],
    output: {
      dir: 'build-universal/nomodule/src/components',
      format: 'systemjs',
    },
    plugins: [
      minifyHTML(),
      babel(babelConfig),
      resolve(),
      copy(copyConfig),
    ],
    preserveEntrySignatures: false,
  },
```

There are three main differences from the modern configuration:

*   It defines a `configs` array, instead of a single configuration object.
*   The main app bundle uses a different format (SystemJS instead of ES modules).
*   The main app bundle is compiled using the Babel plugin.

#### Polyfill bundle {#polyfill-bundle}

The entrypoint for the Babel polyfills bundle is a JavaScript file that imports two Common JS modules, which in turn import a number of smaller modules:

```js
import 'core-js/stable';
import 'regenerator-runtime/runtime';
```

The Rollup config bundles all of these modules into a single file:

```js
const configs = [

   ... 

  // Babel polyfills for older browsers that don't support ES2015+.
  {
    input: 'src/babel-polyfills-nomodule.js',
    output: {
      file: 'build-universal/nomodule/src/babel-polyfills-nomodule.js',
      format: 'iife',
    },
    plugins: [commonjs({ include: ['node_modules/**'] }), resolve()],
  },
];
```

#### Loading it all {#loading-it-all}

The `index.html` file loads all of the bundles in the correct order:

*   The Babel polyfills bundle.
*   The Web Components polyfill loader, which performs feature detection and loads any required Web Components polyfills.
*   The SystemJS loader.
*   The application bundle.

(The example `index.html` also includes a small application-specific polyfill for the `fetch` API.)

With extra material removed, the portion of `index.html` that loads script looks like this:

```html

<script src="nomodule/src/babel-polyfills-nomodule.js"></script>


<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>


<script src="node_modules/systemjs/dist/s.min.js"></script>


<script>
  System.import('./nomodule/src/components/shop-app.js');
</script>
```

### Using multiple builds {#using-multiple-builds}

In theory, it's ideal to deliver a modern ES6 bundle to modern browsers and the larger ES5 bundle to older browsers. In practice, this can be challenging. Here are three possible techniques for delivering different builds to different browsers:

*   `module` and `nomodule` script tags. 

*   Client-side feature detection. 

*   Differential serving. 

These approaches are discussed in the following sections.

#### Module/nomodule gambit

Since browsers that don't support modules won't execute module scripts (`<script type="module">`), and browsers that support modules won't load `nomodule` scripts (`<script nomodule>`), you can include the legacy bundles using `nomodule`.  In practice, the browsers that support modules also support the other ES6 language features used by LitElement, and don't require transpilation.

You can see this in practice in the Shop example app. See the [`index-modnomod.html`](https://github.com/Polymer/shop/blob/rollup-examples-v2/index-modnomod.html) file.
The advantage of this technique is that it doesn't require any logic on the server side.

The main drawback to this technique is that Edge versions 16–18 support JavaScript modules, but _don't_ support dynamic imports. That's not an issue if your application can be packaged in a single bundle, but if you have a larger application that uses dynamic imports and you need to support older versions of Edge, this technique won't work for you. 

Another drawback is that IE 11 (and possibly some other older browsers) may download (but not execute) `<script type="module">` bundles, and Edge 16-18 may download (but not execute) `<script nomodule>` bundles. This represents a performance penalty on these older browsers.

#### Client-side feature detection

In this technique, the initial page load includes a small script that runs feature detection code and then imperatively loads one of the bundles. 

This is another technique that doesn't require any server logic. However, it can introduce delays, since the browser won't start downloading the application bundle until after the initial JavaScript payload has downloaded and executed. 

#### Differential serving

In this technique, the server uses the User-Agent request header to determine which bundle to serve to the browser. This technique (also called "browser sniffing") has drawbacks. It's less correct than client-side feature detection, in that it relies on a static list of features supported by each browser. Also, some browsers may send an incorrect User-Agent header. However, it tends to have a performance advantage over the other approaches, since the browser only receives the bundles it needs.

The [prpl-server](https://github.com/Polymer/prpl-server) project is a Node.js web server that supports differential serving. 

## Build requirements {#build-requirements}

This section describes the requirements for building applications using LitElement. Use this section if you're creating your own build setup.

LitElement is packaged as a set of ES modules, written in modern JavaScript (ES 2017). These are supported natively in modern browsers (Chrome, Safari, Firefox, and Edge, for example). LitElement also uses bare module specifiers, which are not supported by any browsers yet.

When building an app using LitElement, your build system will need to handle the following:

*   Resolving bare (or Node-style) module identifiers. LitElement uses bare module specifiers.
*   Transforming ES modules to another module system, if required, to support older browsers.
*   Transpiling modern JavaScript syntax to ES 5, if required, to support older browsers.

For older browsers, you'll also need to load certain polyfills:

*   Web Components polyfills
*   Dynamic imports polyfill. Required by browsers (in particular, Edge 16 through 18) that support static imports for ES modules, but not dynamic imports. 

### Bare module specifiers {#bare-module-specifiers}

LitElement uses bare module specifiers to import modules from the lit-html library, like this:

```js
import {html} from 'lit-html';
```

Browsers currently only support loading modules from URLs or relative paths, not bare names referring to e.g. an npm package, so the build system needs to handle them: either by transforming the specifier to one that works for ES modules in the browser, or by producing a different type of module as output.

Webpack automatically handles bare module specifiers; for Rollup, you'll need a plugin ([@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve)).

**Why bare module specifiers?** Bare module specifiers let you import modules without knowing exactly where the package manager has installed them. A standards proposal called [Import maps](https://github.com/WICG/import-maps) would let browsers support bare module specifiers. In the meantime, bare import specifiers can easily be transformed as a build step. There are also some polyfills and module loaders that support import maps. 

### Supporting older browsers {#supporting-older-browsers}

Supporting older browsers (specifically Internet Explorer 11), requires a number of extra steps:

*   Transpiling modern JavaScript syntax to ES 5.
*   Transforming ES modules to another module system.
*   Loading polyfills.
    *   Babel polyfills.
    *   Web Components polyfills.

You may need other polyfills depending on your application. 

#### Transpiling to ES5 {#transpiling-to-es5}

Rollup, webpack and other build tools have plugins to support transpiling modern JavaScript for older browsers. [Babel](https://babeljs.io/) is the most commonly used transpiler. 

Unlike some libraries, LitElement is delivered as a set of ES modules using modern JavaScript. When you build your app, you need to compile LitElement as well as your own code. 

If you have a build already set up, it may be configured to ignore the `node_modules` folder when transpiling. If this is the case, we recommend updating this to transpile LitElement and lit-html. For example, if you're using the [Rollup Babel plugin](https://github.com/rollup/rollup-plugin-babel), you might have a configuration like this to exclude the `node_modules` folder from transpilation:

```js
exclude: [ 'node_modules/**' ]
```

You can replace this with a rule to explicitly include folders to transpile:

```js
include: [ 'src/**', 'node_modules/lit-element/**', 'node_modules/lit-html/**']
```

Babel uses a set of helpers and polyfills for implementing various modern JavaScript features. Babel can package these polyfills in with your application code. However, this causes issues with the Web Components polyfills. To avoid issues, bundle the Babel polyfills separately. See [Polyfill bundle](#polyfill-bundle) for an example of building this bundle with Rollup, and see [Loading it all](#loading-it-all) for an example `index.html` showing the load order. 

**Why no ES5 build?** The LitElement npm package doesn't include an ES5 build because modern JavaScript is smaller and generally faster. When building an application, you can compile modern JavaScript down to create the exact build (or builds) you need based on the browsers you need to support. 

If LitElement included multiple builds, individual elements could end up depending on different builds of LitElement—resulting in multiple versions of the library being shipped down to the browser.


#### Transforming modules {#transforming-modules}

When producing output for IE11, there are three common output formats:

*   No modules (IIFE). Code is bundled as a single file, wrapped in an immediately-invoked function expression (IIFE).
*   AMD modules. Uses the Asynchronous Module Definition format; requires a module loader script, such as [require.js](https://requirejs.org/).
*   SystemJS modules. [SystemJS](https://github.com/systemjs/systemjs) is a module loader that defines its own module format. It also supports AMD, CommonJS, and standard JavaScript modules.

The IIFE format works fine if all of your code can be bundled into a single file. To use code splitting with older browsers like IE11, you'll need to produce output in either the AMD or SystemJS module format.

The universal build in the [Building with Rollup](#building-with-rollup) section uses SystemJS format. You can see an example of loading the main SystemJS module here:

[https://github.com/Polymer/shop/blob/rollup-examples-v2/index-universal.html#L109](https://github.com/Polymer/shop/blob/rollup-examples-v2/index-universal.html#L109)

#### Polyfills {#polyfills}

In addition to any application-specific polyfills, you'll need to load the Babel polyfills and the Web Components polyfills.

Note that the Babel polyfills should be bundled separately from the application bundle, and loaded before the Web Components polyfills. This is discussed in [Babel build and polyfill bundle](#babel-build-and-polyfill-bundle). To see an example of generating the Babel polyfill bundle in Rollup, see [Polyfill bundle](#polyfill-bundle). For an example of loading the bundles, see [Loading it all](#loading-it-all).



## Optimizations {#optimizations}

LitElement projects benefit from the same optimizations as other web projects:

*   Bundling (for example, using Rollup or webpack).
*   Code minification/optimization (Terser works well for LitElement, because it supports modern JavaScript).
*   Compression (such as gzip).

In addition, there are a few smaller optimizations that are more specific to LitElement:

*   Minify template literals. Lit-html templates are defined using template literals, which don't get processed by standard HTML minifiers. Adding a plugin that minifies template literals can result in a modest decrease in code size. (Unless your templates are very large, this is a small optimization).
*   Compile out shady-render. If you're _only_ supporting modern browsers, you can compile out the shady-render module used to support older browsers.

The example builds presented in [Building with Rollup](#building-with-rollup) include most of these optimizations.

### Code minification {#code-minification}

There are many options for code minification. Terser works well with the modern JavaScript used by LitElement. For more information, the [terser](https://www.npmjs.com/package/terser) package description is an excellent overview.

### Minify template literals {#minify-template-literals}

Lit-html templates are defined using template literals, which don't get processed by standard HTML minifiers. Adding a plugin that minifies template literals can result in a modest decrease in code size. (Unless your templates are very large, this is a small optimization).

Several packages are available to perform this optimization:

*   Rollup: [rollup-plugin-minify-html-literals](https://www.npmjs.com/package/rollup-plugin-minify-html-literals?activeTab=readme)
*   Webpack: [minify-template-literal-loader](https://www.npmjs.com/package/minify-template-literal-loader)


### Compile out the shady-render module {#compile-out-the-shady-render-module}

If you're building for modern browsers only, you can remove LitElement's built-in support for shady DOM, the shadow DOM polyfill, saving about 12KB of bundle size.

To do so, configure your build system to replace the `shady-render` module with the base `lit-html` module, which provides a generic version of `render`. This saves about 12KB from your bundle.

For a Rollup build:

1.  Install the `alias` plugin.

    ```bash
    npm i -D @rollup/plugin-alias
    ```

2.  Configure the alias plugin to replace references to the `shady-render` module with references to the main `lit-html` module. 

    ```js
    alias({
      entries: [{
        find: 'lit-html/lib/shady-render.js',
        replacement: 'node_modules/lit-html/lit-html.js'
      }]
    }),
    ```

For a webpack build:

*   Add the following resolve.alias setting to your webpack configuration:

    ```js
    resolve: {
      alias: {
        'lit-html/lib/shady-render.js': path.resolve(__dirname, './node_modules/lit-html/lit-html.js')
      }
    },
    ```

## TypeScript {#typescript}

The TypeScript language extends JavaScript by adding types and type checking. The TypeScript compiler, `tsc`, compiles TypeScript into standard JavaScript.

While it's possible to run the TypeScript compiler as part of the bundling process, we recommend running it separately, to generate an intermediate JavaScript version of your project. Because of issues with the TypeScript compiler's output for older browsers. **We recommend configuring TypeScript to output modern JavaScript (ES2017 target and ES modules).** 

For example, if you have a `tsconfig.json` file, you'd include the following options to output modern JavaScript:

```json
{
  "compilerOptions": {
    "target": "es2017",
    "module": "es2015",
    ...
```

Use this intermediate version as input to your build tools. To support older browsers, use Babel to recompile the intermediate, modern JavaScript version into backward-compatible JavaScript, as described in [Transpiling to ES5](#transpiling-to-es5) and [Transforming modules](#transforming-modules).

---

###  Guide Community (`docs/_guide/community.md`)

---
layout: guide
title: Community
slug: community
lit_dev_path: /docs/tools/publishing/
---

{::options toc_levels="1..3" /}
* ToC
{:toc}


There are many great resources and locations to learn about LitElement and web components,
share what you've built, and more. All community participation is subject to the Lit
<a href="https://github.com/lit/lit/blob/main/CODE_OF_CONDUCT.md">Code of Conduct</a>—be
excellent to each other!

*   <strong>Join us on <a href="https://lit.dev/slack-invite/">Slack</a>!</strong> The
    Lit & Friends Slack workspace has thousands of users discussing LitElement, web components, and related topics.
    Check out <code>#general</code>, <code>#beginners</code>, or
    <code>#tools</code> to get started.

*   Follow us on <a href="https://twitter.com/buildWithLit">Twitter</a>
    for the latest on Lit and web components. Many
    of our team members can be found tweeting about LitElement, lit-html,
    and the latest developments in the web platform.


*   On <a href="https://stackoverflow.com/tags/lit-element">StackOverflow</a> use
    the  <code><a href="https://stackoverflow.com/tags/lit-element">lit-element</a></code> or
    <code><a href="https://stackoverflow.com/tags/lit-html">lit-html</a></code> tags when
    looking for answers. You can also find help on underlying web standards like
    <a href="https://stackoverflow.com/tags/web-component">web components</a>, and try your
    hand at answering other people’s queries.

---

###  Guide Decorators (`docs/_guide/decorators.md`)

---
layout: guide
title: Using decorators
slug: decorators
lit_dev_path: /docs/components/decorators/
---

Decorators are special expressions that can alter the behavior of class, class method, and class field declarations. LitElement supplies a set of decorators that reduce the amount of boilerplate code you need to write when defining a component.

For example, the `@customElement` and `@property` decorators make a basic element definition more compact:

```js
import {LitElement, html, customElement, property} from 'lit-element';

@customElement('my-element')
class MyElement extends LitElement {

 // Declare observed properties
 @property()
 adjective = 'awesome';

 // Define the element's template
 render() {
   return html`<p>your ${this.adjective} template here</p>`;
 }
}
```

The `@customElement` decorator defines a custom element, equivalent to calling:

```js
customElements.define('my-element', MyElement);
```

The `@property` decorator declares a reactive property. The lines:

```js
 @property()
 adjective = 'awesome';
```

Are equivalent to:

```js
static get properties() {
  return {
    adjective: {}
  };
}

constructor() {
  this.adjective = 'awesome';
}
```

## Enabling decorators

To use decorators, you need to use a compiler such as Babel or the TypeScript compiler.

<div class="alert alert-info">

**The decorators proposal**. Decorators are a [stage 2 proposal](https://github.com/tc39/proposal-decorators) for addition to the ECMAScript standard, which means they're neither finalized nor implemented in browsers yet. Compilers like Babel and TypeScript provide support for proposed features like decorators by compiling them into standard JavaScript a browser can run.

</div>

### To use decorators with TypeScript

To use decorators with [TypeScript](https://www.typescriptlang.org/docs/handbook/decorators.html), enable the `experimentalDecorators` compiler option.

```json
"experimentalDecorators": true,
```

Enabling `emitDecoratorMetadata` is not required and not recommended.

### To use decorators with Babel

If you're compiling JavaScript with [Babel](https://babeljs.io/docs/en/), you can enable decorators by adding  the following plugins:

*   [`@babel/plugin-proposal-decorators`](https://babeljs.io/docs/en/babel-plugin-proposal-decorators). 
*   [`@babel/plugin-proposal-class-properties`](https://babeljs.io/docs/en/babel-plugin-proposal-class-properties)

To enable the plugins, you'd add code like this to your Babel configuration:

```js
plugins = [
  '@babel/plugin-proposal-class-properties',
  ['@babel/plugin-proposal-decorators', {decoratorsBeforeExport: true}],
];
```

## LitElement decorators

LitElement provides the following decorators:

*   [`@customElement`](https://lit-element.polymer-project.org/api/modules/_lit_element_.html#customelement). Define a custom element.
*   [`@eventOptions`](https://lit-element.polymer-project.org/api/modules/_lit_element_.html#eventoptions). Add event listener options for a declarative event listener.
*   [`@property`](https://lit-element.polymer-project.org/api/modules/_lit_element_.html#property) and [`internalProperty`](https://lit-element.polymer-project.org/api/modules/_lit_element_.html#internalproperty). Define properties.
*   [`@query`](https://lit-element.polymer-project.org/api/modules/_lit_element_.html#query), [`queryAll`](https://lit-element.polymer-project.org/api/modules/_lit_element_.html#queryAll), and [`queryAsync`](https://lit-element.polymer-project.org/api/modules/_lit_element_.html#queryAsync). Create a property getter that returns specific elements from your component's render root.
*   [`@queryAssignedNodes`](https://lit-element.polymer-project.org/api/modules/_lit_element_.html#queryAssignedNodes). Create a property getter that returns the children assigned to a specific slot. 


All of the decorators can be imported directly from the <code>lit-element</code> module.

```js
import {eventOptions} from 'lit-element';
```

---

###  Guide Events (`docs/_guide/events.md`)

---
layout: guide
title: Events
slug: events
lit_dev_path: /docs/components/events/
---

{::options toc_levels="1..3" /}
* ToC
{:toc}


## Where to add your event listeners

You need to add event listeners in a method that is guaranteed to fire before the event occurs. However, for optimal loading performance, you should add your event listener as late as possible.  

The most common ways to add an event listener:

* Declaratively, in  your component's template
* In the component constructor, for listeners added on the component itself.
* In the `connectedCallback`, for listeners that need to reference DOM outside the component (for example, `Window` or `Document`).
* After first paint, if you're adding a lot of listeners and first paint performance is critical.


### Add declarative event listeners

You can use lit-html `@event` bindings in your template to add event listeners to your component. 

**Example**

```js
render() {
  return html`<button @click="${this._handleClick}">`;
}
```

Declarative event listeners are added when the template is rendered. This is usually the best way to add listeners to elements in your templated DOM.

### Add event listeners in the constructor

If you need to listen for an event that might occur before your component has been added to DOM, you might need to add the event listener in your component's constructor. 

The component constructor is a good place to add event listeners on the host element itself.

**Example**

```js
constructor() {
  super();
  this.addEventListener('focus', this._handleFocus);
}
```

### Add event listeners in `connectedCallback`

`connectedCallback` is a lifecycle callback in the custom elements API. `connectedCallback` fires each time a custom element is appended into a document-connected element. See [the MDN documentation on using custom elements lifecycle callbacks](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#Using_the_lifecycle_callbacks) for more information.

If your component adds an event listener to anything except itself or its children–for example, to `Window`, `Document`, or some element in the main DOM–you should add the listener in `connectedCallback` and remove it in `disconnectedCallback`.

*   Removing the event listener in `disconnectedCallback` ensures that any memory allocated by your component will be cleaned up when your component is destroyed or disconnected from the page. 

*   Adding the event listener in `connectedCallback` (instead of, for example, the constructor or `firstUpdated`) ensures that your component will re-create its event listener if it is disconnected and subsequently reconnected to DOM.

**Example**

```js
connectedCallback() {
  super.connectedCallback();
  window.addEventListener('resize', this._handleResize);
}
disconnectedCallback() {
  window.removeEventListener('resize', this._handleResize);
  super.disconnectedCallback();
}
```

### Add event listeners after first paint

Sometimes, you may want to defer adding an event listener until after first paint—for example, if you're adding a lot of listeners and first paint performance is critical.

LitElement doesn't have a specific lifecycle callback called after first paint, but you can use this pattern with the `firstUpdated` lifecycle callback:

```js
async firstUpdated() {
  // Give the browser a chance to paint
  await new Promise((r) => setTimeout(r, 0));
  this.addEventListener('click', this._handleClick);
}
```

`firstUpdated` fires after the first time your component has been updated and called its `render` method, but **before the browser has had a chance to paint**. The `Promise`/`setTimeout` line yields to the browser
    
See [firstUpdated](/guide/lifecycle#firstupdated) in the Lifecycle documentation for more information.


## Using `this` in event listeners

Event listeners added using the declarative (`@event`) syntax in the template are automatically _bound_ to the component.

Therefore, you can use `this` to refer to your component instance inside any declarative event handler:

```js
class MyElement extends LitElement {
  render() {
    return html`<button @click="${this._handleClick}">click</button>`;
  }
  _handleClick(e) {
    console.log(this.prop);
  }
}
```

When adding listeners imperatively with `addEventListener`, you'll need to bind the event listener yourself if you need a reference to the component instance. For example:

```js
this.boundResizeHandler = this.handleResize.bind(this);
window.addEventListener('resize', this.boundResizeHandler);
```

Or use an arrow function as a class field:

```ts
export class MyElement extends LitElement {
  private _handleResize = () => { /* handle the event */ }

  constructor() {
    window.addEventListener('resize', this._handleResize);
  }
}
```

See the [documentation for `this` on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) for more information.

## Setting event listener options

When you add an event listener imperatively, using `addEventListener`, you can specify various event listener options. For example, to use a passive event listener in plain JavaScript you'd do something like this:

```js
someElement.addEventListener('touchstart', this._handleTouchStart, {passive: true});
```

The `eventOptions` decorator allows you to add event listener options to a listener that's added declaratively in your template.

```js
import {LitElement, html, eventOptions} from 'lit-element';
...

@eventOptions({passive: true})
private _handleTouchStart() { ... }

render() { 
  return html`
    <div @touchstart=${this._handleTouchStart}><div>
  `;
}
```

<div class="alert alert-info">

**Using decorators.** Decorators are a proposed JavaScript feature, so you’ll need to use a compiler like Babel or TypeScript to use decorators. See [Using decorators](decorators) for details.

</div>

The object passed to `eventOptions` is used as the `options` parameter to `addEventListener`.



More information:

*   [EventTarget.addEventListener()](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) on MDN for a description of the event listener options.


## Use cases

* [Fire a custom event from a LitElement-based component](#fire-custom-event).
* [Handle a custom event fired by a LitElement-based component](#handle-custom-event).
* [Handle an event fired by a shadow DOM child of your component](#handle-shadow-dom-event).
* [Add event listeners imperatively](#imperative).

### Fire an event from a LitElement-based component {#fire-event}

Fire a custom event:

```js
class MyElement extends LitElement {
  render() {
    return html`<div>Hello World</div>`;
  }
  firstUpdated(changedProperties) {
    let event = new CustomEvent('my-event', {
      detail: {
        message: 'Something important happened'
      }
    });
    this.dispatchEvent(event);
  }
}
```

Fire a standard event:

```js
class MyElement extends LitElement {
  render() {
    return html`<div>Hello World</div>`;
  }
  updated(changedProperties) {
    let click = new Event('click');
    this.dispatchEvent(click);
  }
}
```

### Handle an event fired by a LitElement-based component {#handle-fired-event}

If you want to listen to an event fired from a LitElement-based component from within another LitElement or from a lit-html template, you can use the lit-html declarative event syntax:

```html
<my-element @my-event="${(e) => { console.log(e.detail.message) }}"></my-element>
```

To listen to events fired from a LitElement-based component in other contexts, like HTML or another framework, use the standard mechanism for listening to DOM events.

In plain HTML and JavaScript, this would be the `addEventListener` API:

```js
const myElement = document.querySelector('my-element');
myElement.addEventListener('my-event', (e) => {console.log(e)});
```

## Working with events and shadow DOM

When working with events and shadow DOM, there are a few things you need to know about. 

### Event bubbling

Some events bubble up through the DOM tree, so that they are detectable by any element on the page. 

Whether or not an event bubbles depends on the value of its `bubbles` property. To check if a particular event bubbles:

```js
handleEvent(e){
  console.log(e.bubbles);
}
```

See the MDN documentation on the [Event interface](https://developer.mozilla.org/en-US/docs/Web/API/Event) for more information.

### Event retargeting

Bubbling events fired from within shadow DOM are retargeted so that, to any listener external to your component, they appear to come from your component itself. 

**Example**

```html
<my-element onClick="(e) => console.log(e.target)"></my-element>
```

```js
render() {
  return html`
    <button id="mybutton" @click="${(e) => console.log(e.target)}">
      click me
    </button>`;
}
```

When handling such an event, you can find where it originated from with `composedPath`:

```js
handleMyEvent(event) {
  console.log('Origin: ', event.composedPath()[0]);
}
```

### Custom events

By default, a bubbling custom event fired inside shadow DOM will stop bubbling when it reaches the shadow root. 

To make a custom event pass through shadow DOM boundaries, you must set both the `composed` and `bubbles` flags to `true`:

```js
firstUpdated(changedProperties) {
  let myEvent = new CustomEvent('my-event', { 
    detail: { message: 'my-event happened.' },
    bubbles: true, 
    composed: true });
  this.dispatchEvent(myEvent);
}
```

See the [MDN documentation on custom events](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) for more information.

---

###  Guide Lifecycle (`docs/_guide/lifecycle.md`)

---
layout: guide
title: Lifecycle
slug: lifecycle
lit_dev_path: /docs/components/lifecycle/
---

{::options toc_levels="1..3" /}
* ToC
{:toc}

## Overview

LitElement-based components update asynchronously in response to observed property changes. Property changes are batched—if more properties change after an update is requested, but before the update starts, all of the changes are captured in the same update.

At a high level, the update lifecycle is:

1. A property is set.
2. Check whether an update is needed. If an update is needed, request one.
3. Perform the update:
  * Process properties and attributes.
  * Render the element.
4. Resolve a Promise, indicating that the update is complete.

####  LitElement and the browser event loop

The browser executes JavaScript code by processing a queue of tasks in the [event loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop). In each iteration of the event loop, the browser takes a task from the queue and runs it to completion.

When the task completes, before taking the next task from the queue, the browser allocates time to perform work from other sources—including DOM updates, user interactions, and the microtask queue.

By default, LitElement updates are requested asynchronously, and queued as microtasks. This means that Step 3 above (Perform the update) is executed at the end of the next iteration of the event loop.

You can change this behavior so that Step 3 awaits a Promise before performing the update. See [`performUpdate`](#performUpdate) for more information.

For a more detailed explanation of the browser event loop, see [Jake Archibald's article](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/).

#### Lifecycle callbacks {#lifecyclecallbacks}

LitElement also inherits the default [lifecycle callbacks](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#Using_the_lifecycle_callbacks) from the Web Component standard:
* `connectedCallback`: Invoked when a component is added to the document's DOM.
* `disconnectedCallback`: Invoked when a component is removed from the document's DOM.
* `adoptedCallback`: Invoked when a component is moved to a new document.
* `attributeChangedCallback`: Invoked when component attribute changes.

<div class="alert alert-info">

**Be aware that adoptedCallback is not polyfilled.** 

</div>

**All lifecycle methods need to call the super method.** 

Example:

```js
connectedCallback() {
  super.connectedCallback()

  console.log('connected')
}
```

#### Promises and asynchronous functions

LitElement uses [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) objects to schedule and respond to element updates.

Using `async` and `await` makes it easy to work with Promises. For example, you can await the `updateComplete` Promise:

```js
// `async` makes the function return a Promise & lets you use `await`
async myFunc(data) {
  // Set a property, triggering an update
  this.myProp = data;

  // Wait for the updateComplete promise to resolve
  await this.updateComplete;
  // ...do stuff...
  return 'done';
}
```

Because `async` functions return a Promise, you can await them, too:

```js
let result = await myFunc('stuff');
// `result` is resolved! You can do something with it
```

See the [Web Fundamentals primer on Promises](https://developers.google.com/web/fundamentals/primers/promises) for a more in-depth tutorial.

## Assorted use cases

Common reasons to hook into the custom element lifecycle or the LitElement update lifecycle are initializations, managing derived data, and dealing with events that originate outside of your element's template. The following list provides some common use cases and approaches. In several cases there is more than one way to achieve a certain goal. Reading this list along with the detailed [technical reference](#reference) will provide you with a rather complete picture and enable you to decide what fits your component's needs best.

- Use [property.hasChanged](#haschanged) for **checking** "Is this a change? Do I want to run the update lifecycle?".
- Use the element [constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/constructor) for [initializing LitElement properties](./properties#initialize) with **default values**. (*Attribute values* from the DOM are *not available* when the constructor runs.)
- Use [firstUpdated](#firstupdated) for **initializing private fields from DOM attributes** (as the constructor doesn't have access to them). Note that [render](#render) has already run at this point and your changes might trigger another update lifecycle. If it's imperative that you get access to attribute values *before* the first render happens, consider using [connectedCallback](#lifecyclecallbacks), but you'll need to do the extra logic for figuring out the "first" update yourself as [connectedCallback](#lifecyclecallbacks) can be called multiple times.
- Use [updated](#updated) for keeping **derived data** up to date or **reacting to changes**. If you find, that you're causing re-renders, consider using [update](#update) instead.
- Use custom [JS property getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) for **derived data** that is "cheap" to calculate and if its not likely to change often and your element doesn't re-[render](#render) often.
- Use [requestUpdate](#requestupdate) to **trigger an update lifecycle** when LitElement cannot pick it up. (E.g. if you have an [observed property](./properties) that is an array, and you add an item to that array instead of replacing the entire array, LitElement won't "see" this change, because the *reference* to the array *didn't change*.)
- Use [connectedCallback](#lifecyclecallbacks) to register **event handlers** for outside your element's template, but don't forget to remove them in [disconnectedCallback](#lifecyclecallbacks)!

## Methods and properties reference {#reference}

In call order, the methods and properties in the update lifecycle are:

1.  [someProperty.hasChanged](#haschanged)
1.  [requestUpdate](#requestupdate)
1.  [performUpdate](#performupdate)
1.  [shouldUpdate](#shouldupdate)
1.  [update](#update)
1.  [render](#render)
1.  [firstUpdated](#firstupdated)
1.  [updated](#updated)
1.  [updateComplete](#updatecomplete)

### someProperty.hasChanged {#haschanged}

All declared properties have a function, `hasChanged`, which is called whenever the property is set; if `hasChanged` returns true, an update is scheduled.

See the Properties documentation for information on [configuring `hasChanged` to customize what constitutes a property change](/guide/properties#haschanged).

### requestUpdate {#requestupdate}

```js
// Manually start an update
this.requestUpdate();

// Call from within a custom property setter
this.requestUpdate(propertyName, oldValue);
```

| **Params**<br/><br/>&nbsp; | `propertyName`<br/><br/>`oldValue`| Name of property to be updated. <br/><br/> Previous property value. |
| **Returns**  | `Promise` | Returns the [`updateComplete` Promise](#updatecomplete), which resolves on completion of the update. |
| **Updates?** | No | Property changes inside this method will not trigger an element update. |

If [`hasChanged`](#haschanged) returned `true`, `requestUpdate` fires, and the update proceeds.

To manually start an element update, call `requestUpdate` with no parameters.

To implement a custom property setter that supports property options, pass the property name and its previous value as parameters.

**Example: Manually start an element update**

```js
{% include projects/lifecycle/requestupdate/my-element.js %}
```

{% include project.html folder="lifecycle/requestupdate" openFile="my-element.js" %}

**Example: Call `requestUpdate` from a custom property setter**

```js
{% include projects/properties/customsetter/my-element.js %}
```

{% include project.html folder="properties/customsetter" openFile="my-element.js" %}

### performUpdate {#performupdate}

```js
/**
 * Implement to override default behavior.
 */
performUpdate() { ... }
```

| **Returns** | `void` or `Promise` |  Performs an update. |
| **Updates?** | No | Property changes inside this method will not trigger an element update. |

By default, `performUpdate` is scheduled as a microtask after the end of the next execution of the browser event loop. To schedule `performUpdate`, implement it as an asynchronous method that awaits some state before calling `super.performUpdate()`. For example:

```js
async performUpdate() {
  await new Promise((resolve) => requestAnimationFrame(() => resolve()));
  super.performUpdate();
}
```

{% include project.html folder="lifecycle/performupdate" openFile="my-element.js" %}

### shouldUpdate {#shouldupdate}

```js
/**
 * Implement to override default behavior.
 */
shouldUpdate(changedProperties) { ... }
```

| **Params** | `changedProperties`| `Map`. Keys are the names of changed properties; Values are the corresponding previous values. |
| **Returns**  | `Boolean` | If `true`, update proceeds. Default return value is `true`. |
| **Updates?** | Yes | Property changes inside this method will trigger an element update. |

Controls whether an update should proceed. Implement `shouldUpdate` to specify which property changes should cause updates. By default, this method always returns true.

**Example: Customize which property changes should cause updates**

```js
{% include projects/lifecycle/shouldupdate/my-element.js %}
```

{% include project.html folder="lifecycle/shouldupdate" openFile="my-element.js" %}

### update {#update}

| **Params** | `changedProperties`| `Map`. Keys are the names of changed properties; Values are the corresponding previous values. |
| **Updates?** | No | Property changes inside this method do not trigger an element update. |

Reflects property values to attributes and calls `render` to render DOM via lit-html. Provided here for reference. You don't need to override or call this method. But if you override it, make sure to call `super.update(changedProperties)` or [render](#render) will never be called.

### render {#render}

```js
/**
 * Implement to override default behavior.
 */
render() { ... }
```

| **Returns** | `TemplateResult` | Must return a lit-html `TemplateResult`. |
| **Updates?** | No | Property changes inside this method will not trigger an element update. |

Uses lit-html to render the element template. You must implement `render` for any component that extends the LitElement base class.

See the documentation on [Templates](/guide/templates) for more information.

### firstUpdated {#firstupdated}

```js
/**
 * Implement to override default behavior.
 */
firstUpdated(changedProperties) { ... }
```

| **Params** | `changedProperties`| `Map`. Keys are the names of changed properties; Values are the corresponding previous values. |
| **Updates?** | Yes | Property changes inside this method will trigger an element update. |

Called after the element's DOM has been updated the first time, immediately before [`updated`](#updated) is called.

Implement `firstUpdated` to perform one-time work after the element's template has been created.

**Example: Focus an input element on first update**

```js
{% include projects/lifecycle/firstupdated/my-element.js %}
```

{% include project.html folder="lifecycle/firstupdated" openFile="my-element.js" %}

### updated {#updated}

```js
/**
 * Implement to override default behavior.
 */
updated(changedProperties) { ... }
```

| **Params** | `changedProperties`| `Map`. Keys are the names of changed properties; Values are the corresponding previous values. |
| **Updates?** | Yes | Property changes inside this method will trigger an element update. |

Called when the element's DOM has been updated and rendered. Implement to perform some task after an update.

**Example: Focus an element after update**

```js
{% include projects/lifecycle/updated/my-element.js %}
```

{% include project.html folder="lifecycle/updated" openFile="my-element.js" %}

### updateComplete {#updatecomplete}

```js
// Await Promise property.
await this.updateComplete;
```

| **Type** | `Promise` | Resolves with a `Boolean` when the element has finished updating. |
| **Resolves** <br/><br/>| `true` if there are no more pending updates.<br/><br/> `false` if this update cycle triggered another update. |

The `updateComplete` Promise resolves when the element has finished updating. Use `updateComplete` to wait for an update:

  ```js
  await this.updateComplete;
  // do stuff
  ```

  ```js
  this.updateComplete.then(() => { /* do stuff */ });
  ```

**Example**

```js
{% include projects/lifecycle/updatecomplete/my-element.js %}
```

{% include project.html folder="lifecycle/updatecomplete" openFile="my-element.js" %}

#### Overriding updateComplete {#overriding-updatecomplete}

To await additional state before fulfilling the `updateComplete` promise, override the `_getUpdateComplete` method. For example, it may be useful to await the update of a child element here. First await `super._getUpdateComplete()`, then any subsequent state.

It's recommended to override the `_getUpdateComplete` method instead of the `updateComplete` getter to ensure compatibility with users who are using TypeScript's ES5 output (see [TypeScript#338](https://github.com/microsoft/TypeScript/issues/338)).

  ```js
  class MyElement extends LitElement {
    async _getUpdateComplete() {
      await super._getUpdateComplete();
      await this._myChild.updateComplete;
    }
  }
  ```

## Examples {#examples}

#### Control when updates are processed

[Implement `performUpdate`](#performupdate):

```js
async performUpdate() {
  await new Promise((resolve) => requestAnimationFrame(() => resolve());
  super.performUpdate();
}
```

{% include project.html folder="lifecycle/performupdate" openFile="my-element.js" %}

#### Customize which property changes should cause an update

[Implement `shouldUpdate`](#shouldupdate):

```js
shouldUpdate(changedProps) {
  return changedProps.has('prop1');
}
```

{% include project.html folder="lifecycle/shouldupdate" openFile="my-element.js" %}

#### Customize what constitutes a property change

Specify [`hasChanged`](#haschanged) for the property. See the [Properties documentation](properties#haschanged).

#### Manage property changes and updates for object subproperties

Mutations (changes to object subproperties and array items) are not observable. Instead, either rewrite the whole object, or call [`requestUpdate`](#requestupdate) after a mutation.

```js
// Option 1: Rewrite whole object, triggering an update
this.prop1 = Object.assign({}, this.prop1, { subProp: 'data' });

// Option 2: Mutate a subproperty, then call requestUpdate
this.prop1.subProp = 'data';
this.requestUpdate();
```

{% include project.html folder="lifecycle/subproperties" openFile="my-element.js" %}

#### Update in response to something that isn't a property change

Call [`requestUpdate`](#requestupdate):

```js
// Request an update in response to an event
this.addEventListener('load-complete', async (e) => {
  console.log(e.detail.message);
  console.log(await this.requestUpdate());
});
```

{% include project.html folder="lifecycle/requestupdate" openFile="my-element.js" %}

#### Request an update regardless of property changes

Call [`requestUpdate()`](#requestupdate):

```js
this.requestUpdate();
```

#### Request an update for a specific property

Call [`requestUpdate(propName, oldValue)`](#requestupdate):

```js
let oldValue = this.prop1;
this.prop1 = 'new value';
this.requestUpdate('prop1', oldValue);
```

{% include project.html folder="lifecycle/requestupdate" openFile="my-element.js" %}

#### Do something after the first update

Implement [`firstUpdated`](#firstupdated):

```js
firstUpdated(changedProps) {
  console.log(changedProps.get('prop1'));
}
```

{% include project.html folder="lifecycle/firstupdated" openFile="my-element.js" %}

#### Do something after every update

Implement [`updated`](#updated):

```js
updated(changedProps) {
  console.log(changedProps.get('prop1'));
}
```

{% include project.html folder="lifecycle/updated" openFile="my-element.js" %}

#### Do something when the element next updates

Await the [`updateComplete`](#updatecomplete) promise:

```js
await this.updateComplete;
// do stuff
```

```js
this.updateComplete.then(() => {
  // do stuff
});
```

#### Wait for an element to finish updating

Await the [`updateComplete`](#updatecomplete) promise:

```js
let done = await updateComplete;
```

```js
updateComplete.then(() => {
  // finished updating
});
```

{% include project.html folder="lifecycle/updatecomplete" openFile="my-element.js" %}

---

###  Guide Properties (`docs/_guide/properties.md`)

---
layout: guide
title: Properties
slug: properties
lit_dev_path: /docs/components/properties/
---

{::options toc_levels="1..3" /}
* ToC
{:toc}

## Overview {#overview}

LitElement manages your declared properties and their corresponding attributes. By default, LitElement will: 

* Ensure that an element update is scheduled when any declared property changes.
* Capture instance values for declared properties. Apply any property values that are set before the browser registers a custom element definition.
* Set up an observed (not reflected) attribute with the lowercased name of each property.
* Handle attribute conversion for properties declared as type `String`, `Number`, `Boolean`, `Array`, and `Object`.
* Use direct comparison (`oldValue !== newValue`) to test for property changes.
* Apply any property options and accessors declared by a superclass. 

{:.alert .alert-warning}
<div>

**Remember to declare all of the properties that you want LitElement to manage.** For the property features above to be applied, you must [declare the property](#declare). 

</div>

## Declare properties {#declare}

Declare your element's properties using a static `properties` field, or using decorators:

_Properties field_

<div class="language-js">
<pre class="highlight">
static get properties() {
  return { 
    <var>propertyName</var>: <var>options</var>
  };
}
</pre>
</div>

_Decorator (requires TypeScript or Babel)_

<div class="language-ts">
<pre class="highlight">
export class MyElement extends LitElement {
  @property(<var>options</var>) 
  <var>propertyName</var>;
</pre>
</div>

In either case, you can pass an options object to configure features for the property. 

### Property options

The options object can have the following properties:

<dl>
<dt>

`attribute`

</dt>
<dd>

Whether the property is associated with an attribute, or a custom name for the associated attribute. Default: true. See [Configure observed attributes](#observed-attributes). If `attribute` is false, the `converter`, `reflect` and `type` options are ignored. 

</dd>
<dt>

`converter`

</dt>
<dd>

A [custom converter](#conversion-converter) for converting between properties and attributes. If unspecified, use the [default attribute converter](#conversion-type).

</dd>
<dt>

`hasChanged`

</dt>
<dd>

A function that takes an `oldValue` and `newValue` and returns a boolean to indicate whether a [property has changed](#haschanged) when being set. If unspecified, LitElement uses a strict inequality check (`newValue !== oldValue`) to determine whether the property value has changed.

</dd>
<dt>

`noAccessor`

</dt>
<dd>

Set to true to avoid generating the default [property accessor](#accessors). Default: false.

</dd>
<dt>

`reflect`

</dt>
<dd>

Whether property value is reflected back to the associated attribute. Default: false. See  [Configure reflected attributes](#reflected-attributes).

</dd>
<dt>

`type`

</dt>
<dd>

A type hint for converting between properties and attributes. This hint is used by LitElement's default attribute converter, and is ignored if `converter` is set. If `type` is unspecified, behaves like `type: String`. See [Use LitElement's default attribute converter](#conversion-type). 

</dd>

An empty options object is equivalent to specifying the default value for all options.

<div class="alert alert-info">

**An options object by another name.** This guide uses the descriptive term "options object." In practice the options object is an instance of `PropertyDeclaration`, so you'll see that name if you're using an IDE, or looking at the API reference. By either name, it's an object that defines a set of options.

</div>

### Declare properties in a static properties field

To declare properties in a static `properties` field:

```js
static get properties() { 
  return { 
    greeting: {type: String},
    data: {attribute: false},
    items: {}
  };
}
```

An empty option object is equivalent to specifying the default value for all options.

<div class="alert alert-info">

Declared properties are initialized like standard class fields—either in the constructor, or with a field initializer if you're using decorators.

</div>

**Example: Declare properties with a static `properties` field** 

```js
{% include projects/properties/declare/my-element.js %}
```

{% include project.html folder="properties/declare" openFile="my-element.js" %}

### Declare properties with decorators {#declare-with-decorators}

Use the `@property` decorator to declare properties (instead of the static `properties` field).

```js
@property({type: String})
mode = 'auto';

@property()
data = {};
```

The argument to the `@property` decorator is an [options object](#property-options). Omitting the argument is equivalent to specifying the default value for all options.

<div class="alert alert-info">

**Using decorators.** Decorators are a proposed JavaScript feature, so you'll need to use a transpiler like Babel or the TypeScript compiler to use decorators. See [Using decorators](decorators) for details.

</div>

There is also an `@internalProperty` decorator for private or protected properties that should trigger an update cycle. Properties declared with `@internalProperty` shouldn't be referenced from outside the component.

```ts
@internalProperty()
protected active = false;
```

The `@internalProperty` decorator automatically sets `attribute` to false; **the only option you can specify for an internal property is the `hasChanged` function.**

The `@internalProperty` decorator can serve as a hint to a code minifier that the property name can be changed during minification.

**Example: Declare properties with decorators** 

```js
{% include projects/properties/declaretypescript/my-element.ts %}
```

{% include project.html folder="properties/declaretypescript" openFile="my-element.ts" %}

## What happens when properties change

A property change can trigger an asynchronous update cycle, which causes the component to re-render its template.

When a property changes, the following sequence occurs:

1.  The property's setter is called.
1.  The setter calls the property's `hasChanged` function. The `hasChanged` function takes the property's old and new values, and returns true if the change should trigger an update. (The default `hasChanged` uses a strict inequality test (`oldValue !== newValue`) to determine if the property has changed.)
1.  If `hasChanged` returns true, the setter calls `requestUpdate` to schedule an update. The update itself happens asynchronously, so if several properties are updated at once, they only trigger a single update.
1.  The component's `update` method is called, reflecting changed properties to attributes and re-rendering the component's templates.

There are many ways to hook into and modify the update lifecycle. For more information, see [Lifecycle](lifecycle).


## Initialize property values {#initialize}

Typically, you initialize property values in the element constructor. 

When using decorators, you can initialize the property value as part of the declaration (equivalent to setting the value in the constructor).

You may want to defer initializing a property if the value is expensive to compute and is not required for the initial render of your component. This is a fairly rare case.

### Initialize property values in the element constructor {#initialize-constructor}

If you implement a static properties field, initialize your property values in the element constructor:

```js
static get properties() { return { /* Property declarations */ }; } 

constructor() {
  // Always call super() first
  super();

  // Initialize properties 
  this.greeting = 'Hello';
}
```

{:.alert .alert-warning}
<div> 

Remember to call `super()` first in your constructor, or your element won't render at all.

</div>

**Example: Initialize property values in the element constructor** 

{% include project.html folder="properties/declare" openFile="my-element.js" %}

### Initialize property values when using decorators

When using the `@property` decorator, you can initialize a property as part of the declaration:

```ts
@property({type : String}) 
greeting = 'Hello';
```

**Example: Initialize property values when using decorators** 

{% include project.html folder="properties/declaretypescript" openFile="my-element.ts" %}



## Configure attributes {#attributes}

### Convert between properties and attributes {#conversion}

While element properties can be of any type, attributes are always strings. This impacts the [observed attributes](#observed-attributes) and [reflected attributes](#reflected-attributes) of non-string properties:

  * To **observe** an attribute (set a property from an attribute), the attribute value must be converted from a string to match the property type. 

  * To **reflect** an attribute (set an attribute from a property), the property value must be converted to a string.

#### Use the default converter {#conversion-type}

LitElement has a default converter which handles `String`, `Number`, `Boolean`, `Array`, and `Object` property types.

To use the default converter, specify the `type` option in your property declaration:

```js
// Use LitElement's default converter 
prop1: { type: String },
prop2: { type: Number },
prop3: { type: Boolean },
prop4: { type: Array },
prop5: { type: Object }
```

The information below shows how the default converter handles conversion for each type.

**Convert from attribute to property**

* For **Strings**, when the attribute is defined, set the property to the attribute value.
* For **Numbers**, when the attribute is defined, set the property to `Number(attributeValue)`.
* For **Booleans**, when the attribute is:
  * non-`null`, set the property to `true`.
  * `null` or `undefined`, set the property to `false`.
* For **Objects and Arrays**, when the attribute is:
  * Defined, set the property value to `JSON.parse(attributeValue)`.

**Convert from property to attribute** 

* For **Strings**, when the property is:
  * `null`, remove the attribute.
  * `undefined`, don't change the attribute.
  * Defined and not `null`, set the attribute to the property value.
* For **Numbers**, when the property is:
  * `null`, remove the attribute.
  * `undefined`, don't change the attribute.
  * Defined and not `null`, set the attribute to the property value.
* For **Booleans**, when the property is:
  * truthy, create the attribute.
  * falsy, remove the attribute.
* For **Objects and Arrays**, when the property is:
  * `null` or `undefined`, remove the attribute.
  * Defined and not `null`, set the attribute value to `JSON.stringify(propertyValue)`.

**Example: Use the default converter** 

```js
{% include projects/properties/defaultconverter/my-element.js %}
```

{% include project.html folder="properties/defaultconverter" openFile="my-element.js" %}

#### Configure a custom converter {#conversion-converter}

You can specify a custom property converter in your property declaration with the `converter` option:

```js
myProp: { 
  converter: // Custom property converter
} 
```

`converter` can be an object or a function. If it is an object, it can have keys for `fromAttribute` and `toAttribute`: 

```js
prop1: { 
  converter: { 
    fromAttribute: (value, type) => { 
      // `value` is a string
      // Convert it to a value of type `type` and return it
    },
    toAttribute: (value, type) => { 
      // `value` is of type `type` 
      // Convert it to a string and return it
    }
  }
}
```

If `converter` is a function, it is used in place of `fromAttribute`:

```js
myProp: { 
  converter: (value, type) => { 
    // `value` is a string
    // Convert it to a value of type `type` and return it
  }
} 
```

If no `toAttribute` function is supplied for a reflected attribute, the attribute is set to the property value without conversion.

During an update: 

  * If `toAttribute` returns `null`, the attribute is removed. 

  * If `toAttribute` returns `undefined`, the attribute is not changed.

**Example: Configure a custom converter** 

```js
{% include projects/properties/attributeconverter/my-element.js %}
```

{% include project.html folder="properties/attributeconverter" openFile="my-element.js" %}

### Configure observed attributes {#observed-attributes}

An **observed attribute** fires the custom elements API callback `attributeChangedCallback` whenever it changes. By default, whenever an attribute fires this callback, LitElement sets the property value from the attribute using the property's `fromAttribute` function. See [Convert between properties and attributes](#conversion) for more information.

By default, LitElement creates a corresponding observed attribute for all declared properties. The name of the observed attribute is the property name, lowercased:

```js
// observed attribute name is "myprop"
myProp: { type: Number }
```

To create an observed attribute with a different name, set `attribute` to a string: 

```js
// Observed attribute will be called my-prop
myProp: { attribute: 'my-prop' }
```

To prevent an observed attribute from being created for a property, set `attribute` to `false`. The property will not be initialized from attributes in markup, and attribute changes won't affect it.

```js
// No observed attribute for this property
myProp: { attribute: false }
```

An observed attribute can be used to provide an initial value for a property via markup. See [Initialize properties with attributes in markup](#initialize-markup).

**Example: Configure observed attributes**

```js
{% include projects/properties/attributeobserve/my-element.js %}
```

{% include project.html folder="properties/attributeobserve" openFile="my-element.js" %}



### Configure reflected attributes {#reflected-attributes}

You can configure a property so that whenever it changes, its value is reflected to its [observed attribute](#observed-attributes). For example:

```js
// Value of property "myProp" will reflect to attribute "myprop"
myProp: {reflect: true}
```

When the property changes, LitElement uses the `toAttribute` function in the property's converter to set the attribute value from the new property value. 

* If `toAttribute` returns `null`, the attribute is removed.

* If `toAttribute` returns `undefined`, the attribute is not changed.

* If `toAttribute` itself is undefined, the attribute value is set to the property value without conversion.

{:.alert .alert-info}
<div>

**LitElement tracks reflection state during updates.** LitElement keeps track of  state information to avoid creating an infinite loop of changes between a property and an observed, reflected attribute.

</div>

**Example: Configure reflected attributes**

```js
{% include projects/properties/attributereflect/my-element.js %}
```

{% include project.html folder="properties/attributereflect" openFile="my-element.js" %}

### Set property values from attributes in markup {#initialize-markup}

If a property is configured with `attribute: true` (the default), users can set the property values from observed attributes in static markup:

_index.html_ 

```html
<my-element 
  mystring="hello world"
  mynumber="5"
  mybool
  myobj='{"stuff":"hi"}'
  myarray='[1,2,3,4]'></my-element>
```

See [observed attributes](#observed-attributes) and [converting between properties and attributes](#conversion) for more information on setting up initialization from attributes.

<div class="alert alert-info">

**Attributes versus property bindings.** Setting a static attribute value is not the same as binding to a property. See [Bind to a property](templates#bind-to-a-property).

</div>

## Configure property accessors {#accessors}

By default, LitElement generates a getter/setter pair for all declared properties. The setter is invoked whenever you set the property:

```js
// Declare a property
static get properties() { return { myProp: { type: String } }; }
...
// Later, set the property
this.myProp = 'hi'; // invokes myProp's generated property accessor
```

Generated accessors automatically call `requestUpdate`, initiating an update if one has not already begun.

### Create your own property accessors {#accessors-custom}

To specify how getting and setting works for a property, you can define your getter/setter pair. For example:

```js
static get properties() { return { myProp: { type: String } }; }

set myProp(value) {
  // Implement setter logic here... 
  // retrieve the old property value and store the new one
  this.requestUpdate('myProp', oldValue);
} 
get myProp() { ... }

...

// Later, set the property
this.myProp = 'hi'; // Invokes your setter
```

If your class defines its own accessors for a property, LitElement will not overwrite them with generated accessors. If your class does not define accessors for a property, LitElement will generate them, even if a superclass has defined the property or accessors. 

The setters that LitElement generates automatically call `requestUpdate`. If you write your own setter you must call `requestUpdate` manually, supplying the property name and its old value.

**Example**

A common pattern for accessors is to store the property value using a private property that's only accessed inside the component. This example uses an underscore prefix (`_prop`) to identify the private property—you could also use TypeScript's `private` or `protected` keywords.

```js
{% include projects/properties/customsetter/my-element.js %}
```

If you want to use your own property accessor with the `@property` decorator, you can achieve this by putting the decorator on the getter:

```ts
   private _myProp: string = '';

  @property({ type: String })
  get myProp(): string {
    return this._myProp;
  }
  set myProp(value: string) {
    const oldValue = this._myProp;
    this._myProp = value;
    this.requestUpdate('myProp', oldValue);
  }
```

### Prevent LitElement from generating a property accessor {#accessors-noaccessor}

In rare cases, a subclass may need to change or add property options for a property that exists on its superclass.

To prevent LitElement from generating a property accessor that overwrites the superclass's defined accessor, set `noAccessor` to `true` in the property declaration:

```js
static get properties() { 
  return { myProp: { type: Number, noAccessor: true } }; 
}
```

You don't need to set `noAccessor` when defining your own accessors. 

**Example** 

**Subclass element**

```js
{% include projects/properties/accessorssubclassing/sub-element.js %}
```

{% include project.html folder="properties/accessorssubclassing" openFile="sub-element.js" %}

## Configure property changes {#haschanged}

All declared properties have a function, `hasChanged`, which is called when the property is set. 

`hasChanged` compares the property's old and new values, and evaluates whether or not the property has changed. If `hasChanged` returns true, LitElement starts an element update if one is not already scheduled. See the [Element update lifecycle documentation](lifecycle) for more information on how updates work.

By default:

* `hasChanged` returns `true` if `newVal !== oldVal`.
* `hasChanged` returns `false` if both the new and old values are `NaN`.

To customize `hasChanged` for a property, specify it as a property option:

```js
myProp: { hasChanged(newVal, oldVal) {
  // compare newVal and oldVal
  // return `true` if an update should proceed
}}
```

<div class="alert alert-info">

**hasChanged may not be called for every change.** If a property's `hasChanged` returns true once, it won't be called again until after the next update, even if the property is changed multiple times. If you want to be notified each time a property is set, you should create a custom setter for the property, as described in [Create your own property accessors](#accessors-custom).

</div>

**Example: Configure property changes** 

```js
{% include projects/properties/haschanged/my-element.js %}
```

{% include project.html folder="properties/haschanged" openFile="my-element.js" %}

---

###  Guide Publish (`docs/_guide/publish.md`)

---
layout: guide
title: Publish an element
slug: publish
lit_dev_path: /docs/tools/publishing/
---

{::options toc_levels="1..3" /}
* ToC
{:toc}

This page describes how to publish a LitElement component to npm.

We recommend publishing JavaScript modules in standard ES2017. If you're writing your element in standard ES2017, you don't need to transpile for publication. If you're using TypeScript, or ES2017+ features such as decorators or class fields, you will need to transpile your element for publication.

## Publishing to npm

To publish your component to npm, [see the instructions on contributing npm packages](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry).

Your package.json configuration should have both the `main` and `module` fields:

**package.json**

```json
{
  "main": "my-element.js",
  "module": "my-element.js"
}
```

You should also create a README describing how to consume your component. A basic guide to consuming LitElement components is documented at [Use a component](use).

## Transpiling with TypeScript

When compiling your code from TypeScript to JavaScript, we recommend targeting ES2017 with Node.js module resolution.

The following JSON sample is a partial tsconfig.json that uses recommended options for targeting ES2017:

```json
  "compilerOptions": {
    "target": "es2017",
    "module": "es2015",
    "moduleResolution": "node",
    "lib": ["es2017", "dom"],
    "experimentalDecorators": true
  }
```

See the [tsconfig.json documentation](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) for more information.

## Transpiling with Babel

To transpile a LitElement component that uses proposed JavaScript features, use Babel.

Install Babel and the Babel plugins you need. For example:

```
npm install --save-dev @babel/core
npm install --save-dev @babel/plugin-proposal-class-properties
npm install --save-dev @babel/plugin-proposal-decorators
```

Configure Babel. For example:

**babel.config.js**

```js
const plugins = [
  '@babel/plugin-proposal-class-properties',
  ['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true } ],
];

module.exports = { plugins };
```

You can run Babel via a bundler plugin such as [rollup-plugin-babel](https://www.npmjs.com/package/rollup-plugin-babel), or from the command line. See the [Babel documentation](https://babeljs.io/docs/en/) for more information.

---

###  Guide Start (`docs/_guide/start.md`)

---
layout: guide
title: Getting Started
slug: start
lit_dev_path: /docs/getting-started/
---

{::options toc_levels="1..3" /}
* ToC
{:toc}

There are two main ways to use LitElement: 


*   **Creating reusable components to share with other developers.** Individual components or sets of related components are usually published to npm. To create a reusable component project, see [Create a LitElement component project](#component-project).

*   **Creating app-specific components.** The source for these components may live as part of an application project. To add LitElement components to your app, see [Add LitElement to an existing project](#existing-project).

## Create a LitElement component project {#component-project}

Get started writing a reusable LitElement component that could be published for others to use. 

To get started working on a component locally, you can use one of these starter projects:

*   [LitElement JavaScript starter project ](https://github.com/PolymerLabs/lit-element-starter-js)
*   [LitElement TypeScript starter project](https://github.com/PolymerLabs/lit-element-starter-ts)

Both projects define a LitElement component. They also add a set of optional tools for developing, linting, and testing the component:

*   Node.js and npm for managing dependencies. _Requires Node.js 10 or greater._
*   A local dev server,  [ES dev server](https://open-wc.org/developing/es-dev-server.html#getting-started).
*   Linting with [ESLint](https://eslint.org/) and [lit-analyzer](https://www.npmjs.com/package/lit-analyzer).
*   Testing with [Karma](https://karma-runner.github.io/latest/index.html).
*   A static doc site built with [web component analyzer](https://www.npmjs.com/package/web-component-analyzer) and [eleventy](https://www.11ty.dev/).

None of these tools is _required_ to work with LitElement. They represent one possible set of tools for a good developer experience. 

<div class="alert alert-info">

**Alternative starting point.** As an alternative to the official LitElement starter projects, the open-wc project has a [project generator](https://open-wc.org/docs/development/generator/) for web components using LitElement. The open-wc script asks a series of questions and scaffolds out a project for you. 

</div>

### Download the starter project

The quickest way to try out a project locally is to download one of the starter projects as a zip file. 

1.  Download the starter project from GitHub as a zip file:

    *   [JavaScript starter project](https://github.com/PolymerLabs/lit-element-starter-js/archive/master.zip)
    *   [TypeScript starter project](https://github.com/PolymerLabs/lit-element-starter-ts/archive/master.zip)

1.  Uncompress the zip file.

1.  Install dependencies.

    ```bash
    cd <project folder>
    npm i
    ```

<div class="alert alert-info">

**Want it on GitHub?** If you're familiar with git you may want to create a GitHub repository for your starter project,
instead of just downloading the zip file. You can use the [GitHub template repository](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template) feature to create your own repository from the [JavaScript starter project ](https://github.com/PolymerLabs/lit-element-starter-js) or the [TypeScript starter project](https://github.com/PolymerLabs/lit-element-starter-ts). Then clone your new repository and install dependencies, as above.

</div>

### Try out your project

1.  **If you're using the TypeScript version of the starter**, build the JavaScript version of your project:

    ```bash
    npm run build
    ```

    To watch files and rebuild when the files are modified, run the following command in a separate shell:

    ```bash
    npm run build:watch
    ```

    **No build step is required if you're using the JavaScript version of the starter project.**

1.  Run the dev server:

    ```bash
    npm run serve
    ```

1.  Open the project demo page in a browser tab. For example:

    [http://localhost:8000/dev/](http://localhost:8000/dev/)

    Your server may use a different port number. Check the URL in the terminal output for the correct port number.


### Edit your component

Edit your component definition. The file you edit depends on which language you're using:

*   JavaScript. Edit the `my-element.js` file in the project root.
*   TypeScript. Edit the `my-element.ts` file in the `src` directory.

A couple of things to look for in the code:

*   The code defines a class for the component (`MyElement`) and registers it with the browser as a custom element named `<my-element>`.

    _JavaScript_

    ```js
    export class MyElement extends LitElement { ... } 

    customElements.define('my-element', MyElement);
    ``` 

    _TypeScript_

    ```ts
    @customElement('my-element')
    export class MyElement extends LitElement { ... } 
    ```


*   The component's `render` method defines a [template](templates) that will be rendered as a part of the component. In this case, it includes some text, some data bindings, and a button. For more information, see [Templates](templates).

    ```js
    export class MyElement extends LitElement {
      ...
      render() {
        return html`
          <h1>Hello, ${this.name}!</h1>
          <button @click=${this._onClick}>
            Click Count: ${this.count}
          </button>
          <slot></slot>
        `;
      }
    }
    ```

*   The component defines some [properties](properties). The component responds to changes in these properties (for example, by re-rendering the template when necessary). For more information, see [Properties](properties). 

    _JavaScript_

    ```js
    export class MyElement extends LitElement {

      static get properties() {
        return {
          name: {type: String}
        }
      }

      constructor() {
        super();
        this.name = 'World';
      }
      ...
    }
    ```

    _TypeScript_

    ```ts
    export class MyElement extends LitElement {
      ...
      @property({type: String})
      name = 'World';
      ...
    }
    ```

### Rename your component

You'll probably want to change the component name from "my-element" to something more appropriate. This is easiest to do using an IDE or other text editor that lets you do a global search and replace through an entire project.

1.  **If you're using the TypeScript version**, remove generated files:

    ```bash
    npm run clean
    ```

1.  Search and replace "my-element" with your new component name in all files in your project (except in the `node_modules` folder).
1.  Search and replace "MyElement" with your new class name in all files in your project (except in the `node_modules` folder).
1.  Rename the source and test files to match the new component name:

    JavaScript:

    * `src/my-element.js`
    * `src/test/my-element_test.js`

    TypeScript:

    * `src/my-element.ts`
    * `src/test/my-element_test.ts`

1.  **If you're using the TypeScript version**, rebuild the project:

    ```bash
    npm run build
    ```

1.  Test and make sure your component is still working:

    ```bash
    npm run serve
    ```

### Next steps

Ready to add features to your new component? Head over to [Templates](templates) for details on writing templates for your LitElement component.

For details on running tests and using other tools, see the starter project README:

*   [TypeScript project README](https://github.com/PolymerLabs/lit-element-starter-ts/blob/master/README.md)
*   [JavaScript project README](https://github.com/PolymerLabs/lit-element-starter-js/blob/master/README.md)

## Add LitElement to an existing project {#existing-project}

You don't need a lot of tooling for LitElement projects. Chances are if you have an existing set of tools, you can integrate LitElement into it with very limited changes. These instructions assume you're using npm for package management, and using a tool like Rollup or webpack to bundle your code for production.

For details on building projects, including some sample Rollup configurations, see [Build for production](build).

<div class="alert alert-info">

**If you're starting from scratch**, the open-wc project has a [project generator](https://open-wc.org/guides/developing-components/getting-started/) that can scaffold out an application project using LitElement.

</div>

### Prerequisites

Your build system will need to handle consuming bare module specifiers:

```js
import {LitElement, html} from 'lit-element';
```

Webpack automatically handles bare module specifiers; for Rollup, you'll need a plugin ([@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve)).

### Install LitElement

LitElement is available from npm:

```bash
npm i lit-element 
```

### Add an element

Pick a location to store your LitElement components, and create a test element: 

_components/my-element.js_

```js
import {LitElement, html} from 'lit-element';

class MyElement extends LitElement {
  render() {
    return html`
      <div>Hello from MyElement!</div>
    `;
  }
}

customElements.define('my-element', MyElement);
```

Import your component:

Index.js

```js
import './components/my-elements.js';
```

Use your component:

index.html

```html
<my-element></my-element>
```

At this point, you should be able to build and run your project and see the "Hello from MyElement!" message.

### Adjust for your build system

How you import the component may vary slightly depending on your build system and project structure. If you're writing in TypeScript, you'll use TypeScript files and use LitElement's decorators. (You can find a sample TypeScript element in the [TypeScript starter project](https://github.com/PolymerLabs/lit-element-starter-ts/blob/master/src/my-element.ts)).

For more details and sample build configurations, see [Build for production](build).

### Optional: Use ES dev server

If you already have a dev server that works with your build system, it should work with LitElement. [ES dev server](https://open-wc.org/developing/es-dev-server.html) is an alternative dev server that provides a simple, bundler-free workflow. It performs a small number of useful transforms, including transforming bare module specifiers, transpiling to ES5 when needed, and adding polyfills for older browsers.

1. Install es-dev-server

    ```bash
    npm i -D es-dev-server
    ```

1. Add a dev server command to `package.json`: 


    ```json
    {
      "scripts": {
        "serve": "es-dev-server --app-index index.html --node-resolve --watch --open"
      }
    }
    ```

1. Start ES dev server:

    ```bash
    npm run serve
    ```

### Supporting older browsers

To support older browsers that don't support ES6 and the web components specifications, you'll need to take a few extra steps to produce code that will run on the older browsers. 

See [Build for production](build) for more information.

### Next steps

Ready to add features to your project? Head over to [Templates](templates) for details on writing templates for your LitElement component.

For more on building applications that use web components, see the open-wc recommendations on [Building](https://open-wc.org/building/).

---

###  Guide Styles (`docs/_guide/styles.md`)

---
layout: guide
title: Styles
slug: styles
lit_dev_path: /docs/components/styles/
---

{::options toc_levels="1..3" /}
* ToC
{:toc}

This page describes how to add styles to your component.

Your component's template is rendered to its shadow DOM tree. The styles you add to your component are automatically _scoped_ to the shadow tree, so they don't leak out and affect other elements. 


## Add styles to your component {#add-styles}

For optimal performance, define scoped styles in a static `styles` property. 

Define styles in a tagged template literal, using the `css` tag function:  

```js
import { LitElement, css, html } from 'lit-element';

class MyElement extends LitElement {
  static get styles() {
    return css`
      div { color: red; }
    `;
  }
  render() { 
    return html`
      <div>I'm styled!</div> 
    `;
  }
}
```

The styles you add to your component are _scoped_ using shadow DOM. For a quick overview of shadow DOM styling, see [Shadow DOM styling overview](#shadow-dom).

The value of the static `styles` property can be:
    
*   A single tagged template literal.
    
    ```js
    static get styles() {
      return css`...`;
    } 
    ```

*   An array of tagged template literals.

    ```js
    static get styles() {
      return [ css`...`, css`...`];
    }
    ```

The static `styles` property is _usually_ the best way to add styles to your component, but 
there are some use cases you can't handle this way—for example, linking to an external style sheet.
For alternate ways to add styles, see [Define scoped styles in the template](#styles-in-the-template).

### Expressions in static styles {#expressions}

Static styles apply to all instances of a component. Any expressions in CSS are evaluated **once**, then reused for all instances. 

To allow for theming or per-instance style customization, use CSS variables and custom properties to create [configurable styles](#configurable).

To prevent LitElement-based components from evaluating potentially malicious code, the `css` tag only  allows nested expressions that are themselves `css` tagged strings or numbers.

```js
{% include projects/style/nestedcss/my-element.js %}
```

{% include project.html folder="style/nestedcss" openFile="my-element.js" %}

This restriction exists to protect applications from security vulnerabilities whereby malicious styles, or even malicious code, can be injected from untrusted sources such as URL parameters or database values.

If you must use an expression in a `css` literal that is not itself a `css` literal, **and** you are confident that the expression is from a fully trusted source such as a constant defined in your own code, then you can wrap the expression with the `unsafeCSS` function:

```js
{% include projects/style/unsafecss/my-element.js %}
```

{% include project.html folder="style/unsafecss" openFile="my-element.js" %}

{:.alert .alert-warning}
<div>

**Only use the `unsafeCSS` tag with trusted input.** Injecting unsanitized CSS is a security risk. For example,
malicious CSS can "phone home" by adding an image URL that points to a third-party server.

</div>

### Inheriting styles

Using an array of tagged template literals, a component can inherit the styles from a LitElement superclass, and add its own styles:

```js
class MyElement extends SuperElement {
  static get styles() {
    return [
      super.styles,
      css`...`
    ];
  }
}
```

{% include project.html folder="style/superstyles" openFile="my-element.js" %}

### Sharing styles

You can share styles between components by creating a module that exports tagged
styles:

```js
import { css } from 'lit-element';

export const buttonStyles = css`
  .blue-button {
    color: white;
    background-color: blue;
  }
  .blue-button:disabled {
    background-color: grey;
  }`;
```

Your element can then import the styles and add them to its static `styles` property:

```js
import { buttonStyles } from './button-styles.js';

class MyElement extends LitElement {
  static get styles() {
    return [
      buttonStyles,
      css`
        :host { display: block;
          border: 1px solid black;
        }`
    ]
  }
  ...
}
```

You can also import an external style sheet by adding a `<link>` element to your template, but this has a number of limitations. For details, see [Import an external stylesheet](#external-stylesheet).

## Shadow DOM styling overview {#shadow-dom}

This section gives a brief overview of shadow DOM styling.

Styles you add to a component can affect:

* The shadow tree (your component's rendered template).
* The component itself.
* The component's children.


### Style the shadow tree {#shadowroot}

LitElement templates are rendered into a shadow tree by default. Styles scoped to an element's shadow tree don't affect the main document or other shadow trees. Similarly, with the exception of [inherited CSS properties](#inheritance), document-level styles don't affect the contents of a shadow tree.

When you use standard CSS selectors, they only match elements in your component's shadow tree.

```js
class MyElement extends LitElement {
  static get styles() {
    // Write styles in standard CSS
    return css`
      * { color: red; }
      p { font-family: sans-serif; }
      .myclass { margin: 100px; }
      #main { padding: 30px; }
      h1 { font-size: 4em; }
    `;
  }
  render() {
    return html`
      <p>Hello World</p>
      <p class="myclass">Hello World</p>
      <p id="main">Hello World</p>
      <h1>Hello World</h1>
    `;
  }
}
```

{% include project.html folder="style/styleatemplate" openFile="my-element.js" %}

### Style the component itself

You can style the component itself using special `:host` selectors. (The element that owns, or "hosts" a shadow tree is called the _host element_.)

To create default styles for the host element, use the `:host` CSS pseudo-class and `:host()` CSS pseudo-class function.

*   `:host` selects the host element.

*   <code>:host(<var>selector</var>)</code> selects the host element, but only if the host element matches _selector_.

```js
static get styles() {
  return css`
    /* Selects the host element */
    :host { 
      display: block; 
    }

    /* Selects the host element if it is hidden */
    :host([hidden]) { 
      display: none; 
    }
  `;
}
```

{% include project.html folder="style/host" openFile="my-element.js" %}

Note that the host element can be affected by styles from outside the shadow tree, as well, so you should consider 
the styles you set in `:host` and `:host()` rules as _default styles_ that can be overridden by the user. For example:

```css
my-element {
  display: inline-block;
}
```

### Style the component's children

Your component may accept children (like a `<ul>` element can have `<li>` children). To render children, your template needs to include one or more `<slot>` elements, as described in [Render children with the slot element](templates#slots).

The `<slot>` element acts as a placeholder in a shadow tree where the host element's children are displayed. For example: 

```js
class MyElement extends LitElement {
  render() {
    return html`<slot></slot>`;
  }
}
```

```html
<my-element><p>Slotted content</p></my-element>
```

{% include project.html folder="style/slottedbase" openFile="my-element.js" %}

Use the `::slotted()` CSS pseudo-element to select children that are included in your template via `<slot>`s.

*   `::slotted(*)` matches all slotted elements.

*   `::slotted(p)` matches slotted paragraphs.

*   `p ::slotted(*)` matches slotted elements where the `<slot>` is a descendant of a paragraph element.

    ```html
    <p>
      <slot></slot>
    </p>
    ```

```js
{% include projects/style/slottedselector/my-element.js %}
```

{% include project.html folder="style/slottedselector" openFile="my-element.js" %}

Note that **only direct slotted children** can be styled with `::slotted()`. 

```html
<my-element>
  <div>Stylable with ::slotted()</div>
</my-element>

<my-element>
  <div><p>Not stylable with ::slotted()</p></div>
</my-element>
```

Also, children can 
be styled from outside the shadow tree, so you should regard your `::slotted()` styles as
default styles that can be overridden.

```css
my-element div {
  // Outside style targetting a slotted child can override ::slotted() styles
}
```


{:.alert .alert-info}
<div>

**Watch out for limitations in the Shady CSS polyfill around slotted content!** See the [Shady CSS limitations](https://github.com/webcomponents/polyfills/tree/master/packages/shadycss#limitations) for details on how to use the `::slotted()` syntax in a polyfill-friendly way. 

</div>

### Configurable styles with custom properties {#configurable}

Static styles are evaluated once per class. Use CSS variables and custom properties to make styles that can be configured at runtime:

```js
static get styles() {
  return css`
    :host { color: var(--themeColor); }
  `;
} 
```

```html
<style>
  html { 
    --themeColor: #123456;
  }
</style>
<my-element></my-element>
```

See the section on [CSS custom properties](#customprops) for more information. 



## Define scoped styles in the template {#styles-in-the-template}

We recommend using static styles for optimal performance.  However, sometimes you may want to
define styles in the LitElement template. There are two ways to add scoped styles in the template:

*   Add styles using a `<style>` element.
*   Add styles using an external style sheet.

Each of these techniques has its own set of advantages and drawbacks.

### In a style element

We recommend using static styles for optimal performance. However, static styles are evaluated **once per class**. Sometimes, you might need to evaluate styles per instance.

We recommend using CSS properties to create [customizable styles](#customizable). However, you can also include `<style>` elements in a LitElement template. These are updated per instance.

```js
render() {
  return html`
    <style>
      /* updated per instance */
    </style>
    <div>template content</div>
  `;
}
```

#### Expressions and style elements

The most intuitive way to evaluate per-instance styles has some important limitations and performance issues. We consider the example below to be an anti-pattern:

```text
// Anti-pattern!
render() {
  return html`
    <style>
      :host {
        /* Warning: this approach has limitations & performance issues! */
        color: ${myColor}
      } 
    </style>
    <div>template content</div>
  `;
}
```

Expressions inside a `<style>` element won't update per instance in ShadyCSS, due to limitations of the ShadyCSS polyfill. See the [ShadyCSS readme](https://github.com/webcomponents/polyfills/tree/master/packages/shadycss#limitations) for more information.

Additionally, evaluating an expression inside a `<style>` element is inefficient. When any text inside a `<style>` element changes, the browser must re-parse the whole `<style>` element, resulting in unnecessary work. 

If you need to evaluate expressions inside a `<style>` element, use the following strategy to avoid creating performance problems:

*   Separate styles that require per-instance evaluation from those that don't.

*   Evaluate per-instance CSS properties by creating an expression that captures that property inside a complete `<style>` block. Include it in your template.

**Example**

```js
{% include projects/style/perinstanceexpressions/my-element.js %}
```

{% include project.html folder="style/perinstanceexpressions" openFile="my-element.js" %}

### Import an external stylesheet {#external-stylesheet}

We recommend placing your styles in a static `styles` property for optimal performance. However, you can include an external style sheet in your template with a `<link>`:

```js
{% include projects/style/where/my-element.js %}
```

{% include project.html folder="style/where" openFile="my-element.js" %}

There are some important caveats though:

*  The [ShadyCSS polyfill](https://github.com/webcomponents/shadycss/blob/master/README.md#limitations) doesn't support external style sheets.

*   External styles can cause a flash-of-unstyled-content (FOUC) while they load.

*   The URL in the `href` attribute is relative to the **main document**. This is okay if you're building an app and your asset URLs are well-known, but avoid using external style sheets when building a reusable element.

## Dynamic classes and styles

One way to make styles dynamic is to add bindings to the `class` or `style` attributes in your template.

The lit-html library offers two directives, `classMap` and `styleMap`, to conveniently apply classes and styles in HTML templates. 

For more information on these and other lit-html directives, see the documentation on [lit-html built-in directives](https://lit-html.polymer-project.org/guide/template-reference#built-in-directives).

To use `styleMap` and/or `classMap`:

1.  Import `classMap` and/or `styleMap`:

    ```js
    import { classMap } from 'lit-html/directives/class-map';
    import { styleMap } from 'lit-html/directives/style-map';
    ```

2.  Use `classMap` and/or `styleMap` in your element template:

    ```js
    constructor() {
      super();
      this.classes = { mydiv: true, someclass: true };
      this.styles = { color: 'green', fontFamily: 'Roboto' };
    }
    render() {
      return html`
        <div class=${classMap(this.classes)} style=${styleMap(this.styles)}>
          Some content
        </div>
      `;
    }
    ```

{% include project.html folder="style/maps" openFile="my-element.js" %}

### classMap syntax {#classmap}

`classMap` applies a set of classes to an HTML element:

```html
<div class=${classMap({alert:true,info:true})}>Content.</div>

```

{% include project.html folder="style/classmap" openFile="my-element.js" %}

### styleMap syntax {#stylemap}

`styleMap` applies a set of CSS rules to an HTML element:

```html
<button style=${styleMap({
  backgroundColor: 'blue',
  border: '1px solid black'
})}>A button</button>


```

{% include project.html folder="style/stylemap" openFile="my-button.js" %}

To refer to hyphenated properties such as `font-family`, use the camelCase equivalent (`fontFamily`) or place the hyphenated property name in quotes (`'font-family'`). 

To refer to custom CSS properties such as `--custom-color`, place the whole property name in quotes (`'--custom-color'`).

|**Inline style or CSS**|**styleMap equivalent**|
|----|----|
| `background-color: blue;` <br/> | `backgroundColor: 'blue'` <br/><br/> or <br/><br/>`'background-color': 'blue'`|
| `font-family: Roboto, Arial, sans-serif;` <br/> | `fontFamily: 'Roboto, Arial, sans-serif'` <br/><br/> or <br/><br/>`'font-family': 'Roboto, Arial, sans-serif'`|
|`--custom-color: #FFFABC;`|`'--custom-color': '#FFFABC;'`|
|`--otherCustomColor: #FFFABC;`|`'--otherCustomColor': '#FFFABC;'`|
|`color: var(--customprop, blue);`|`color: 'var(--customprop, blue)'`|

**Examples**

Inline style syntax:

```html 
<div style="
  background-color:blue;
  font-family:Roboto;
  --custom-color:#e26dd2;
  --otherCustomColor:#77e26d;">
</div>
```

Equivalent CSS syntax:

```css
div {
  background-color: blue;
  font-family: Roboto;
  --custom-color: #e26dd2;
  --otherCustomColor: #77e26d;
}
```

Equivalent `styleMap` syntax:

```js 
html`
  <div style=${styleMap({
    'background-color': 'blue',
    fontFamily: 'Roboto',
    '--custom-color': '#e26dd2',
    '--otherCustomColor': '#77e26d'
  })}></div>
`
```

{% include project.html folder="style/stylemap2" openFile="index.html" %}

## Theming

*   Use [**CSS inheritance**](#inheritance) to propagate style information to LitElement components and their rendered templates.

    ```html
    <style>
      html {
        --themeColor: #123456;
        font-family: Roboto;
      }
    </style>

    
    <my-element></my-element>
    ```

*   Use [**CSS variables and custom properties**](#customprops) to configure styles per-instance.

    ```html
    <style>
      html {
        --my-element-background-color: /* some color */;
      }
      .stuff {
        --my-element-background-color: /* some other color */;
      }
    </style>
    <my-element></my-element>
    <my-element class="stuff"></my-element>
    ```

    ```js
    // MyElement's static styles
    static get styles() {
      return css`
        :host {
          background-color: var(--my-element-background-color);
        }
      `;
    }
    ```

### CSS inheritance {#inheritance}

CSS inheritance lets parent and host elements propagate certain CSS properties to their descendents.

Not all CSS properties inherit. Inherited CSS properties include:

* `color`
* `font-family` and other `font-*` properties
* All CSS custom properties (`--*`)

See [CSS Inheritance on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/inheritance) for more information.

You can use CSS inheritance to set styles on an ancestor element that are inherited by its descendents:

```html
<style>
html { 
  font-family: Roboto;
}
</style>
<div>
  <p>Uses Roboto</p>
</div>
```

Similarly, host elements pass down inheritable CSS properties to their shadow trees. 

You can use the host element's type selector to style it:

```html
<style>
  my-element { font-family: Roboto; }
</style>
<my-element></my-element>
```

```js
class MyElement extends LitElement {
  render() { 
    return html`<p>Uses Roboto</p>`; 
  }
}
```

{% include project.html folder="style/inherited3" openFile="index.html" %}

You can also use the `:host` CSS pseudo-class to style the host from inside its own template:

```js
static get styles() {
  return css`
    :host {
      font-family: Roboto;
    }
  `;
}
render() {
  return html`
    <p>Uses Roboto</p>
  `;
}
```

{% include project.html folder="style/inherited" openFile="my-element.js" %}

{:.alert .alert-info}
<div id="specificity">

**Type selectors have higher specificity than :host.**

An element type selector has higher specificity than the `:host` pseudo-class selector. Styles set for a custom element tag will override styles set with `:host` and `:host()`:

```html
<style>
  my-element { font-family: Courier; }
</style>
<my-element></my-element>
```

```js
class MyElement extends LitElement {
  static get styles() { 
    return css`:host { font-family: Roboto; }`
  }
  render() {
    return html`<p>Will use courier</p>`;
  }
}
```

{% include project.html folder="style/specificity" openFile="index.html" %}

</div>

### CSS custom properties {#customprops}

All CSS custom properties (<code>--<var>custom-property-name</var></code>) inherit. You can use this to make your component's styles configurable from outside. 

The following component sets its background color to a CSS variable. The CSS variable uses the value of `--my-background` if it's available, and otherwise defaults to `yellow`:

```js
class MyElement extends LitElement {
  static get styles() { 
    return css`
      :host { 
        background-color: var(--my-background, yellow); 
      }
    `;
  }
  render() {
    return html`<p>Hello world</p>`;
  }
}
```

Users of this component can set the value of `--my-background`, using the `my-element` tag as a CSS selector:

```html
<style>
  my-element {
    --my-background: rgb(67, 156, 144);
  }
</style>
<my-element></my-element>
```

`--my-background` is configurable per instance of `my-element`:

```html
<style>
  my-element {
    --my-background: rgb(67, 156, 144);
  }
  my-element.stuff {
    --my-background: #111111;
  }
</style>
<my-element></my-element>
<my-element class="stuff"></my-element>
```

If a component user has an existing app theme, they can easily set the host's configurable properties to use theme properties:

```html
{% include projects/style/customproperties/index.html %}
```

{% include project.html folder="style/customproperties" openFile="index.html" %}

See [CSS Custom Properties on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) for more information.

### A simple example theme {#example-theme}

_index.html_

```html
{% include projects/style/theming/index.html %}
```

_my-element.js_

```js
{% include projects/style/theming/my-element.js %}
```

{% include project.html folder="style/theming" openFile="theme.css" %}

---

###  Guide Templates (`docs/_guide/templates.md`)

---
layout: guide
title: Templates
slug: templates
lit_dev_path: /docs/components/rendering/
---

{::options toc_levels="1..3" /}
* ToC
{:toc}

Add a template to your component to define internal DOM to implement your component.

To encapsulate the templated DOM LitElement uses
[shadow DOM](https://developers.google.com/web/fundamentals/web-components/shadowdom).
Shadow DOM provides three benefits:

* DOM scoping. DOM APIs like `document.querySelector` won't find elements in the
  component's shadow DOM, so it's harder for global scripts to accidentally break your component.
* Style scoping. You can write encapsulated styles for your shadow DOM that don't
  affect the rest of the DOM tree.
* Composition. The component's shadow DOM (managed by the component) is separate from the component's children. You can choose how children are rendered in your templated DOM. Component users can add and remove children using standard DOM APIs without accidentally breaking anything in your shadow DOM.

Where native shadow DOM isn't available, LitElement
uses the [Shady CSS](https://github.com/webcomponents/polyfills/tree/master/packages/shadycss) polyfill.


## Define and render a template

To define a template for a LitElement component, write a `render` function for your element class:

```js
import { LitElement, html } from 'lit-element';

class MyElement extends LitElement {
  render() {
    return html`<p>template content</p>`;
  }
}
```

*   Write your template in HTML inside a JavaScript [template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) by enclosing the raw HTML in back-ticks
    (<code>``</code>).


*   Tag your template literal with the [`html`](https://lit-html.polymer-project.org/api/modules/lit_html.html#html)
    tag function.

*   The component's `render` method can return anything that lit-html can render. Typically, it
    returns a single `TemplateResult` object (the same type returned by the `html` tag function).

Example

```js
{% include projects/docs/templates/define/my-element.js %}
```

{% include project.html folder="docs/templates/define" openFile="my-element.js" %}

LitElement uses lit-html templates; this page summarizes the features of lit-html templates,
for more details, see [Writing templates](https://lit-html.polymer-project.org/guide/writing-templates)
and the [Template syntax reference](https://lit-html.polymer-project.org/guide/template-reference)
in the lit-html documentation.

### Design a performant template

LitElement renders and re-renders asynchronously, updating in response to batched property changes (see [Element update lifecycle](#lifecycle) for more information).

During an update, only the parts of the DOM that change are re-rendered. To get the performance benefits of this model, you should **design your element's template as a pure function of its properties**.

To do this, make sure the `render` function:

* Does not change the element's state.
* Does not have any side effects.
* Only depends on the element's properties.
* Returns the same result when given the same property values.

Also, avoid making DOM updates outside of `render`. Instead, express the element's template as a function of its state, and capture its state in properties.

The following code uses inefficient DOM manipulation:

_dom-manip.js_

```text
// Anti-pattern. Avoid!

constructor() {
  super();
  this.addEventListener('stuff-loaded', (e) => {
    this.shadowRoot.getElementById('message').innerHTML=e.detail;
  });
  this.loadStuff();
}
render() {
  return html`
    <p id="message">Loading</p>
  `;
}
```

We can improve the template by declaring the message as a property, and binding the property into the template. Declaring a property tells your component to re-render its template when the property changes.


_update-properties.js_

```js
static get properties() {
  return {
    message: {type: String}
  }
}

constructor() {
  super();
  this.message = 'Loading';
  this.addEventListener('stuff-loaded', (e) => { this.message = e.detail } );
  this.loadStuff();
}
render() {
  return html`
    <p>${this.message}</p>
  `;
}
```

{% include project.html folder="docs/templates/design" openFile="update-properties.js" %}

The following sections discuss different types of property bindings. See [Properties](properties) for information on declaring properties.

### Use properties, loops, and conditionals in a template

When defining your element's template, you can bind the element's properties to the
template; the template is re-rendered whenever the properties change.

#### Properties

To add a property value to a template, insert it with `${this.propName}`:

```js
static get properties() {
  return {
    myProp: {type: String}
  };
}
...
render() {
  return html`<p>${this.myProp}</p>`;
}
```

#### Loops

Iterate over an array:

```js
html`<ul>
  ${this.myArray.map(i => html`<li>${i}</li>`)}
</ul>`;
```

<div class="alert alert-info">

**repeat directive**. In most cases, `Array.map` is the most efficient way to create a repeating template. In some cases, you may want to consider lit-html's `repeat` directive. In particular, if the repeated elements are stateful, or very expensive to regenerate. For more information, see [Repeating templates with the repeat directive](https://lit-html.polymer-project.org/guide/writing-templates#repeating-templates-with-the-repeat-directive) in the lit-html docs.

</div>
#### Conditionals

Render based on a Boolean condition:

```js
html`
  ${this.myBool?
    html`<p>Render some HTML if myBool is true</p>`:
    html`<p>Render some other HTML if myBool is false</p>`}
`;
```

#### Examples

```js
{% include projects/docs/templates/expressions/my-element.js %}
```

{% include project.html folder="docs/templates/expressions" openFile="my-element.js" %}

### Bind properties to templated elements

You can insert JavaScript expressions as placeholders for HTML text content, attributes, Boolean attributes, properties, and event handlers.

* Text content: `<p>${...}</p>`
* Attribute: `<p id="${...}"></p>`
* Boolean attribute: `?disabled="${...}"`
* Property: `.value="${...}"`
* Event handler: `@event="${...}"`

JavaScript expressions can include your element's properties. LitElement observes and reacts to property changes, so your templates update automatically.

Data bindings are always one-way (parent to child). To share data from a child element to its parent, fire an event and capture the relevant data in the `detail` property.

#### Bind to text content

Bind `prop1` to text content:

```js
html`<div>${this.prop1}</div>`
```

#### Bind to an attribute

Bind `prop2` to an attribute:

```js
html`<div id="${this.prop2}"></div>`
```

Attribute values are always strings, so an attribute binding should return a value that can be converted into a string.

#### Bind to a boolean attribute

Bind `prop3` to a boolean attribute:

```js
html`<input type="text" ?disabled="${this.prop3}">`
```

Boolean attributes are added if the expression evaluates to a truthy value, and removed if it evaluates to a falsy value.

#### Bind to a property

Bind `prop4` to a property:

```js
html`<input type="checkbox" .value="${this.prop4}"/>`
```

#### Bind to an event handler

Bind `clickHandler` to a `click` event:

```js
html`<button @click="${this.clickHandler}">pie?</button>`
```

The default event context for `@event` expressions is `this`, so there is no need to bind the handler function.

#### Examples

_my-element.js_

```js
{% include projects/docs/templates/databinding/my-element.js %}
```

{% include project.html folder="docs/templates/databinding" openFile="my-element.js" %}

### Render children with the slot element {#slots}

Your component may accept children (like a `<ul>` element can have `<li>` children).

```html
<my-element>
  <p>A child</p>
</my-element>
```
By default, if an element has a shadow tree, its children don't render at all.

To render children, your template needs to include one or more [`<slot>` elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot), which act as placeholders for child nodes.

<div class="alert alert-info">

**Finding slotted children.** If your component needs information about its slotted children, see [Accessing slotted children](#accessing-slotted-children).

</div>

#### Use the slot element

To render an element's children, create a `<slot>` for them in the element's template. For example:

```js
render(){
  return html`
    <div>
      <slot></slot>
    </div>
  `;
}
```

Children will now render in the `<slot>`:

```html
<my-element>
  <p>Render me</p>
</my-element>
```

The children aren't _moved_ in the DOM tree, but they're rendered _as if_ they were children of the `<slot>`.

Arbitrarily many children can populate a single slot:

```html
<my-element>
  <p>Render me</p>
  <p>Me too</p>
  <p>Me three</p>
</my-element>
```

{% include project.html folder="docs/templates/slots" openFile="my-element.js" %}

#### Use named slots

To assign a child to a specific slot, ensure that the child's `slot` attribute matches the slot's `name` attribute:

```js
render(){
  return html`
    <div>
      <slot name="one"></slot>
    </div>
  `;
}
```

_index.html_

```html
<my-element>
  <p slot="one">Include me in slot "one".</p>
</my-element>
```

* **Named slots only accept children with a matching `slot` attribute.**

  For example, `<slot name="one"></slot>` only accepts children with the attribute `slot="one"`.

* **Children with a `slot` attribute will only be rendered in a slot with a matching `name` attribute.**

  For example, `<p slot="one">...</p>` will only be placed in `<slot name="one"></slot>`.

**Examples**

_my-element.js_

```js
{% include projects/docs/templates/namedslots/my-element.js %}
```

_index.html_

```html
{% include projects/docs/templates/namedslots/index.html %}
```

{% include project.html folder="docs/templates/namedslots" openFile="my-element.js" %}

**Use `name`, not `id`, to select slots.**

Note that a `slot`'s `id` attribute has no effect!

_my-element.js_

```js
render(){
  return html`
    <div>
      <slot id="one"></slot>
    </div>
  `;
}
```

_index.html_

```html
<my-element>
  <p slot="one">nope.</p>
  <p>ohai..</p>
</my-element>
```

{% include project.html folder="docs/templates/slotid" openFile="my-element.js" %}

## Compose a template from other templates

You can compose LitElement templates from other LitElement templates. In the following example, we compose a template for an element called `<my-page>` from smaller templates for the page's header, footer, and main content:

```js
  function headerTemplate(title) {
    return html`<header>${title}</header>`;
  }
  function articleTemplate(text) {
    return html`<article>${text}</article>`;
  }
  function footerTemplate() {
    return html`<footer>Your footer here.</footer>`;
  }

class MyPage extends LitElement {
  ...
  render() {
    return html`
      ${headerTemplate(this.article.title)}
      ${articleTemplate(this.article.text)}
      ${footerTemplate()}
    `;
  }
}
```

{% include project.html folder="docs/templates/compose" openFile="my-page.js" %}

You can also compose templates by importing other elements and using them in your template:

```js
import './my-header.js';
import './my-article.js';
import './my-footer.js';

class MyPage extends LitElement {
  render() {
    return html`
      <my-header></my-header>
      <my-article></my-article>
      <my-footer></my-footer>
    `;
  }
}
```

{% include project.html folder="docs/templates/composeimports" openFile="my-page.js" %}

## Specify the render root {#renderroot}

The node into which your component's template will render is called its **render root**.

By default, LitElement creates an open `shadowRoot` and renders inside it, producing the following DOM structure:

```text
<my-element>
  #shadow-root
    <p>child 1</p>
    <p>child 2</p>
```

To customize a component's render root, implement `createRenderRoot` and return the node you want the template to render into.

For example, to render the template into the main DOM tree as your element's children:

```text
<my-element>
  <p>child 1</p>
  <p>child 2</p>
```

Implement `createRenderRoot` and return `this`:

```js
class LightDom extends LitElement {
  render() {
    return html`
      <p>This template renders without shadow DOM.</p>
    `;
  }
  createRenderRoot() {
  /**
   * Render template without shadow DOM. Note that shadow DOM features like
   * encapsulated CSS and slots are unavailable.
   */
    return this;
  }
}
```

{% include project.html folder="docs/templates/renderroot" openFile="my-element.js" %}

## Template syntax cheat sheet

#### Render

```js
render() { return html`<p>template</p>`; }
```

#### Properties, loops, conditionals

```js
// Property
html`<p>${this.myProp}</p>`;

// Loop
html`${this.myArray.map(i => html`<li>${i}</li>`)}`;

// Conditional
html`${this.myBool?html`<p>foo</p>`:html`<p>bar</p>`}`;
```

#### Data bindings

```js
// Attribute
html`<p id="${...}">`;

// Boolean attribute
html`<input type="text" ?disabled="${...}">`;

// Property
html`<input .value="${...}">`;

// Event handler
html`<button @click="${this.doStuff}"></button>`;
```

#### Composition

```js
// From multiple templates on same class

render() {
  return html`
    ${this.headerTemplate}
    <article>article</article>
  `;
}
get headerTemplate() {
  return html`<header>header</header>`;
}
```

```js
// By importing elements
import './my-header.js';

class MyPage extends LitElement{
  render() {
    return html`
      <my-header></my-header>
      <article>article</article>
    `;
  }
}
```

#### Slots

```js
render() { return html`<slot name="thing"></slot>`; }
```

```html
<my-element>
  <p slot="thing">stuff</p>
</my-element>
```

## Using other lit-html features

Since LitElement uses the lit-html `html` tag function to define templates you can take advantage
of the entire lit-html feature set for writing your templates. This includes lit-html _directives_,
special functions that customize the way lit-html renders a binding.

To import features directly from lit-html, your project should add lit-html as a direct dependency.
We recommend using the widest practical version range for lit-html, to minimize the chance of npm
installing two different versions of lit-html:

```bash
npm i lit-element@^2.0.0
npm i lit-html@^1.0.0
```

### Import and use a lit-html directive

You can import and use a lit-html directive and use it as shown in the [lit-html documentation](https://lit-html.polymer-project.org/guide/template-reference#built-in-directives).

```js
import { LitElement, html } from 'lit-element';
import { until } from 'lit-html/directives/until.js';

const content = fetch('./content.txt').then(r => r.text());

html`${until(content, html`<span>Loading...</span>`)}`
```

For a list of directives supplied with lit-html, see [Built-in directives](https://lit-html.polymer-project.org/guide/template-reference#built-in-directives) in the Template syntax reference.

## Accessing nodes in the shadow DOM
The `render()` method result is usually rendered into shadow DOM, so the nodes are not direct children of the component. Use `this.shadowRoot.querySelector()` or `this.shadowRoot.querySelectorAll()` to find nodes in the
shadow DOM.

You can query the templated DOM after its initial render (for example, in `firstUpdated`), or use a getter pattern, like this:

```js
get _closeButton() {
  return this.shadowRoot.querySelector('#close-button');
}
```

LitElement supplies a set of decorators that provide a shorthand way of defining getters like this.

More information:

*   [Element.querySelector()](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector) on MDN.
*   [Element.querySelectorAll()](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll) on MDN.

### @query, @queryAll, and @queryAsync decorators

The `@query`, `@queryAll`, and `@queryAsync` decorators all provide a convenient way to access nodes in the component's shadow root.

<div class="alert alert-info">

**Using decorators.** Decorators are a proposed JavaScript feature, so you’ll need to use a compiler like Babel or TypeScript to use decorators. See [Using decorators](decorators) for details.

</div>

The `@query` decorator modifies a class property, turning it into a getter that returns a node from the render root. The optional second argument is a cache flag which when true performs the DOM query only once and caches the result. This can be used as a performance optimization in cases when the node being queried is not expected to change.


```js
import {LitElement, html} from 'lit-element';
import {query} from 'lit-element/lib/decorators.js';

class MyElement extends LitElement {
  @query('#first')
  _first;

  render() {
    return html`
      <div id="first"></div>
      <div id="second"></div>
    `;
  }
}
```

This decorator is equivalent to:

```js
get first() {
  return this.renderRoot.querySelector('#first');
}
```

<div class="alert alert-info">

**shadowRoot and renderRoot**. The [`renderRoot`](/api/classes/_lit_element_.litelement.html#renderroot) property identifies the container that the template is rendered into. By default, this is the component's `shadowRoot`. The decorators use `renderRoot`, so they should work correctly even if you override `createRenderRoot` as described in [Specify the render root](#renderroot)

</div>

The `@queryAll` decorator is identical to `query` except that it returns all matching nodes, instead of a single node. It's the equivalent of calling `querySelectorAll`.


```js
import {LitElement, html} from 'lit-element';
import {queryAll} from 'lit-element/lib/decorators.js';

class MyElement extends LitElement {
  @queryAll('div')
  _divs;

  render() {
    return html`
      <div id="first"></div>
      <div id="second"></div>
    `;
  }
}
```

Here, `divs` would return both `<div>` elements in the template. For TypeScript, the typing of a `@queryAll` property is `NodeListOf<HTMLElement>`. If you know exactly what kind of nodes you'll retrieve, the typing can be more specific:

```js
@queryAll('button')
_buttons!: NodeListOf<HTMLButtonElement>
```

The exclamation point (`!`) after `buttons` is TypeScript's [non-null assertion operator](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator). It tells the compiler to treat `buttons` as always being defined, never `null` or `undefined`.

Finally, `@queryAsync` works like `@query`, except that instead of returning a node directly, it returns a `Promise` that resolves to that node. Code can use this instead of waiting for the `updateComplete` promise.

This is useful, for example, if the node returned by `@queryAsync` can change as a result of another property change.

## Accessing slotted children

To access children assigned to slots in your shadow root, you can use the standard `slot.assignedNodes` method and the `slotchange` event.

For example, you can create a getter to access assigned nodes for a particular slot:

```js
get _slottedChildren() {
  const slot = this.shadowRoot.querySelector('slot');
  const childNodes = slot.assignedNodes({flatten: true});
  return Array.prototype.filter.call(childNodes, (node) => node.nodeType == Node.ELEMENT_NODE);
}
```

You can also use the `slotchange` event to take action when the assigned nodes change. The following example extracts the text content of all of the slotted children.

```js
handleSlotchange(e) {
  const childNodes = e.target.assignedNodes({flatten: true});
  // ... do something with childNodes ...
  this.allText = Array.prototype.map.call(childNodes, (node) => {
    return node.textContent ? node.textContent : ''
  }).join('');
}

render() {
  return html`<slot @slotchange=${this.handleSlotchange}></slot>`;
}
```

More information:

*   [HTMLSlotElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSlotElement) on MDN.


### @queryAssignedNodes decorator

The `@queryAssignedNodes` decorator converts a class property into a getter that returns all of the assigned nodes for a given slot in the component's shadow tree. The optional second boolean argument when true flattens the assigned nodes, meaning any assigned nodes that are slot elements are replaced with their assigned nodes. The optional third argument is a css selector which filters the results to matching elements.

<div class="alert alert-info">

**Using decorators.** Decorators are a proposed JavaScript feature, so you’ll need to use a compiler like Babel or TypeScript to use decorators. See [Using decorators](decorators) for details.

</div>

```js
// First argument is the slot name
// Second argument is `true` to flatten the assigned nodes.
@queryAssignedNodes('header', true)
_headerNodes;

// If the first argument is absent or an empty string, list nodes for the default slot.
@queryAssignedNodes()
_defaultSlotNodes;
```

The first example above is equivalent to the following code:

```js
get headerNodes() {
  const slot = this.shadowRoot.querySelector('slot[name=header]');
  return slot.assignedNodes({flatten: true});
}
```

For TypeScript, the typing of a `queryAssignedNodes` property is `NodeListOf<HTMLElement>`.

## Resources

For more information on shadow DOM:

* [Shadow DOM v1: Self-Contained Web Components](https://developers.google.com/web/fundamentals/web-components/shadowdom) on Web Fundamentals.
* [Using shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM) on MDN.

For more information on lit-html templates:

* [Writing templates](https://lit-html.polymer-project.org/guide/writing-templates)
* [Template syntax reference](https://lit-html.polymer-project.org/guide/template-reference)

---

###  Guide Use (`docs/_guide/use.md`)

---
layout: guide
title: Use a component
slug: use
lit_dev_path: /docs/
---

{::options toc_levels="1..3" /}
* ToC
{:toc}

This page describes how to [use a LitElement component in your application](#use). It also describes how to make sure your deployed code is browser-ready by [building it for production](#build) and [loading the Web Components polyfills](#polyfills).

## Use a LitElement component {#use}

This is a general guide to using third-party LitElement components. Refer to a component's README or other documentation for specific details.

To use a LitElement component in your code:

1.  From your project folder, install the component from npm.

    ```
    npm install some-package-name
    ```

2.  Import the component.

    In a JavaScript module: 

    ```js
    import 'some-package-name';
    ```

    In an HTML page:

    ```html
    <script type="module">
    import './path-to/some-package-name/some-component.js';
    </script>
    ```

    Or:

    ```html
    <script type="module" src="./path-to/some-package-name/some-component.js"></script>
    ```

3.  Add the component to your application or component:

    ```html
    <some-component></some-component>
    ```

## Develop {#develop}

Elements built with LitElement are published to npm as standard JavaScript modules, which all major browsers can now load. 

However, LitElement and elements built with it import their dependencies using bare module specifiers (for example, `import { ... } from 'module-name'`) instead of full paths (`import {...} from '../path/to/module-name'`). 

At the time of writing, browsers must still be provided with the full path to a standard JavaScript module in order to load it. To convert bare module specifiers to full paths, a light transform is required.

For a local server that does this automatically, try the [Open Web Components ES dev server](https://open-wc.org/developing/es-dev-server.html). 

## Build for production {#build}

To build for production, you can use a bundler such as WebPack or Rollup.

The following example configuration for [Rollup](https://rollupjs.org/guide/en) resolves dependencies, converts bare module specifers to paths, and bundles the output.

**rollup.config.js**

```js
import resolve from 'rollup-plugin-node-resolve';

export default {
  // If using any exports from a symlinked project, uncomment the following:
  // preserveSymlinks: true,
	input: ['src/index.js'],
	output: {
		file: 'build/index.js',
		format: 'es',
		sourcemap: true
	},
	plugins: [
    resolve()
  ]
};
```

See a [sample build configuration for LitElement with Babel and Rollup](https://github.com/PolymerLabs/lit-element-build-rollup/blob/master/src/index.html).

## Load the WebComponents polyfills {#polyfills}

Elements built with LitElement use the Web Components set of standards, which are currently supported by all major browsers with the exception of Edge. 

For compatibility with older browsers and Edge, load the Web Components polyfills.

To load the WebComponents polyfills:

1.  From your project folder, install the `@webcomponents/webcomponentsjs` package:

    ```
    npm install --save-dev @webcomponents/webcomponentsjs
    ```

2.  Add the polyfills to your HTML entrypoint:

    ```html
    <head>
       
      

      
      <script 
        src="path-to/webcomponents-loader.js"
        defer>
      </script> 

      
      <script type="module">
        // Take care of cases in which the browser runs this
        // script before it has finished running 
        // webcomponents-loader.js (e.g. Firefox script execution order)
        window.WebComponents = window.WebComponents || { 
          waitFor(cb){ addEventListener('WebComponentsReady', cb) }
        }

        WebComponents.waitFor(async () => { 
          import('./path-to/some-element.js');
        });
      </script>
    </head>
    <body>
      
      <some-element></some-element>
    </body>
    ```

3.  Ensure that `node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js` and `node_modules/@webcomponents/webcomponentsjs/bundles/**.*` are included in your build.

<div class="alert"> 

**Do not transpile the polyfills.** Bundling them is okay.

</div>

See [the Webcomponentsjs documentation](https://github.com/webcomponents/webcomponentsjs) for more information.

---

###  Try Create (`docs/_try/create.md`)

---
layout: try
slug: create
title: Create a component
---

In this step, you'll fill in the gaps in the starting code to create an element class with a basic HTML template.

**Starting code**

_my-element.js_

```js
{% include projects/try/create/before/my-element.js %}
```

Click **Launch Code Editor** to edit the starting code. When you're ready to see your code in action, click **Preview**.

{% include project.html folder="try/create/before" openFile="my-element.js" %}

1.  **Import the `LitElement` base class and `html` helper function.**

    In my-element.js, replace the existing `import` statement with the following code:

    ```js
    import { LitElement, html } from 'lit-element';
    ```

2.  **Create a class for your element that extends the LitElement base class.**

    In my-element.js, replace the existing class definition with the following code:

    ```js
    class MyElement extends LitElement {
      render() {
        return html`
          <p>Hello world! From my-element</p>
        `;
      }
    }
    ```

    The `render` function defines your component's template. You must implement `render` for every LitElement component.

3.  **Register the new element with the browser.**

    In my-element.js, replace the existing call to `customElements.define()` with the following code:

    ```js
    customElements.define('my-element', MyElement);
    ```

Here's the completed code for this step:

_my-element.js_

```js
{% include projects/try/create/after/my-element.js %}
```

Your code sample should be working now. LitElement components are added to a page with simple HTML tags, like this:

```html
<my-element></my-element>
```

[Next: 2. Properties](properties)

---

###  Try Events (`docs/_try/events.md`)

---
layout: try
slug: events
title: Events
---

In this step, you'll use lit-html's `@event` annotation to add an event listener to an element inside your template. You'll also add an event handler method to your class which will fire whenever the event occurs.

**Starting code**

_my-element.js_

```js
{% include projects/try/events/before/my-element.js %}
```

{% include project.html folder="try/events/before" openFile="my-element.js" %}
  
1.  **Add a button with an event listener to your template.**

    In my-element.js, add the following `<button>` element to your HTML template:

    ```html
    <button @click=${this.clickHandler}>Click</button>
    ```

    The binding syntax `@click=${this.clickHandler}` adds a listener for the `click` event, which calls the `clickHandler` method.

2. **Add the `clickHandler` method to your class.** 

    Add the following method to your `MyElement` class:

    ```js
    clickHandler(event) {
      console.log(event.target);
      this.myBool = !this.myBool;
    }
    ```

    The `clickHandler` method toggles the boolean property, `myBool`, which you defined in the previous step.

Here's the completed code for this step:

_my-element.js_

```js
{% include projects/try/events/after/my-element.js %}
```

[Next: 5. Style](style)

---

###  Try Logic (`docs/_try/logic.md`)

---
layout: try
slug: logic
title: Logic in templates
---

In this step, you'll add a loop and a conditional to your LitElement template. 

To repeat a part of your HTML template, you can use a JavaScript expression to iterate over an array property:

```js
${this.myArray.map(item => html`<li>${item}</li>`)}
```

Similarly, to conditionally render some part of your template, you can use a JavaScript expression to examine a boolean property:

```js
${this.myBool ? html`<p>something</p>` : html`<p>something else</p>`}
```

**Starting code**

_my-element.js_

```js
{% include projects/try/logic/before/my-element.js %}
```

{% include project.html folder="try/logic/before" openFile="my-element.js" %}

1.  **Add a boolean property and an array property to your properties getter.**

    Replace the static properties getter with the following code:

    ```js
    static get properties() {
      return {
        message: { type: String },
        myBool: { type: Boolean },
        myArray: { type: Array }
      };
    }
    ```

2.  **Initialize the boolean and array properties.**

    Replace the constructor with the following code:

    ```js
    constructor() {
      super();
      this.message = 'Hello world! From my-element';
      this.myBool = true;
      this.myArray = ['an','array','of','test','data'];
    }
    ```

3.  **Add a loop to your template.**
    
    To loop over the new `myArray` property, add the following code to your template:

    ```js
    <ul>${this.myArray.map(item => html`<li>${item}</li>`)}</ul>
    ```

3.  **Add a conditional to your template.**

    To render conditionally based on the value of `myBool`, add the following code to your template:

    ```js
    ${this.myBool ?
      html`<p>Render some HTML if myBool is true</p>` :
      html`<p>Render some other HTML if myBool is false</p>`}
    ```

Here's the completed code for this step:

_my-element.js_

```js
{% include projects/try/logic/after/my-element.js %}
```

[Next: 4. Events](events)

---

###  Try Properties (`docs/_try/properties.md`)

---
layout: try
slug: properties
title: Use properties
---

In this step, you'll declare a property for your component, initialize the property, and use the value in the component's template. 

**Starting code**

_my-element.js_

```js
{% include projects/try/properties/before/my-element.js %}
```

{% include project.html folder="try/properties/before" openFile="my-element.js" %}

1. **Declare a property.**

    In my-element.js, add the following `properties` getter to the `MyElement` class: 
    
    ```js
    static get properties() {
      return { message: { type: String } };
    }
    ```

    The code snippet above adds a string property called `message` to your element class.

2. **Initialize the property.**

    A good place to initialize property values is in your element constructor. 
        
    In my-element.js, add the following method to the `MyElement` class: 
    
    ```js
    constructor() {
      super();
      this.message = 'Hello world! From my-element';
    }
    ```

    The first line of code in the constructor (`super();`) calls the parent class constructor.

3. **Add the property to your template.**

    You can add properties to your LitElement templates with JavaScript expressions.

    In my-element.js, replace the existing `render` function with the following code:

    ```js
    render() {
      return html`
        <p>${this.message}</p>
      `;
    }
    ``` 

LitElement components update automatically when their properties change. 

Here's the completed code for this step:

_my-element.js_

```js
{% include projects/try/properties/after/my-element.js %}
```

[Next: 3. Logic](logic)

---

###  Try Style (`docs/_try/style.md`)

---
layout: try
slug: style
title: Styling
---

Style your component with CSS by defining a static `styles` getter in your class.

**Starting code**

_my-element.js_

```js
{% include projects/try/style/before/my-element.js %}
```

{% include project.html folder="try/style/before" openFile="my-element.js" %}

1.  **Import the `css` helper function.**

    In my-element.js, replace the `import` statement with the following code:

    ```js
    import { LitElement, html, css } from 'lit-element';
    ```

2.  **Define your styles.**

    To define your styles, add a static `styles` getter to your class:

    ```js
    static get styles() {
      return css`
        p {
          font-family: Roboto;
          font-size: 16px;
          font-weight: 500;
        }
        .red {
          color: red;
        }
        .blue {
          color: blue;
        }
      `;
    }
    ```

3. **Apply your styles.**

    Use `myBool` to apply the styles conditionally. Add the following paragraph to your template:

    ```html
    <p class="${this.myBool ? 'red' : 'blue' }">styled paragraph</p>
    ```

Here's the completed code for this step:

_my-element.js_

```js
{% include projects/try/style/after/my-element.js %}
```

Congratulations - you've made your first element with LitElement. Next, see the [Getting&nbsp;Started](/guide/start) guide and set up LitElement locally.

---

###  Includes Projects Index Typescript Manifest.Json (`docs/_includes/projects/index-typescript/manifest.json`)

{
  "files": [
    "simple-greeting.ts",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Index Manifest.Json (`docs/_includes/projects/index/manifest.json`)

{
  "files": [
    "simple-greeting.js",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Docs Create Manifest.Json (`docs/_includes/projects/docs/create/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Docs Renderroot Manifest.Json (`docs/_includes/projects/docs/renderroot/manifest.json`)

{
  "files": [
    "default-root.js",
    "light-dom.js",
    "index.html",
    "index.ts"
  ],
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Docs Typescript Manifest.Json (`docs/_includes/projects/docs/typescript/manifest.json`)

{
  "files": [
    "my-element.ts",
    "index.html",
    "index.ts"
  ],
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Events Child Manifest.Json (`docs/_includes/projects/events/child/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "@polymer/lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Events Childimperative Manifest.Json (`docs/_includes/projects/events/childimperative/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "@polymer/lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Events Events Manifest.Json (`docs/_includes/projects/events/events/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "@polymer/lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Events Host Manifest.Json (`docs/_includes/projects/events/host/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "@polymer/lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Lifecycle Customize Manifest.Json (`docs/_includes/projects/lifecycle/customize/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Lifecycle Firstupdated Manifest.Json (`docs/_includes/projects/lifecycle/firstupdated/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Lifecycle Haschanged Manifest.Json (`docs/_includes/projects/lifecycle/haschanged/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Lifecycle Microtasks Manifest.Json (`docs/_includes/projects/lifecycle/microtasks/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Lifecycle Performupdate Manifest.Json (`docs/_includes/projects/lifecycle/performupdate/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Lifecycle Requestupdate Manifest.Json (`docs/_includes/projects/lifecycle/requestupdate/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Lifecycle Shouldupdate Manifest.Json (`docs/_includes/projects/lifecycle/shouldupdate/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Lifecycle Subproperties Manifest.Json (`docs/_includes/projects/lifecycle/subproperties/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Lifecycle Update Manifest.Json (`docs/_includes/projects/lifecycle/update/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Lifecycle Updatecomplete Manifest.Json (`docs/_includes/projects/lifecycle/updatecomplete/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Lifecycle Updated Manifest.Json (`docs/_includes/projects/lifecycle/updated/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Accessorssubclassing Manifest.Json (`docs/_includes/projects/properties/accessorssubclassing/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "super-element.js",
    "sub-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Attributeconverter Manifest.Json (`docs/_includes/projects/properties/attributeconverter/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Attributeobserve Manifest.Json (`docs/_includes/projects/properties/attributeobserve/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Attributereflect Manifest.Json (`docs/_includes/projects/properties/attributereflect/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Customsetter Manifest.Json (`docs/_includes/projects/properties/customsetter/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Declare Manifest.Json (`docs/_includes/projects/properties/declare/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Declaretypescript Manifest.Json (`docs/_includes/projects/properties/declaretypescript/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.ts",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Defaultconverter Manifest.Json (`docs/_includes/projects/properties/defaultconverter/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Haschanged Manifest.Json (`docs/_includes/projects/properties/haschanged/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Init Manifest.Json (`docs/_includes/projects/properties/init/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Initmarkup Manifest.Json (`docs/_includes/projects/properties/initmarkup/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Properties Inittypescript Manifest.Json (`docs/_includes/projects/properties/inittypescript/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.ts",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Style Classmap Manifest.Json (`docs/_includes/projects/style/classmap/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest",
    "lit-html": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Customproperties Manifest.Json (`docs/_includes/projects/style/customproperties/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Host Manifest.Json (`docs/_includes/projects/style/host/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Inherited Manifest.Json (`docs/_includes/projects/style/inherited/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Inherited2 Manifest.Json (`docs/_includes/projects/style/inherited2/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Inherited3 Manifest.Json (`docs/_includes/projects/style/inherited3/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Introbutton Manifest.Json (`docs/_includes/projects/style/introbutton/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Introcustomprops Manifest.Json (`docs/_includes/projects/style/introcustomprops/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Intromargin Manifest.Json (`docs/_includes/projects/style/intromargin/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Maps Manifest.Json (`docs/_includes/projects/style/maps/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest",
    "lit-html": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Mapsextended Manifest.Json (`docs/_includes/projects/style/mapsextended/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-button.js",
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest",
    "lit-html": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Nestedcss Manifest.Json (`docs/_includes/projects/style/nestedcss/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Perinstanceexpressions Manifest.Json (`docs/_includes/projects/style/perinstanceexpressions/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Slottedbase Manifest.Json (`docs/_includes/projects/style/slottedbase/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Slottedselector Manifest.Json (`docs/_includes/projects/style/slottedselector/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Specificity Manifest.Json (`docs/_includes/projects/style/specificity/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Styleatemplate Manifest.Json (`docs/_includes/projects/style/styleatemplate/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Stylecustomtag Manifest.Json (`docs/_includes/projects/style/stylecustomtag/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Stylemap Manifest.Json (`docs/_includes/projects/style/stylemap/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-button.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest",
    "lit-html": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Stylemap2 Manifest.Json (`docs/_includes/projects/style/stylemap2/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "index.html",
    "div-3.js"
  ],
  "dependencies": {
    "lit-html": "latest",
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Superstyles Manifest.Json (`docs/_includes/projects/style/superstyles/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "super-element.js",
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Theming Manifest.Json (`docs/_includes/projects/style/theming/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Unsafecss Manifest.Json (`docs/_includes/projects/style/unsafecss/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Unsafecss1 Manifest.Json (`docs/_includes/projects/style/unsafecss1/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Style Where Manifest.Json (`docs/_includes/projects/style/where/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "app-styles.css",
    "index.html"
  ],
  "dependencies": {
    "lit-element": "latest"
  },
  "template": "polymer"
}

---

###  Includes Projects Docs Templates Compose Manifest.Json (`docs/_includes/projects/docs/templates/compose/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-page.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Docs Templates Composeimports Manifest.Json (`docs/_includes/projects/docs/templates/composeimports/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-page.js",
    "my-header.js",
    "my-article.js",
    "my-footer.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Docs Templates Databinding Manifest.Json (`docs/_includes/projects/docs/templates/databinding/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Docs Templates Define Manifest.Json (`docs/_includes/projects/docs/templates/define/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Docs Templates Design Manifest.Json (`docs/_includes/projects/docs/templates/design/manifest.json`)

{
  "files": [
    "dom-manip.js",
    "update-properties.js",
    "index.html",
    "index.ts"
  ],
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Docs Templates Expressions Manifest.Json (`docs/_includes/projects/docs/templates/expressions/manifest.json`)

{
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  },
  "template": "typescript"
}

---

###  Includes Projects Docs Templates Namedslots Manifest.Json (`docs/_includes/projects/docs/templates/namedslots/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Docs Templates Renderroot Manifest.Json (`docs/_includes/projects/docs/templates/renderroot/manifest.json`)

{
  "files": [
    "default-root.js",
    "light-dom.js",
    "index.html",
    "index.ts"
  ],
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Docs Templates Slotid Manifest.Json (`docs/_includes/projects/docs/templates/slotid/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Docs Templates Slots Manifest.Json (`docs/_includes/projects/docs/templates/slots/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "lit-element code sample",
  "description": "lit-element code sample",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Try Create After Manifest.Json (`docs/_includes/projects/try/create/after/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Try Create Before Manifest.Json (`docs/_includes/projects/try/create/before/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Try Events After Manifest.Json (`docs/_includes/projects/try/events/after/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Try Events Before Manifest.Json (`docs/_includes/projects/try/events/before/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Try Logic After Manifest.Json (`docs/_includes/projects/try/logic/after/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Try Logic Before Manifest.Json (`docs/_includes/projects/try/logic/before/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Try Properties After Manifest.Json (`docs/_includes/projects/try/properties/after/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Try Properties Before Manifest.Json (`docs/_includes/projects/try/properties/before/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Try Style After Manifest.Json (`docs/_includes/projects/try/style/after/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

###  Includes Projects Try Style Before Manifest.Json (`docs/_includes/projects/try/style/before/manifest.json`)

{
  "files": [
    "my-element.js",
    "index.html",
    "index.ts"
  ],
  "title": "LitElement Example",
  "description": "LitElement Example",
  "template": "typescript",
  "dependencies": {
    "lit-element": "latest",
    "@webcomponents/webcomponentsjs": "latest"
  }
}

---

--- METRICS ---
- Files Extracted: 105
- Estimated Token Budget: ~48170 tokens
- Canonical Reference: https://codewiki.google/github.com/lit/lit-element
