Optimizing Core Web Vitals for 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    745
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

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 without font-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:

  1. Extract critical CSS (styles for visible viewport) and inline in <style> in <head>
  2. 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.