Cumulative Layout Shift (CLS) measures visual stability during page load. This guide provides Carrd-specific solutions to eliminate layout shifts and maintain a stable, professional user experience.
General Guide: See Global CLS Issues for universal concepts and fixes.
What is CLS?
Cumulative Layout Shift (CLS) is one of Google's Core Web Vitals that measures visual stability. It quantifies how much unexpected layout shift occurs during the page load process.
CLS Thresholds
- Good: ≤ 0.1
- Needs Improvement: 0.1 - 0.25
- Poor: > 0.25
Carrd Baseline Performance
Out of the box, Carrd sites typically achieve:
- CLS: 0.0 - 0.05 (excellent)
- Visual Stability: Very stable layouts
- Minimal shifts: Clean, predictable rendering
If your Carrd site has CLS > 0.1, optimization is needed.
Common CLS Causes on Carrd
Layout shifts on Carrd sites typically come from:
- Images without dimensions: Browser doesn't know size until loaded
- Web fonts loading: Text reflows when fonts load
- Embed elements: Third-party widgets shifting layout
- Dynamic content: JavaScript-injected content
- Ads or widgets: Marketing embeds without reserved space
- Custom CSS: Transitions or animations causing shifts
Diagnosing CLS Issues on Carrd
Step 1: Identify Layout Shifts
Use Google PageSpeed Insights:
- Go to PageSpeed Insights
- Enter your published Carrd site URL
- Click Analyze
- Review CLS score
- Check Avoid large layout shifts in diagnostics
- See which elements are shifting
Step 2: Visual Inspection
Use Chrome DevTools:
- Open your published Carrd site
- Press F12 > Lighthouse
- Check Performance
- Click Generate Report
- Scroll to Diagnostics
- Look for layout shift screenshots
Step 3: Experience Builder
Use Chrome's Layout Shift Regions:
- Press F12 > Console
- Paste this code:
let cls = 0;
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
cls += entry.value;
console.log('Layout Shift:', entry.value, 'Total CLS:', cls);
console.log('Shifted elements:', entry.sources);
}
}
}).observe({type: 'layout-shift', buffered: true});
- Reload page
- See exactly which elements shift and when
Carrd-Specific CLS Optimizations
1. Fix Image Dimensions
Images without explicit dimensions cause layout shifts when they load.
Set Image Dimensions in Carrd
For image elements:
- Select the image in Carrd editor
- In image settings, note the display dimensions
- Add an embed element near the image
- Add explicit dimensions via CSS:
<style>
/* Replace .image-id with your image's ID or class */
.image-element {
width: 800px;
height: 600px;
}
/* Or use aspect ratio (modern browsers) */
.image-element {
aspect-ratio: 4 / 3;
width: 100%;
}
</style>
Aspect Ratio Technique (Recommended)
Best practice for responsive images:
<style>
/* For all images */
img {
max-width: 100%;
height: auto;
}
/* Specific aspect ratio containers */
.hero-image-container {
position: relative;
width: 100%;
aspect-ratio: 16 / 9; /* Adjust to your image ratio */
}
.hero-image-container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
Add this in a Style embed at the top of your page.
Background Images
For section background images:
<style>
/* Reserve space for sections with background images */
#section-hero {
min-height: 600px; /* Set explicit min-height */
}
@media (max-width: 768px) {
#section-hero {
min-height: 400px; /* Smaller on mobile */
}
}
</style>
In Carrd: Find your section ID by inspecting it in browser DevTools.
2. Optimize Web Font Loading
Web fonts cause layout shifts when text reflows after font loads.
Font Display Swap
If using custom fonts, ensure font-display: swap is set:
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
Note the display=swap parameter.
Preload Critical Fonts
For fonts used above the fold:
<link rel="preload" as="font" type="font/woff2" href="https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hiA.woff2" crossorigin>
Add in embed element at top of page.
Font Loading Strategy
Prevent font-based layout shifts:
<style>
/* Ensure fallback font matches custom font dimensions */
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
/* Use similar fallback font to minimize reflow */
}
</style>
System Fonts Alternative
For zero CLS from fonts:
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
/* System fonts = no loading = no shift */
}
</style>
3. Reserve Space for Embeds
Third-party embeds (widgets, social feeds, etc.) often cause layout shifts.
Fixed Height Containers
Wrap embeds in containers with fixed heights:
<div style="min-height: 400px;">
<!-- Your embed code here -->
<script src="https://widget.example.com/embed.js"></script>
</div>
Common Embed Heights
Reserve appropriate space for popular embeds:
- Instagram feed: 500-600px
- Twitter embed: 400-500px
- YouTube video: Use 16:9 aspect ratio
- Calendly: 700px
- Gumroad embed: 300-400px
- Chat widget: Usually fixed position, no space needed
YouTube/Video Embed Wrapper
Prevent shift with aspect ratio wrapper:
<style>
.video-container {
position: relative;
width: 100%;
padding-bottom: 56.25%; /* 16:9 aspect ratio */
height: 0;
overflow: hidden;
}
.video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
<div class="video-container">
<iframe src="https://www.youtube.com/embed/VIDEO_ID" frameborder="0" allowfullscreen></iframe>
</div>
4. Avoid Layout-Shifting Animations
Certain CSS properties cause layout shifts when animated.
Safe CSS Properties
These DON'T cause layout shifts:
transformopacityfilter
These DO cause layout shifts (avoid animating):
width,heightmargin,paddingtop,left,right,bottom(on static elements)font-size
Use Transform Instead
Bad (causes CLS):
.element {
transition: margin-top 0.3s;
}
.element:hover {
margin-top: -10px;
}
Good (no CLS):
.element {
transition: transform 0.3s;
}
.element:hover {
transform: translateY(-10px);
}
5. Dynamic Content Handling
JavaScript-injected content can shift layout.
Reserve Space for Dynamic Content
If loading content via JavaScript:
<div id="dynamic-content" style="min-height: 200px;">
<!-- Content will load here -->
</div>
<script>
// Load content
fetch('/api/content')
.then(response => response.json())
.then(data => {
document.getElementById('dynamic-content').innerHTML = data.html;
});
</script>
The min-height prevents shift when content loads.
Skeleton Screens
Show placeholder while loading:
<style>
.skeleton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: loading 1.5s infinite;
border-radius: 4px;
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
</style>
<div id="content-area">
<!-- Show skeleton while loading -->
<div class="skeleton" style="width: 100%; height: 100px; margin-bottom: 10px;"></div>
<div class="skeleton" style="width: 80%; height: 20px;"></div>
</div>
<script>
// Replace skeleton with actual content after load
window.addEventListener('load', function() {
document.getElementById('content-area').innerHTML = actualContent;
});
</script>
6. Carrd Form Elements
Forms can cause CLS if not handled properly.
Set Form Heights
<style>
/* Prevent form from shifting layout */
form {
min-height: 400px; /* Adjust based on your form */
}
/* Or specific form */
#form-contact {
min-height: 500px;
}
</style>
Form Success/Error States
When showing success/error messages:
<style>
/* Reserve space for form messages */
.form-message {
min-height: 50px;
transition: opacity 0.3s;
}
.form-message:empty {
opacity: 0;
}
</style>
7. Sticky/Fixed Elements
Fixed positioning can cause CLS if not done correctly.
Carrd Navigation/Header
If you have a sticky header:
<style>
/* Reserve space for sticky header */
body {
padding-top: 80px; /* Height of your header */
}
#header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 80px;
z-index: 1000;
}
</style>
Chat Widgets
Chat widgets are usually fixed position, but ensure they don't cause shifts:
<style>
/* Chat widget should use fixed positioning */
#chat-widget {
position: fixed;
bottom: 20px;
right: 20px;
width: 60px;
height: 60px;
/* Does not affect layout flow */
}
</style>
Mobile-Specific CLS Issues
Mobile devices often have worse CLS scores.
Mobile Image Optimization
<style>
@media (max-width: 768px) {
/* Ensure mobile images have explicit dimensions */
.hero-image {
width: 100%;
aspect-ratio: 1 / 1; /* Square on mobile */
}
}
</style>
Mobile Font Sizing
<style>
@media (max-width: 768px) {
/* Prevent font size shifts on mobile */
body {
font-size: 16px; /* Explicit size */
-webkit-text-size-adjust: 100%; /* Prevent iOS auto-sizing */
}
}
</style>
Mobile Embed Handling
<style>
@media (max-width: 768px) {
/* Mobile-specific embed containers */
.embed-container {
min-height: 300px; /* Smaller reserved space on mobile */
}
}
</style>
Advanced Optimizations
Content Visibility API
For below-fold content, use content-visibility:
<style>
/* Skip rendering off-screen content */
.below-fold-section {
content-visibility: auto;
contain-intrinsic-size: 0 500px; /* Estimated height */
}
</style>
This tells the browser the estimated size before rendering.
Intersection Observer for Lazy Loading
Control when elements load:
<script>
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Load content when visible
const embed = entry.target;
embed.style.minHeight = '0'; // Remove reserved space
// Load actual content here
}
});
});
// Observe elements
document.querySelectorAll('.lazy-embed').forEach(el => observer.observe(el));
</script>
Testing Your CLS Improvements
Before and After Comparison
- Baseline: Test current CLS with PageSpeed Insights
- Note score: Record current CLS value
- Implement fixes: Apply optimizations from this guide
- Publish: Publish your Carrd site
- Clear cache: Hard reload (Ctrl+Shift+R)
- Retest: Run PageSpeed Insights again
- Compare: Verify CLS improvement
Testing Tools
- Google PageSpeed Insights: Official CLS scores
- Chrome DevTools Lighthouse: Local testing (F12 > Lighthouse)
- Web Vitals Extension: Real-time CLS monitoring
- WebPageTest: Video playback showing shifts
Visual Regression Testing
Use Chrome DevTools to see shifts:
- F12 > More tools > Rendering
- Check Layout Shift Regions
- Reload page
- Blue rectangles show where shifts occur
Common Carrd CLS Issues and Fixes
Issue: Images Shifting on Load
Symptom: CLS 0.15-0.25, images identified in diagnostics
Fix:
<style>
/* Add aspect ratio to all images */
img {
max-width: 100%;
height: auto;
}
/* Specific image containers with known ratio */
.image-container {
aspect-ratio: 16 / 9;
width: 100%;
}
</style>
Expected improvement: CLS reduced to < 0.05
Issue: Font Loading Reflow
Symptom: CLS 0.08-0.12, text shifts when font loads
Fix:
<!-- Add font-display: swap to font URL -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<!-- Or preload fonts -->
<link rel="preload" as="font" href="FONT_URL.woff2" crossorigin>
Expected improvement: CLS reduced by 0.03-0.06
Issue: Embed Widget Shifting
Symptom: CLS 0.20+, third-party widget loads and pushes content
Fix:
<div style="min-height: 400px;">
<!-- Widget code here -->
</div>
Expected improvement: CLS reduced to < 0.08
Issue: Mobile Layout Shifts
Symptom: Good CLS on desktop (0.05), poor on mobile (0.18)
Fix:
<style>
@media (max-width: 768px) {
/* Set explicit heights for mobile */
.hero-section {
min-height: 400px;
}
/* Fixed mobile image dimensions */
.mobile-image {
aspect-ratio: 4 / 3;
width: 100%;
}
}
</style>
Expected improvement: Mobile CLS reduced to < 0.08
Issue: Form Success Message Shifts
Symptom: CLS spike when form success message appears
Fix:
<style>
/* Reserve space for form message */
.form-container {
min-height: 500px; /* Include space for message */
}
.form-message {
min-height: 60px;
opacity: 0;
transition: opacity 0.3s;
}
.form-message.visible {
opacity: 1;
}
</style>
Expected improvement: Eliminates post-submit CLS
Monitoring CLS Over Time
Google Search Console
Track real-world CLS:
- Go to Google Search Console
- Navigate to Experience > Core Web Vitals
- Review CLS performance
- Identify pages with poor CLS
- Prioritize fixes for high-traffic pages
Real User Monitoring
Track CLS with GA4:
<script>
let cls = 0;
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
cls += entry.value;
}
}
}).observe({type: 'layout-shift', buffered: true});
// Send to GA4 on page unload
window.addEventListener('beforeunload', function() {
if (typeof gtag !== 'undefined') {
gtag('event', 'CLS', {
'value': Math.round(cls * 1000), // Convert to integer
'event_category': 'Web Vitals',
'transport_type': 'beacon'
});
}
});
</script>
Monthly CLS Audits
Establish routine checks:
- Monthly: Test key pages with PageSpeed Insights
- Review: CLS still in "good" range (< 0.1)
- Check: Any new embeds or images added?
- Fix: If CLS degraded, identify and fix cause
- Track: Document changes and improvements
Carrd CLS Best Practices
Design Phase
- Plan image dimensions: Know sizes before upload
- Limit embeds: Only essential third-party widgets
- Use system fonts: When possible, avoid custom fonts
- Fixed layouts: Predictable, stable layouts
Development Phase
- Set explicit dimensions: All images and embeds
- Reserve space: min-height for dynamic content
- Test early: Check CLS before launch
- Mobile first: Test mobile CLS during development
Maintenance Phase
- Audit new embeds: Check CLS impact before adding
- Monitor regularly: Monthly PageSpeed checks
- Quick fixes: Address CLS issues immediately
- Documentation: Note optimal embed heights for reuse
Next Steps
- Optimize LCP for faster loading
- Fix Tracking Issues if analytics aren't working
- Troubleshooting Overview for other common issues