useCLS
Description and use case
useCLS tracks Cumulative Layout Shift for one DOM node. Attach the returned ref to a component root and the hook reports the largest CLS session window for layout-shift entries attributed to that element or its descendants.
This is useful when page-level CLS tells you that something moved, but you need to identify the component that jumped while dynamic content loaded.
API signature
function useCLS<T extends Element = HTMLElement>(options?: UseCLSOptions): UseCLSReturn<T>;
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
options.onMetric | (metric: CLSMetric) => void | No | Callback fired whenever a matching layout shift changes the component CLS value. |
options.includeDescendants | boolean | No | Include layout shifts attributed to descendants. Defaults to true. |
options.ignoreRecentInput | boolean | No | Ignore shifts shortly after user input. Defaults to true. |
options.maxEntries | number | No | Maximum retained matching metrics. Defaults to 50. |
options.enabled | boolean | No | Set false to disable the observer. |
Return value
| Field | Type | Description |
|---|---|---|
ref | (node: T | null) => void | Attach to the component root you want to inspect. |
metric | CLSMetric | null | Latest CLS metric for the observed element, scored by largest session window. |
value | number | Current largest CLS session-window value. Starts at 0. |
rating | CLSRating | null | good, needs-improvement, or poor. |
entries | CLSMetric[] | Matching layout-shift metrics retained for debugging. |
isSupported | boolean | Whether this browser supports Layout Instability entries. |
Live interactive demo (StackBlitz)
GitHub Pages does not serve the isolation headers required for embedded StackBlitz WebContainers. Open the demo in StackBlitz to run it interactively.
Code example
import { useCLS } from 'react-perf-hooks';
export function ProductCard() {
const { ref, value, rating, isSupported } = useCLS<HTMLDivElement>({
onMetric: (metric) => {
navigator.sendBeacon('/api/component-cls', JSON.stringify(metric));
},
});
return (
<article ref={ref}>
<strong>Component CLS</strong>
<span>{isSupported ? `${value.toFixed(3)} (${rating ?? 'waiting'})` : 'unavailable'}</span>
</article>
);
}