Skip to main content

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

NameTypeRequiredDescription
options.onMetric(metric: CLSMetric) => voidNoCallback fired whenever a matching layout shift changes the component CLS value.
options.includeDescendantsbooleanNoInclude layout shifts attributed to descendants. Defaults to true.
options.ignoreRecentInputbooleanNoIgnore shifts shortly after user input. Defaults to true.
options.maxEntriesnumberNoMaximum retained matching metrics. Defaults to 50.
options.enabledbooleanNoSet false to disable the observer.

Return value

FieldTypeDescription
ref(node: T | null) => voidAttach to the component root you want to inspect.
metricCLSMetric | nullLatest CLS metric for the observed element, scored by largest session window.
valuenumberCurrent largest CLS session-window value. Starts at 0.
ratingCLSRating | nullgood, needs-improvement, or poor.
entriesCLSMetric[]Matching layout-shift metrics retained for debugging.
isSupportedbooleanWhether 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>
);
}

Companion article