Как сжимать CSS

07 Apr, 2005

Иногда на больших сайтах размер CSS файла вырастает до 20 килобайт и больше. Несмотря на то что он кэшируется, есть способ все же сжать сам файл. Этот пост практически перевод статьи "The Definitive Post on Gzipping your CSS" написанной Mike Papageorge.
Здесь я опишу методы сжатия CSS файла на 70-80% с помощью PHP. Вообще говоря это можно сделать и без PHP, лишь используя модули апача: mod_gzip или mod_deflate. То как это можно сделать описано тут. Если же доступа к конфигурации у вас нет (как часто бывает на хостингах), то можно воспользоваться одним из нижеследующих методов.

Собственно сжатие

Для сжатия понадобится вот такой кусочек кода
<?php 
ob_start ("ob_gzhandler");
header("Content-type: text/css; charset=UTF-8");
header("Cache-Control: must-revalidate");
$offset = 60 * 60 ;
$ExpStr = "Expires: " . 
gmdate("D, d M Y H:i:s",
time() + $offset) . " GMT";
header($ExpStr);
?>
Этот код делает следующее:
  1. Использует PHPшный ob_gzhandler для посылки сжатых данных. Эта функция сначала проверит может ли броузер принимать контент типа 'gzip,deflate' encoding;при отрицательном ответе посылает несжатые данные.
  2. Посылает header с content type и кодировкой файла - здесь это text/css и UTF-8.
  3. Далее проверяет надо ли уже обновлять кэш для этого файла
  4. Посылает информацию о том, сколько хранить файл в кэше до следующей загрузки.

Метод первый

Первый метод заключается в переименовании вашего CSS файла в .php. При этом прикрепление к страничке будет выглядеть так:
  @import url(mycss.php);
Ну и в начало файла нужно добавить кусочек кода указанный выше.

Метод второй

Второй метод чуть более универсальный. Тут не надо будет ничего менять в CSS файлах. Однако он требует правки .htaccess файла. Во-первых нужно сохранить код указанный выше, например в файл "gzip-css.php". А затем добавить в .htaccess файл следующие строки:
AddHandler application/x-httpd-php .css
php_value auto_prepend_file gzip-css.php
php_flag zlib.output_compression On

Пример

Я применил первый метод на зеркале ukr.net по адоесу http://alegol.ukr.net/. Результат себя полностью оправдал. Поскольку доступа к логам у меня нет, то я воспользовался сервисом websiteoptimisation. Результаты можно увидеть по адресам: alegol, ukr.net В результате размер CSS файла упал с 18Кб до 4.5Кб. Жаль нельзя логи посмотреть и узнать как оно на самом деле работает при массовых нагрузках.

Заключение

100% очень полезная штука особенно когда нет контроля над веб-сервером.

Однако есть несколько недочетов. Ходят слухи что есть какой то глюк в одной из версий ИЕ6, якобы он посылает инфу что может читать gzip, но на самом деле не раскодирует контент такого типа. Если кто то заметит подобный глюк или что то слышал об этих случаях просьба откликнуться в комменты.

Надо только еще перепроверить как оно нагружает сервер, ну а малым и средним сайтам 100% мастду.

Мну удалось найти такую инфу.

Unfortunately, IE6 (and perhaps earlier versions?) appears to have a bug with gzip over SSL where the first 2048 characters are not included in the HTML rendering of the page when refresh is pressed. It only seems to happen on longish pages, and not when the page is first loaded. In fact, sometimes it doesn't happen at all. The only current solution is to put a 2048 character comment at the start of your longish pages of all spaces (which compresses pretty well, fortunately).

Однако тут имелись ввиду ХТМЛ файлы и апачевское сжатие, поэтому не знаю имеет ли это отношение к нашему случаю.

18 комментариев к “Как сжимать CSS”

