Image Optimization for 1C-Bitrix
Images are the largest contributor to page weight for most Bitrix projects. A typical situation: a manager uploads a product photo in high resolution directly from a camera (3–8 MB, 4000×3000 pixels), Bitrix saves the file to /upload/iblock/, and that exact file is served to mobile users. In 2024, this directly affects Core Web Vitals (LCP, CLS), Google search rankings, and conversion rates — slow image loading is directly linked to mobile bounce rates.
Bitrix Resize Mechanism
Bitrix provides CFile::ResizeImageGet() and \Bitrix\Main\UI\FileInput::processFiles() for on-the-fly image resizing. In component templates this looks like:
$resizedImage = CFile::ResizeImageGet(
$arItem['PREVIEW_PICTURE'],
['width' => 400, 'height' => 300],
BX_RESIZE_IMAGE_PROPORTIONAL,
false,
false
);
Results are cached in /upload/resize_cache/. The problem: by default the resize cache has no size limit. On a project with frequent image replacement, the /upload/resize_cache/ folder can grow to 20–50 GB over 2–3 years — with most files being stale.
Conversion to WebP
WebP delivers 25–40% smaller file sizes at equivalent quality for photographs, and 60–80% smaller for graphics with transparency compared to PNG. Modern browsers (Chrome 32+, Firefox 65+, Safari 14+) support WebP.
Ways to implement WebP for Bitrix:
1. At the nginx level via ngx_http_image_filter_module:
location ~* \.(jpg|jpeg|png)$ {
add_header Vary Accept;
if ($http_accept ~* "webp") {
rewrite ^(.*)\.(jpg|jpeg|png)$ $1.webp break;
}
}
This only works if .webp versions of files exist. Generation via a cron script using cwebp or imagemagick.
2. Via a PHP wrapper around CFile::ResizeImageGet():
function getImageSrc(int $fileId, int $width, int $height): string {
$webpSupported = str_contains($_SERVER['HTTP_ACCEPT'] ?? '', 'image/webp');
$format = $webpSupported ? 'webp' : 'jpg';
// Custom converter with result caching
return ImageConverter::resize($fileId, $width, $height, $format);
}
3. The <picture> tag with multiple sources:
<picture>
<source srcset="/upload/resize_cache/product_400x300.webp" type="image/webp">
<img src="/upload/resize_cache/product_400x300.jpg" width="400" height="300" loading="lazy" alt="...">
</picture>
This is the most universal approach — the browser selects the supported format automatically.
AVIF as the Next Step
AVIF (AV1 Image Format) yields a further 20–35% size reduction over WebP for photographs. Chrome supports it from version 85, Firefox from 86, Safari from 16. AVIF encoding is slower than WebP, so for large catalogs generation is performed in the background via a task queue.
Responsive Images (srcset)
Multiple image versions are needed for Retina displays and different screen sizes:
$sizes = [
['width' => 400, 'height' => 300], // mobile
['width' => 800, 'height' => 600], // tablet
['width' => 1200, 'height' => 900], // desktop
];
$srcset = [];
foreach ($sizes as $size) {
$img = CFile::ResizeImageGet($fileId, $size, BX_RESIZE_IMAGE_PROPORTIONAL);
$srcset[] = $img['src'] . ' ' . $size['width'] . 'w';
}
<img srcset="<?= implode(', ', $srcset) ?>"
sizes="(max-width: 768px) 400px, (max-width: 1024px) 800px, 1200px"
src="/upload/fallback.jpg" alt="...">
Case Study: Furniture Catalog, 8,000 SKUs
Before optimization: all images in JPEG, average size 480 KB, no srcset, no WebP. Catalog page (24 products) — 11.5 MB of images on desktop, 11.5 MB on mobile (the same files).
What was done:
- Batch conversion of all images in upload to WebP via
cwebp(cron script, processed overnight) - Resizing via
CFile::ResizeImageGet()in three sizes for srcset -
<picture>tag with WebP source + JPEG fallback img in thecatalog.sectiontemplate - Lazy load for images below the fold
- Configuration of scheduled cleanup for
/upload/resize_cache/entries older than 90 days
Result: average image weight in the catalog — 28 KB (WebP, appropriate size). Catalog page — 680 KB of images on mobile, 1.1 MB on desktop. LCP: 4.2 s → 1.6 s. PageSpeed Mobile: 31 → 74.
Work Stages
| Stage | Content | Duration |
|---|---|---|
| Audit | Analysis of current sizes, formats, and include methods | 0.5 day |
| WebP/AVIF conversion | Batch script + automated conversion on upload | 1–2 days |
Srcset and <picture> |
Component template updates | 2–4 days |
| Lazy load | Attributes and JS for custom scenarios | 0.5–1 day |
| resize_cache cleanup | Cleanup agent configuration | 0.5 day |
Total: 4 to 8 days depending on the number of custom templates and catalog size.







