Lit Web Components Cheat Sheet

Last Updated: November 21, 2025

Component Basics

class MyElement extends LitElement
Create Lit component class
@customElement('my-element')
Register custom element decorator
render() { return html`...` }
Define component template
html`<div>Hello</div>`
Create HTML template literal
css`selector { prop: value }`
Define scoped styles
static styles = css`...`
Add styles to component
static styles = [style1, style2]
Compose multiple style sheets

Property Decorators

@property({ type: String })
Declare reactive public property
@property({ type: Number })
Number property with type conversion
@property({ type: Boolean })
Boolean property (attribute presence)
@property({ type: Array })
Array property
@property({ type: Object })
Object property
@property({ attribute: false })
Property without HTML attribute
@property({ reflect: true })
Reflect property to attribute
@property({ converter: myConverter })
Custom attribute converter
@state()
Private reactive state (no attribute)
@property({ hasChanged: (n, o) => {} })
Custom change detection

Template Expressions

${expression}
Insert dynamic content
${condition ? html`yes` : html`no`}
Conditional rendering
${items.map(i => html`...`)}
Render list with map
?disabled=${!active}
Boolean attribute binding
.value=${data}
Property binding (not attribute)
@click=${this.handleClick}
Event listener binding
class=${classMap(classes)}
Dynamic class mapping
style=${styleMap(styles)}
Dynamic style mapping
${guard([dep], () => html`...`)}
Only re-render when deps change
${cache(condition ? html`A` : html`B`)}
Cache template instances

Directives

repeat(items, key, template)
Efficient list rendering with keys
when(condition, trueCase, falseCase)
Conditional with both branches
choose(value, cases, defaultCase)
Switch-like conditional
map(items, (item, i) => html`...`)
Map directive for lists
range(count)
Generate range of numbers
ifDefined(value)
Only set attribute if defined
live(value)
Check live DOM value (for inputs)
unsafeHTML(html)
Render raw HTML (use carefully)
unsafeSVG(svg)
Render raw SVG
until(promise, loading)
Render promise result with loading state

Lifecycle Methods

connectedCallback()
Called when element added to DOM
disconnectedCallback()
Called when element removed from DOM
firstUpdated(changedProps)
Called after first render
updated(changedProps)
Called after each update
willUpdate(changedProps)
Called before update/render
shouldUpdate(changedProps)
Control whether to update
attributeChangedCallback()
Called when attribute changes
requestUpdate()
Manually trigger update
performUpdate()
Override update lifecycle
updateComplete
Promise that resolves after update

Query Decorators

@query('#id')
Query single element in shadow DOM
@queryAll('.class')
Query all matching elements
@queryAsync('#id')
Async query (resolves after update)
@queryAssignedElements()
Query slotted elements
@queryAssignedNodes()
Query slotted nodes (including text)

Events

@event() myEvent!: EventEmitter
Declare custom event
this.dispatchEvent(new Event('my-event'))
Dispatch custom event
new CustomEvent('name', { detail })
Dispatch event with data
{ bubbles: true, composed: true }
Make event cross shadow boundary
@click=${this.handler}
Bind event in template
@click=${(e: Event) => {}}
Inline event handler

Reactive Controllers

class MyController implements ReactiveController
Create reactive controller
hostConnected()
Controller lifecycle hook
hostDisconnected()
Cleanup when host disconnects
hostUpdate()
Called before host updates
hostUpdated()
Called after host updates
this.host.requestUpdate()
Trigger host update from controller
this.addController(controller)
Register controller in component

Context API

createContext('key')
Create context identifier
@provide({ context: myContext })
Provide context value
@consume({ context: myContext })
Consume context value
@consume({ subscribe: true })
Subscribe to context changes

Best Practices

static shadowRootOptions = { mode: 'open' }
Configure shadow DOM options
@property({ type: String }) name = 'default'
Set default property values
await this.updateComplete
Wait for render to complete
nothing
Render nothing (from lit/html)
noChange
Keep previous value (directives)
static getMetaConfig() { return { ... } }
Define component metadata
💡 Pro Tip: Use @state() for private component state and @property() for public API. Leverage reactive controllers to extract and reuse complex logic across components!
← Back to Web Frameworks | Browse all categories | View all cheat sheets