Прогрессивное улучшение и CSS
Aaron Gustafson, 4 декабря 2008
В предыдущей статье серии мы ознакомились с концепцией прогрессивного улучшения, теперь самое время обсудить ее практическое применение. В этой статье акцент будет сделан на CSS.
Организация стилей
Большинство веб-разработчиков не задумываются о том, как они подключают стили к документу, на самом деле это целое искусство. Используя правильные методы, вы автоматически получите многие из преимуществ прогрессивного улучшения.
Использование нескольких файлов стилей
Очевидно, что файлы стилей содержащие больше 1500 строк сложно поддерживать и разделение может упростить работу с ними. Другое преимущество, о котором не всегда вспоминают, заключается в том, что разделение позволяет лучше управлять представлением для различных устройств, которые мы собираемся поддерживать.
Возьмем файл main.css, содержащий все стили для вашего сайта и разделим его на несколько файлов содержащих типографику, разметку, цветовую информацию, назовем их соответственно: type.css, layout.css, color.css.

Теперь, не прикладывая сколь либо значительных усилий, мы можем показать упрощенную версию страницы в браузерах плохо поддерживающих CSS или очень старых браузерах (таких как Internet Explorer 5/Mac). Как? Вся хитрость в том, как мы подключаем файлы. Перед тем как мы начали вносить изменения, единственный файл main.css подключался с помощью элемента link следующим образом:
<link rel="stylesheet" type="text/css" href="main.css" />
Потом мы разделили его на три файла подключаемых индивидуально:
<link rel="stylesheet" type="text/css" href="type.css" /> <link rel="stylesheet" type="text/css" href="layout.css" /> <link rel="stylesheet" type="text/css" href="color.css" />
В прошлом многие из нас использовали media="screen,projection" чтобы скрыть от Netscape 4.x файл с разметкой, я покажу способ лучше. Но прежде давайте обратим внимание на альтернативные медиа типы.
Альтернативные медиа типы
Поскольку прогрессивное улучшение сфокусировано на контенте и мы хотим показать его лучшим образом на всех устройствах где это возможно, нужно думать не только о браузерах, но и о печати и мобильных устройствах.
К несчастью, рынок мобильных устройств все еще очень фрагментирован и незрел (не заставляйте меня меня вспоминать о мобильных браузерах, думающих, что они должны использовать стили для устройства screen). Благодаря этому, обсуждение всех деталей использования прогрессивного улучшения для мобильных устройств, требует как минимум нескольких статей, а может и целой книги. Но не отчаивайтесь: умные люди уже начали собирать ресурсы призванные помочь в разработке для мобильных устройств, мы же пока сфокусируемся на печати.
Обычно стили для печати подключаются отдельным файлом с помощью элемента link:
<link rel="stylesheet" type="text/css" media="print" href="print.css" />
А файл print.css содержит все стили, используемые в версии для печати, включая типографику и цветовое оформление. В большинстве случаев для печати используются точно такие же, как в главном файле стилей, правила типографики и, возможно, некоторые другие правила, другими словами много кода будет дублироваться. Поэтому отделение типографики и цветовой схемы от разметки отличная идея, нам больше не нужно будет дублировать типографику в стилях для печати. Ну и конечно разделение позволяет нам лучше приспособить сайт для работы в проблематичных браузерах.
Выше мы уже пришли к следующему способу подключения стилей:
<link rel="stylesheet" type="text/css" href="type.css" /> <link rel="stylesheet" type="text/css" href="layout.css" /> <link rel="stylesheet" type="text/css" href="color.css" />
Теперь посмотрим, что можно сделать, чтобы адаптировать сайт к работе в старых браузерах.
Поскольку мы не указали медиа типы, Netscape 4.x будет видеть стили во всех трех файлах, чтобы избежать этого, воспользуемся его слабым пониманием CSS. Для лучшей организации CSS переместим стили из файла layout.css в новый файл screen.css, а в layout.css подключим его с помощью директивы @import, поскольку NS4.x не поддерживает эту директиву, стили, отвечающие за разметку, будут от него надежно скрыты.
@import 'screen.css';
Остается указать, для какого устройства предназначены эти стили:
@import 'screen.css' screen;
Проблема этой записи в том, что IE до седьмой версии включительно, не понимаеет такой синтаксис и игнорирует подключаемые стили. Преодолеть эту проблему нам помогут условные комментарии.
Поскольку IE5/Mac плохо поддерживает CSS, особенно плавающие блоки и позиционирование, лучше полностью скрыть от него стили, отвечающие за разметку. Чтобы сделать это достаточно использовать для имен файлов одинарные ('), а не двойные (") кавычки. При этом типографика и цветовая схема могут быть сохранены.
Тот же самый прием мы используем для подключения файла print.css (который как нетрудно догадаться содержит стили для печати).
@import 'screen.css' screen; @import 'print.css' print;
Теперь у нас не только хорошо организованны стили, но и эффективно задействовано прогрессивное улучшение.

Вопрос на 10 мегадолларов: что делать с IE6?
Для многих разработчиков, Internet Explorer 6 — это новый Netscape 4, он является постоянным источником проблем, и верстальщики с нетерпением ждут того момента когда он окончательно покинет рынок браузеров.
Опустим здесь негодования по поводу проблем в IE6, они хорошо документированы и многие из них легко преодолимы, тем более, что переход на IE7 происходит достаточно быстро (особенно среди индивидуальных пользователей), а IE8 уже в стадии беты, и день когда мы сможем сказать «пока, IE6» все ближе.
Отличный инструмент для реализации прогрессивного улучшения внедрен Microsoft еще в IE5, он называется: условные комментарии. Это замечательное изобретение позволяет нам не только скрыть часть разметки от остальных браузеров, но и точно указать для каких версий IE она должна быть видима.
Как приверженцы веб стандартов мы должны начинать тестирование в наиболее соответствующем стандартам браузере, и только потом в тех, к которым нужно принимать дополнительные меры. Конечно, у каждого разработчика индивидуальный подход, но я стараюсь каждый проект начинать со стандартного набора файлов:
type.csslayout.cssscreen.cssprint.csscolor.css
Потом в зависимости от требований проекта, я добавляю отдельные файлы для некоторых браузеров, в большинстве случаев это ie7.css и ie6.css, если проект требует поддержки более старых версий IE то создается соответствующий файл (например, ie5.5.css).
Тестирование CSS я всегда начинаю в Mozilla Firefox, поскольку при написании CSS использую Edit CSS сайдбар. После того как написаны все стили, я начинаю тестирование в других браузерах. В браузерах хорошо поддерживающих стандарты, редко возникают какие либо проблемы. В IE7 в большинстве случаев, проблем не так уж много, но иногда нужно включить hasLayout или исправить какой нибудь небольшой баг разметки. В этом случае, я добавляю необходимые для этого правила в ie7.css и подключаю его к документу, используя при этом условные комментарии:
<!--[if lte IE 7]> <link rel="stylesheet" type="text/css" href="ie7.css" /> <![endif]-->
Такой условный комментарий позволяет подключать этот стиль только для IE версии меньшей либо равной (lte) 7. Это значит, что если кто-то зайдет на страницу из IE7, то исправления будут работать, но если он зайдет из новой версии, в которой проблема вероятно уже исправлена, файл с этими правилами будет проигнорирован.
С другой стороны, если кто-то зайдет на страницу из IE6, исправления из файла для IE7 будут задействованы и это правильно, поскольку, ошибки которые есть IE7 скорее всего есть и в IE6. Хороший пример такой ошибки это непонимание директивы @import с указанным медиа типом, которое исправляется добавлением директивы @import ' screen.css' в начале файле ie7.css без указания медиа типа, которая подключит недостающий файл.
После того как внесены все исправления необходимые для IE7, я открываю IE6 и смотрю не нужна ли ему помощь в отображении этой страницы, если такая необходимость есть, то я добавляю в документ еще один условный комментарий, в котором подключается файл ie6.css.
<!--[if lte IE 7]> <link rel="stylesheet" type="text/css" href="ie7.css" /> <![endif]--> <!--[if lte IE 6]> <link rel="stylesheet" type="text/css" href="ie6.css" /> <![endif]-->
Стили из файла ie6.css будут работать в IE6 и ниже, и игнорироваться в IE7 и старших версиях.
Использование условных комментариев позволяет легко разделить стили для различных браузеров и избежать использования CSS хаков.
Другие применения прогрессивного улучшения
Прогрессивное улучшение это, конечно, не только способ подключения CSS к документу, подход распространяется и на то, какие правила мы запишем в подключаемые файлы.
Рассмотрим для примера генерируемый контент. Не все браузеры его поддерживают, но он отлично подходит, если нужно добавить элементы дизайна или текст не влияющие на юзабилити страницы, а создающие только дополнительный визуальный эффект.
Для пример возьмем контактную форму:

Создавая HTML код для этой формы, вы, возможно, захотите добавить двоеточия прямо в элемент label. Почему? Добавляют ли они что нибудь к значению меток? Нет. Единственная роль этих двоеточий, создавать визуальный эффект, поэтому их наличие в элементе label нежелательно. HTML код формы будет выглядеть следующим образом:
<form id="contact-form" action="#" method="post">
<fieldset>
<legend>Contact Us</legend>
<p>Send us a message. All fields are required.</p>
<ol>
<li>
<label for="contact-name">Name</label>
<input type="text" id="contact-name" name="name" />
</li>
<li>
<label for="contact-email">Email</label>
<input type="text" id="contact-email" name="email" />
</li>
<li>
<label for="contact-message">Message</label>
<textarea id="contact-message" name="message" rows="4" cols="30">
</textarea>
</li>
</ol>
<button type="submit">Send It</button>
</fieldset>
</form>
А двоеточия мы добавим с помощью генерируемого контента, который отлично для этой цели подходит:
label:after {
content: ":";
}
Такой подход даст вам возможность убрать двоеточия во всех формах сайта, отредактировав только одно правило CSS, вместо того чтобы править каждую форму отдельно. Не стоит беспокоиться о том, что не все браузеры поддерживают генерируемый контент, ведь форма полностью сохраняет свою функциональность — отличный пример прогрессивного улучшения.
Использование правил с продвинутыми селекторами позволяет добавить стили только для современных браузеров. Хорошим примером может быть селектор атрибутов, который игнорируется IE6 другими браузерами его поколения. Егор Клоос использовал это при создании прекрасной темы для CSS Zen Garden названной «Gemination».

Тема Егора Клоос «Gemination» для CSS Zen Garden в браузере, поддерживающем стандарты, и IE6.
Как он это сделал? Очень просто, вот слегка модифицированный пример кода:
/* <= IE 6 */
body {
margin: 0;
text-align:
center;
background: #600 none;
}
/* IE 7, Mozilla, Safari, Opera */
body[id=css-zen-garden] {
margin: 100px 0 0;
padding: 0;
text-align: center;
background: transparent url(squidback.gif);
}
Разница во внешнем виде сайта поразительна и прекрасно иллюстрирует большие возможности техники прогрессивного улучшения.
Что-то похожее сделал на своем сайте и Энди Кларк. Используя условные комментарии, доступные в IE фильтры и немного дополнительных изображений он сделал сайт полностью черно-белым в IE6.

Черно белые изображения получены с помощью фильтра в CSS файле подключаемом только для IE6:
/* =img for Internet Explorer < 6 */
img {
filter: gray;
}
Конечно, эти примеры далеки от того, что нужно использовать в повседневной работе, но они хорошо демонстрируют возможности прогрессивного улучшения.
Подведем итоги
Мы обсудили, множество способов создания CSS с применением концепции прогрессивного улучшения. Самый простой и, возможно, лучший способ это обдуманное подключение тех файлов стилей, которые лучше подходят браузеру или устройству, с которого пользователь просматривает сайт. Борьба с недугами IE не составит проблем, стоит вам только понять возможности условных комментариев.
Translated with the permission of A List Apart Magazine and the author[s].

Спасибо за перевод.
Меня несколько смущает такое пристальное внимание автора текста к браузерам-диновравм. Неужели в зарубежном интернете до сих пор поддерживают NN4 и IE5/Mac? Или же это всё для пущей убедительности метода?
Мне тоже кажется, что динозаврам уделено слишком много внимания, а быстро набирающим популярность мобильным браузерам напротив недостаточно. Постараюсь найти хороший материал, который исправил бы этот дисбаланс.
забавна доля нетскейпа (столь обильно упоминаемого) на рынке браузеров.
типо подключеня CSS, предлагаемый в статье лично мне кажется чем то, наподобие предложения структурировать блоки html-контента ненумерованными списками, то есть, он кажется мне излишне усложненным и вызывающим увеличение трафика, ибо:
1. разделяя типографику и цветовое решение, мы вынуждены дважды упоминать одни и те же теги, классы, идентификаторы
2. непонятно зачем создавать специальный css-файл для экранного отображения, если можно подключить файл для печати и мобильных устройств и при необходимости будут использованы именно они (а по поводу незрелости рынка мобильных устройств — согласен — именно поэтому мобильная версия сайта на данный момент времени — это не подключенный css для мобильников, а отдельная версия сайта, отличающаяся от основной не только стилями, но и структурой html-потока документа).
очень понравился пример про двоеточия, хотя я и н считаю их нежелательными в lаbel. пример понравился не этим. а вот чем:
читаем в предыдущей статье про graceful degradation:
«В соответствии с этой парадигмой, пользователи старых браузеров контент получат не в лучшем виде, но все же получат.»
смотрим, что получит пользователь IE6 при подобной реализации двоеточия. именно «контент не в лучшем виде».
проще говоря, разницы между двумя концепциями или очень мало, или почти нет (или, скажем прямо, я ее не понимаю просто :) )
на данный момент лично я как разработчик верстаю под FF3, тестирую и, иногда, чуть корректирую для FF2 и Opera пары последних версий, после чего пишу стилевые файлы для почти-браузеров IE6 и IE7, подключамые (файлы) через условные комментарии.
итого имею 5 файлов, из которых гарантировано грузятся два.
1. сброс стилей
2. основной стилевой файл
3. пара файлов для ишаков (эти файлы не загружаются для других браузеров)
4. печатные стили
(для мобильных устройств генерируется упрощенная версия сайта (см, к примеру, pitercult.ru)
при небольшом количестве кода вполне можно совместить сброс стилей и главный стилевой файл.
в целом, во время чтения не удавалось избавиться от ощущения, что материалу лет этак 5 (толкьо когда о мобильниках зашла речь - немного успокоился).
статью считаю несеткой, с большим количеством «воды», проще говоря — «почти ни о чем».
поиск концепции всегда приходит к ее нахождению. просто иногда находят то же самое, что имеют.
на мой взгляд, разница менжду этими двумя подходами в рамках следования стилю веб2.0 (я имею в виду принципы формирования контента, дизайнерскую, но не оформительскую сторону) столь эфемерна, что ее подчеркивание высосано из пальца.
Вот так и метаются разработчики между несколькими CSS и оптимизаторами заставляющими сливать все в один файл.
Идея о выносе двоеточия в подключаемую разметку на мой взгляд несколько бредова. Насколько легко будет понять человеку, читающему твой код откуда берётся двоеточие, если в разметке его нет? Оно с одинаковой долей вероятности может быть реализовано как через js, так и через css.
И, ко всему прочему, поиск по регулярным выражениям ещё никто не отменял.
Я читал, что разделение на разные файлы стилей не желательно, т.к. то заставляет повторно обращаться серверу для загрузки каждого фала стилей. А это в целом влияет на скорость загрузки. Насколько себя оправдывает деление в этом плане?
На скорость загрузки влияет несущественно. Такая организация оправдана при сложной разработке и очень, очень сокращает время на поиск и отладку, включая совместную работу нескольких разработчиков над одним и тем же ресурсом.
Никто не мешает слить все это в один файл при окончательном запуске проекта.
@SeoEvgeny
Присоединюсь к idcontent.
Во время разработки разделяю файлы на несколько, при чем если проект большой, то еще и в зависимости от модулей применяемых на сайте (news.css, catalog.css и т.п.), а при выкладывании «на продакшин» переключаю конфиг сайта, и получаю единый, слитый версионный CSS (например main_1.1.css), который упаковывается дополнительно через gzip (например в main_1.1.css.gz) и на уровне сервера в зависимости от поддержки / не поддержки gzip отдаю тот или иной файл с заголовками для длительного кэширования браузером.
Версии для мобильных / печати / осликов — в отдельные аналогичные файлы через media="…" + условные комментарии.
И с одной стороны получаем удобство разработки, а с другой минимальный трафик для пользователей + минимальное число запросов к серверу, что актуально для высоконагруженных проектов.
Разделение через @import 'screen.css' screen; — по моему и усложняет «ориентацию» по CSS для разработчика, особенно если не ты полностью верстал / вел проект + не дает возможности упаковки и подражает лишние запросы.
А вообще идея понятна и хороша — главное информация, а как ее представить можно подумать отдельно )
А если брать не обычные статистические страницы, а CMS. К тому же на многих сайтах есть отдельный стиль для печати. Я сторонник использования одного файла *.css для всего сайта, так как идет кэширование после первой загрузки.
Представте что я тупой пользователь который понятия не имеет что такое CSS Web 2.0 семантика и блочная верстка. Мен понравилась эта статья я беру и сохраняю эту страничку причем тип файла выбираю "Веб страница, только HTML". Я думаю вы уже догадались, что я увижу?
Собственно вопрос, как сделать чтобы страница отображалась корректно, в вышеописаной ситуации?