Ready-made reactive controllers for common browser APIs — ResizeObserver, MutationObserver, IntersectionObserver, PerformanceObserver — plus task management and context.
Lit provides several packages that ship reactive controllers wrapping common browser and application APIs. Install only what you need.
IntersectionController wraps the IntersectionObserver API to notify the host when a target element enters or exits the viewport (or another scroll container).Import
import { IntersectionController } from '@lit-labs/observers/intersection-controller.js';
Constructor
new IntersectionController<T>(host: ReactiveControllerHost & Element, config: IntersectionControllerConfig<T>)
Config options
Option
Type
Description
config
IntersectionObserverInit
Options passed directly to the IntersectionObserver constructor (e.g. { threshold: 0.5 }).
target
Element | null
Element to observe. Defaults to the host element. Pass null to observe nothing automatically.
callback
(entries: IntersectionObserverEntry[], observer: IntersectionObserver) => T
Processes entries into controller.value.
skipInitial
boolean
When true, ignores the initial intersection state reported when observation starts. Defaults to false.
Instance members
Member
Type
Description
value
T | undefined
The last value returned by callback.
callback
IntersectionValueCallback<T> | undefined
The callback function (can be reassigned).
observe(target)
void
Start observing an additional element.
unobserve(target)
void
Stop observing an element.
ExampleShow different content based on whether the element is visible in the viewport:
Unlike ResizeController and MutationController, IntersectionObserver always fires its callback immediately when observe() is called to report the initial intersection state. Use skipInitial: true to suppress this if the initial state is not needed.
IntersectionController logs a warning and exits early in environments where IntersectionObserver is not available, including server-side rendering.
PerformanceController wraps the PerformanceObserver API to collect performance timeline entries (marks, measures, resource timings, etc.) and make them available in the reactive update cycle.Import
import { PerformanceController } from '@lit-labs/observers/performance-controller.js';
Constructor
new PerformanceController<T>(host: ReactiveControllerHost, config: PerformanceControllerConfig<T>)
Unlike the other observer controllers, PerformanceController accepts a plain ReactiveControllerHost — it does not require the host to also be an Element, since PerformanceObserver is not tied to a specific DOM element.
Config options
Option
Type
Description
config
PerformanceObserverInit
Required. Options passed to PerformanceObserver.observe() (e.g. { entryTypes: ['measure'] }).
callback
(entries: PerformanceEntryList, observer: PerformanceObserver, entryList?: PerformanceObserverEntryList) => T
Processes performance entries into controller.value.
skipInitial
boolean
When true, skips calling callback with an empty entry list on first observe. Defaults to false.
Instance members
Member
Type
Description
value
T | undefined
The last value returned by callback.
callback
PerformanceValueCallback<T> | undefined
The callback function (can be reassigned).
observe()
void
Start observing. Called automatically on hostConnected.
flush()
void
Immediately process any buffered entries and request a host update.
ExampleCollect measure entries and display the most recent one:
import { LitElement, html } from 'lit';import { customElement } from 'lit/decorators.js';import { PerformanceController } from '@lit-labs/observers/performance-controller.js';@customElement('perf-monitor')class PerfMonitor extends LitElement { private _perf = new PerformanceController(this, { config: { entryTypes: ['measure'] }, callback: (entries) => entries.at(-1), }); render() { const latest = this._perf.value; return html` <p> Last measure: ${latest ? `${latest.name} — ${latest.duration.toFixed(1)}ms` : 'none'} </p> `; }}
PerformanceController logs a warning and exits early in environments where PerformanceObserver is not available, including server-side rendering.
@lit/task — The Task controller manages async operations with built-in pending, complete, and error states. Use it for data fetching, debounced computations, and any work that should re-run when reactive properties change.
ContextConsumer and ContextProvider
@lit/context — ContextConsumer and ContextProvider implement the W3C community Context Protocol, enabling components to share data across the element tree without prop drilling.