General Guide: See Global CLS Guide for universal concepts and fixes.
What is CLS?
Cumulative Layout Shift measures visual stability. Google recommends CLS under 0.1. SharePoint Online generates CLS from web parts loading and initializing at different times, images in document libraries without dimensions, SPFx dynamic import chunks rendering after the page frame, and the SharePoint app bar/header loading sequence.
SharePoint-Specific CLS Causes
- Web part lazy initialization -- SPFx web parts render placeholder spinners first, then swap in content at varying heights
- Image web part sizing -- images inserted via the Image web part or Hero web part may not have explicit dimensions in the HTML output
- Dynamic data web parts -- List, Document Library, and Highlighted Content web parts fetch data asynchronously and render after page load
- SharePoint app bar -- the left navigation app bar loads after the main content, pushing the page content right
- News/Events web parts -- these fetch content from multiple sources and render cards at variable heights
Fixes
1. Reserve Space in Custom SPFx Web Parts
// In your web part render method
public render(): void {
// Set a minimum height on the web part container immediately
this.domElement.style.minHeight = '300px';
this.domElement.style.contain = 'layout';
// Render loading skeleton first
this.domElement.innerHTML = `
<div class="skeleton" style="min-height: 300px;">
<div class="skeleton-line" style="height: 24px; width: 60%; background: #eee; margin-bottom: 12px;"></div>
<div class="skeleton-line" style="height: 16px; width: 90%; background: #eee; margin-bottom: 8px;"></div>
<div class="skeleton-line" style="height: 16px; width: 75%; background: #eee;"></div>
</div>
`;
// Then load real content
this._loadContent().then(content => {
this.domElement.innerHTML = content;
});
}
2. Fix Image Sizing
In SPFx web parts that render images:
// Always include width/height from the image metadata
const renderImage = (imageUrl: string, metadata: IImageMetadata) => {
return `
<div style="aspect-ratio: ${metadata.width}/${metadata.height}; overflow: hidden; background: #f3f3f3;">
<img
src="${imageUrl}"
width="${metadata.width}" height="${metadata.height}"
alt="${metadata.altText}"
style="width: 100%; height: 100%; object-fit: cover;"
loading="lazy"
/>
</div>
`;
};
For the built-in Image web part, use CSS in your site's theme:
/* Target SharePoint's image web part output */
.CanvasComponent img[data-sp-image] {
max-width: 100%;
height: auto;
}
/* Hero web part containment */
div[data-sp-feature-tag="Hero"] {
min-height: 400px;
contain: layout;
}
3. Constrain Built-In Web Part Containers
Add CSS via an SPFx Application Customizer or site theme:
/* Highlighted Content web part */
div[data-sp-feature-tag="ContentRollup"] {
min-height: 350px;
contain: layout;
}
/* News web part */
div[data-sp-feature-tag="NewsReel"] {
min-height: 400px;
contain: layout;
}
/* Events web part */
div[data-sp-feature-tag="Events"] {
min-height: 300px;
contain: layout;
}
/* Document Library web part */
div[data-sp-feature-tag="DocumentLibrary"] {
min-height: 250px;
contain: layout;
}
/* Quick Links */
div[data-sp-feature-tag="QuickLinks"] {
min-height: 120px;
contain: layout;
}
4. Handle App Bar CLS
/* Prevent app bar from shifting content */
.sp-appBar {
position: fixed;
left: 0;
top: 0;
height: 100vh;
z-index: 1000;
}
/* Reserve space for app bar when visible */
.mainContent {
margin-left: 48px; /* App bar collapsed width */
}
5. Preload Custom Fonts
In your SPFx Application Customizer:
// In onInit()
const preload = document.createElement('link');
preload.rel = 'preload';
preload.href = '/sites/yoursite/SiteAssets/fonts/brand.woff2';
preload.as = 'font';
preload.type = 'font/woff2';
preload.crossOrigin = 'anonymous';
document.head.appendChild(preload);
Measuring CLS on SharePoint
- SharePoint Page Diagnostics extension -- identifies slow-loading web parts that contribute to CLS
- Chrome DevTools Performance tab -- record and filter for layout-shift entries
- Test pages with many web parts -- pages with 5+ web parts in a single section have the highest CLS risk
- Mobile testing -- SharePoint responsive layout reflows differently on mobile and tablet viewports
Analytics Script Impact
- SharePoint's built-in usage analytics are server-side and cause no CLS
- Custom analytics via SPFx Application Customizers should not inject visible DOM elements
- Cookie consent implementations should use
position: fixedoverlays - Avoid Script Editor web parts for analytics -- they execute synchronously and can inject content that shifts layout