Как я сократил вес CSS-бандла в 3.5 раза: рефакторинг, Bootstrap и единая система карточек
Когда мы говорим о скорости загрузки страниц сайта, мы сразу думаем о статике, которая тормозит весь процесс! Даже если у вас на странице нет изображений, загрузка все равно может происходить медленно из-за CSS и JS файлов. Даже если вы постарались минимизировать количество статических файлов, этого может быть недостаточно.
Часто один из самых «тяжёлых» элементов на странице — это CSS. В моём случае основной сгенерированный CSS-файл весил 986 КБ — это довольно много, особенно, если учесть, что основная задача сайта — как можно быстрее предоставить пользователю контент.
В этой статье я расскажу, как мне удалось сократить объем CSS до 284 КБ — практически уменьшить в три с половиной раза. Без потери функциональности. Более того — с улучшением читаемости и управляемости кода.
🚨 Проблема: дублирование, фрагментарность и кастомные велосипеды
Первоначально проект имел:
- собственную кастомную сетку;
- десятки вариаций отступов с уникальными классами;
- 12 различных версий карточек публикаций;
- бессистемную организацию медиа-запросов;
- отсутствие Mobile First-подхода;
- вложенные классы.
Каждый компонент разрабатывался «в моменте», что привело к множеству схожих, но не унифицированных решений. Например:
.card-news,.card-event,.article-card— все были карточками, но с разной версткой;.margin-bottom-10,.mb-15px,.block-space— все обозначали отступы, но не системно;- сетка использовалась своя, а потом ещё одна, слегка изменённая.
.hh-cols__item--right .card-news— неочевидные зависимости, которые увеличивают вес селектора и которые трудно искать в коде.
Последствия:
- увеличение итогового CSS-файла;
- сложность поддержки;
- невозможность быстро переиспользовать стили;
- медленная загрузка на мобильных устройствах;
- из-за не корректно-написанных стилей могли происходить сдвиги при перерисовке страницы.
🔧 Решение: системный подход и Bootstrap как основа
1. Отказ от кастомной сетки в пользу Bootstrap Grid
Я перенёс структуру сетки на Bootstrap 5, ограничившись использованием только Grid-системы и миксинов отступов (без полной зависимости от всей библиотеки).
Почему это важно:
Bootstrap Grid давно оптимизирован и протестирован. Она основана на Mobile First-подходе и предлагает гибкую 12-колоночную структуру. Главное — не тащить всю библиотеку, а использовать только нужное.
Результат:
- взяты брейкпоинты Bootstrap и единая логика классов вида:
row,col-md-6; - исчезновение дубликатов сетки;
- упрощение шаблонов.
2. Унифицированная система отступов
Вместо десятков кастомных классов я оставил стандартизированные классы вида mb-{x}, px-{y}, в духе Bootstrap.
Для этого использовал генерацию через SCSS-циклы:
Плюсы:
- читаемость и предсказуемость;
- переиспользуемость;
- уменьшение объема итогового CSS.
3. Одна универсальная карточка вместо 12 шаблонов
Я выделил общие элементы всех карточек (заголовок, дата, изображение) и создал один компонент card-universal, где блоки могут включаться или выключаться через условия.
В шаблоне это может выглядеть так:
Что это дало:
- избавление от дублирующего CSS;
- один набор стилей для десятков карточек;
- упрощение логики и шаблонов;
- -100 КБ в финальном CSS только за счёт этого шага.
Как видно из примера выше, в шаблоне используются данные из массива, то есть к моменту вывода данные уже получены. Таким образом я отделяю логику от верстки. Зачем я отделяю логику от верстки можно узнать тут.
4. Композиция медиа-запросов через Webpack + SCSS
По умолчанию в генерируемом CSS остаются там же, где были написаны в препроцессоре(я использую SCSS). Из-за этого запросы не группируются, а следовательно создают лишний объем и нагрузку на браузер пользователя.
Я использовал плагин postcss-sort-media-queries в Webpack, который группирует запросы.
До:
После:
Плюс:
Код не повторяется 20 раз — все медиа-правила организованы в одном месте.
5. Mobile First — как философия
Переход на Mobile First дал два главных результата:
- уменьшение веса: базовые стили применяются всем, а расширения добавляются только для отдельных медиа-правил;
- улучшение UX на мобильных: сайт стал быстрее и адаптивнее.
📊 Результаты оптимизации
| Показатель | Было | Стало |
|---|---|---|
| Размер итогового CSS | 976 КБ | 284 КБ |
| Количество карточек | 12 | 1 |
| Кастомных отступов | >30 | 1 система |
| Подключение Bootstrap | ❌ | ✅ (только grid и spacing) |
| Медиа-инструкции | хаос | структурированы |
| Стиль адаптивности | mixed | Mobile First |
📚 Подтверждение практики
Согласно исследованию Google Web Fundamentals, задержки при загрузке стилей напрямую влияют на First Contentful Paint (FCP) и Time to Interactive (TTI) — ключевые метрики Core Web Vitals.
Сокращение CSS-файла даже на 100 КБ может ускорить загрузку на 300–500 мс, особенно в 3G-сетях.
💡 Выводы и советы
- Не бойтесь использовать части фреймворков, если они помогают решать ваши задачи.
- Не плодите зависимости без необходимости.
- Не изобретайте велосипед для стандартных вещей.
- Унификация компонентов — залог чистоты и скорости.
- Используйте Mobile First и собирайте медиа-запросы — это даёт реальные преимущества.
📈 Что дальше?
Работа по оптимизации еще не завершена, так как в ряде случаев еще остались не унифицированные карточки и отступы, хотя бóльшая часть уже переработана. Далее буду оптимизировать JS.
🤔 Зачем это нужно владельцу сайта?
Мы все боремся за внимание пользователей, в этой борьбе важна каждая мелочь. Если вы зарабатываете через сайт, быстрая загрузка страницы увеличит вероятность того, что пользователь оставит вам свои деньги!