Optimizing Core Web Vitals for 1C-Bitrix
Core Web Vitals are three Google metrics: LCP (main content load speed), CLS (layout stability), FID/INP (responsiveness to input). Since 2021, they're part of search ranking. Bitrix sites typically show: LCP 4–8 seconds instead of threshold 2.5 s, CLS 0.2–0.5 instead of 0.1, FID/INP above 200 ms.
Diagnostics
Start with Chrome DevTools → Lighthouse → Performance. It's synthetic but shows bottlenecks well. PageSpeed Insights (pagespeed.web.dev) provides real user data from CrUX (Chrome User Experience Report) — more important than synthetic for actual search impact.
For Bitrix sites, main problem sources:
- LCP: slow TTFB + large images in hero banner
- CLS: images without
width/height, fonts withoutfont-display, dynamic blocks (cart, banners) - FID/INP: heavy JavaScript, blocking scripts in
<head>
LCP: Critical Rendering Path
LCP element in Bitrix store is usually hero banner (slider) or first image in catalog. Problem: image loads via JS after page render.
Solution — preload for LCP image:
<link rel="preload" as="image" href="/upload/banners/main.webp"
imagesizes="100vw" fetchpriority="high">
Add to <head> of template. In Bitrix — in header.php of main template or via AddHeadString() in component.
Sliders are LCP's main enemy. Libraries like Swiper.js load JS (100–300 KB), delaying first slide show. Optimization: render first slide in static HTML, defer JS initialization via defer or requestIdleCallback.
CLS: Layout Shifts
CLS is nonzero in Bitrix because of:
Images without sizes. Standard Bitrix components often output <img src="..." alt="..."> without width and height. Browser doesn't know size until loading, redraws layout. Solution — add sizes to component template:
// In template.php of catalog.element component
$width = $arItem['PREVIEW_PICTURE']['WIDTH'] ?? 300;
$height = $arItem['PREVIEW_PICTURE']['HEIGHT'] ?? 300;
echo '<img src="' . $arItem['PREVIEW_PICTURE']['SRC'] . '" '
. 'width="' . $width . '" height="' . $height . '" '
. 'loading="lazy" decoding="async" alt="' . htmlspecialchars($arItem['NAME']) . '">';
Cart and counters. Block "In cart: N items" or cart icon in header loads AJAX after render and shifts content. Reserve space via CSS: min-width, min-height for blocks with dynamic data.
Google Fonts and third-party fonts. Without font-display: swap, browser hides text until font loads (FOIT), then redraws. Add to CSS:
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap;
}
JavaScript: Rendering Block and INP
Typical Bitrix problem: in template <head>, 10–20 JS files are loaded via CJSCore::Init(). Browser stops parsing HTML on each synchronous <script>.
Switch to defer:
<!-- Was (blocks rendering): -->
<script src="/bitrix/js/main/core.js"></script>
<!-- Now: -->
<script src="/bitrix/js/main/core.js" defer></script>
In Bitrix, manage scripts via \Bitrix\Main\Page\Asset. Toggle JS output to footer via Settings → Main Module → Performance → Move scripts to page end.
INP (Interaction to Next Paint) replaces FID since March 2024. Measures delay on all interactions, not just first. Main culprits: heavy event handlers, synchronous operations in click handlers. Diagnose via DevTools → Performance → INP.
Images: WebP and Lazy Loading
Bitrix can convert images to WebP via resize_image module. Setting in /bitrix/.settings.php:
'resize_image' => [
'value' => [
'webp' => true,
'webp_quality' => 80,
],
],
After enabling, CFile::ResizeImageGet() returns WebP version for supporting browsers. For old browsers — automatic fallback to JPEG/PNG.
Lazy loading for images outside viewport:
<img src="..." loading="lazy" decoding="async" width="300" height="200">
LCP image shouldn't be loading="lazy" — delays its loading. Other images — can and should be.
CSS: Critical Path
Bitrix loads CSS via \Bitrix\Main\Page\Asset::addCss(). All CSS outputs in <head>, blocking render. For faster first paint:
- Extract critical CSS (styles for visible viewport) and inline in
<style>in<head> - Load remaining CSS asynchronously:
<link rel="preload" as="style" onload="this.rel='stylesheet'">
Tools for critical CSS: critical (npm), PurgeCSS for removing unused styles.
Optimization Timeline
| Task | Time | Impact |
|---|---|---|
| Diagnostics: PageSpeed + DevTools analysis | 1 day | — |
| Preload LCP image, lazy load others | 1–2 days | LCP −1–2 s |
| Add width/height to images | 1–3 days | CLS → 0 |
| Move JS to defer/footer | 1–2 days | FID/INP −50–200 ms |
| WebP conversion + image optimization | 1–2 days | LCP −0.5–1.5 s |
| Critical CSS | 2–3 days | LCP −0.5–1 s |
| TTFB optimization (SQL, cache) | 3–10 days | LCP −1–4 s |
Full Core Web Vitals optimization for Bitrix store from scratch — 3–5 weeks. First results visible within a week.