1.DiGiTAL | 30 Apr, 2005
нашел и разобрался... просто не было необходимости пользоваться, так что предыдущие комменты прошу удалить, как флуд ;)
2.DiGiTAL | 30 Apr, 2005
по поводу второго метода: а что делать, если хостер отключил установки пхп для хаткасов? идея просто понравилась... а реализовать - никак... и надо не для цсс совсем
3.akella | 30 Apr, 2005
тогда как по мне проще заставить его юзать mod_gzip или deflate. Или связаться с хостером, тока надо на хорошее настроение попасть :). Ниче более дельного не знаю :(
4.ganges | 09 Apr, 2005
Нормально работает, действительно можно сжимать. Вот только быстро привыкаешь :) и перестаешь париться насчет размера файлов, а это имеет, как ты понимаешь, последствия. Поэтому, имхо, надо просто стараться писать короткий CSS, что в случае с Укрнет, конечно, врядли возможно. Я стараюсь писать суммарный CSS не более 12 килобайт, пока получается :)
5.mourner | 09 Apr, 2005
Кстати, только что заметил, что у тебя линк на css validator в футере поломан. :-)
6.akella | 10 Apr, 2005
знаю знаю Спсб - боюсь что не пройду валидацию ;) скоро исправлю...
7.tobto_ | 14 Mar, 2006
а засунуть css в кеш с помощью javascript?
8.W@D | 18 Mar, 2006
А разве CSS не в кэше?! (вопрос риторический)
9.Aleko | 16 Oct, 2009
Можно ещё так оптимизировать: http://studioad.ru/blog/szhimaem_css_algoritmom_base62/2009-10-16-97
10.Тормоз | 30 Aug, 2007
Попробовал у себя сделать - CSS вообще грузиться перестали. Жаль.
11.Тормоз | 30 Aug, 2007
Привет! Твой блог знаю уже не первый год, но на этот раз пришел с поисковика, и нашел именно то, что искал :) Спасибо!
12.gugglegum | 12 Sep, 2007
Во-первых, выдавать CSS при помощи PHP -- это дико с точки зрения нагрузки на веб-сервер. Во-вторых, Ваш первый метод увеличивает время загрузки на 1 GET-запрос. И на самом деле это не нужно, Вы можете в самом HTML прописать ссылку не на CSS, а на PHP-файл. Так будет проще, быстрее и естественнее. В-третьих, доступ к серверу на нормальных хостингах все же есть. И если у нас есть доступ к .htaccess, используемому во втором методе, то наверняка мы там же можем заюзать и mod_deflate. В-четвертых, Ваш метод хоть и реализует сжатие CSS, но при этом почти сводит на нет кэширование. Вы используете только Expiration Model кэширования, а по истечению срока вынуждаете браузер загружать CSS заново, даже если он не изменился. Я предлагаю свой вариант. Я просто модифицировал один свой старый исходник, сейчас у меня есть более совершенный способ, но он слишком большой для постинга сюда. Мой вариант использует сразу обе модели кэширования: Expiration и Validation. В течение 24 часов CSS будет лежать в кэше и браузер даже не будет обращаться к серверу, а по истечении 24 часов браузер пошлет условный запрос, который вернет CSS только, если он с тех пор изменился, либо HTTP/1.1 304 Not Modified, если нет. Мой вариант использует mod_rewrite. Лично я использую исключительно его при написании веб-приложений, поэтому его наличие на сервере для меня -- как стандарт де-факто. Я просто ставлю в технические требования к веб-серверу наличие этого модуля. Итак, в .htaccess пишем: RewriteEngine on RewriteCond %{REQUEST_FILENAME} -f RewriteRule \.css$ cssfilter.php а в cssfilter.php: */ // assume that REQUEST_URI contains short URI from document root $file = $_SERVER['DOCUMENT_ROOT'].$_SERVER['REQUEST_URI']; // we don't have to warn about file existing because rewrite rule guarantees that. if (($content = file_get_contents($file)) !== false) { // handle HTTP request header If-Modified-Since (simulating static content) $lastmod = filemtime($file); if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { $modsince = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']); if ($modsince != -1 && $modsince == $lastmod) { header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); header('Content-Type: text/css'); exit(); } } $maxAge = 3600 * 24; header('Expires: '.gmdate("D, d M Y H:i:s", time() + $maxAge) . " GMT"); header('Cache-Control: public; max-age='.$maxAge); header('Last-Modified: '.gmdate("D, d M Y H:i:s", $lastmod) . " GMT"); header('Content-Type: text/css'); // output CSS file ob_start('gz_handler'); echo $content; ob_end_flush(); } else // we should never reach this condition (only if some hardware error) echo "Read file error"; ?>
13.gugglegum | 12 Sep, 2007
Мда... Форматирование кода сломалось, и комментарий почему-то удалился, остался только закрывающий комментарий в начале...
14.DfK | 26 Oct, 2007
мм, не знаю, у меня текст сжимается не меньше чем в 10 раз;)
15.Taras | 19 Dec, 2007
из 11 поста не работает в FireFox
16.ScorpAL | 27 Feb, 2008
http://dev.wp-plugins.org/wiki/css-compress CSS Compress - плагин для WordPress для сжатия CSS в GZip
17.BOLK | 20 Nov, 2008
Тут ошибка: header("Content-type: text/css; charset: UTF-8"); Должно быть: header("Content-type: text/css; charset=UTF-8");
18.akella | 20 Nov, 2008
Спасибо! Поправил!