29 Март 2010 | Разделы: Юзабилити, Разработка, Верстка, Дизайн

Перевод статьи Fluid Grids, автор Ethan Marcotte.
Translated with the permission of A List Apart Magazine and the author[s].
В начале прошлого года мне довелось перестраивать сайт, сильно перегруженный контентом. Дизайн должен был соответствовать довольно простым требованиям: клиент попросил оставить существующий логотип организации, но повысить плотность текстов и улучшить оформление и удобочитаемость. Таким образом, начали мы с того, что потратили довольно много времени на вычерчивание четкой сетки для библиотеки контентных модулей.
В последние годы такой подход встречается все чаще. Интерес к сеточному дизайну и применение его на веб-сайтах обрели второе дыхание благодаря Марку Боултону , Хою Винху и остальным . Ни капли не преувеличивая, можно утверждать, что идея оказалась более чем успешной: появилось большое количество CSS фреймворков, снабженных разнообразным инструментарием, предназначенным для того, чтобы среднестатитистический дизайнер мог легко освоить новый метод. Впрочем, почему бы и нет? Пятиминутных размышлений достаточно, чтобы признать преимущества использования сеток: дизайнеры получают возможность упорядочивать контент при помощи рационального и структурированного фреймворка, а пользователи наслаждаются четкими удобными сайтами.
Однако наш клиент выдвинул еще одно требование, от которого у меня екнуло сердце: дизайн должен быть гибким и подстраиваться под размер окна. Как правило, подобное условие заставляет меня громко и неприлично выражать свою радость. В веб-дизайне гибкой верстке уделяется недостаточно внимания. Судьба внешнего вида сайта оказывается в руках пользователя и зависит его предпочтений в выборе браузера. Это совершенно убивает дизайнерский замысел.
Вместо того, чтобы изучать преимущества гибкого веб-дизайна, мы прибегаем к маленькой хитрости: «минимальному разрешению экрана». Эти три слова имеют поистине магическую силу; под их прикрытием мы штампуем один жесткий дизайн за другим, переделывая их каждые пару лет в соответствии с новыми стандартами ширины - как только это становится достаточно безопасно. «Минимальное разрешение экрана» позволяет проектировать сайты для неких выдуманных пользователей, которые видят ваше творение в соответствии с замыслом Божьим и Фотошопа. У этих пользователей всегда установлено разрешение 1024×768, и они никогда не пользуются, например, ноутбуками OLPC , и не смотрят на мир через монитор, которому больше 4-х лет. Если пользователь не соответствует «минимальному разрешению экрану», ну что ж, для таких придумали полосу прокрутки, разве нет?
Конечно, во время написания сайта мне было не до гневных речей в адрес дизайна с фиксированной шириной страницы. Передо мной стояла другая проблема: мы разработали довольно сложную сетку для размещения всего требуемого контента, но клиент — и, как следствие, его пользователи — хотел получить гибкую сетку. На тот момент все знакомые мне сеточные дизайны были жесткими, поэтому вопрос встал ребром: как создать гибкую сетку?
Как оказалось, все зависит от контекста.
Оказавшись лицом к лицу с непосильной задачей, я прибег к своей лучшей тактике: попытался ее избежать. Временно отложив вопрос о том, как заставить сетку меняться при изменении параметров страницы, я начал писать то, что знал: сначала стили для цветов и фона, затем для шрифтов.
Скорее всего, вы слышали о часто описываемой проблеме Internet Explorer — невозможности менять размер шрифтов в пикселях. Если установлен шрифт Georgia высотой 16 пикселей, то сколько ни пытайся его увеличить или уменьшить, в IE он сохранит эту высоту. IE7 и выше позволяет пользователю масштабировать всю страницу, но простое изменение размера пиксельного шрифта в Internet Explorer, как правило, невозможно. Таким образом, чтобы обеспечить нашим пользователям наибольший комфорт, мы — дизайнеры, съевшие собаку на стандартах — обычно стараемся избежать использования пиксельных размеров, вооружаясь вместо этого относительными единицами, будь то ключевые слова, проценты или мои фавориты, em.
Если вы когда-нибудь работали с относительными единицами, например, em, вы уже знаете, что все зависит от контекста: другими словами, действительное значение em для элемента вычисляется в зависимости от величины font-size родительского элемента. Например, предположим, что мы работаем со следующим объектом:
Пример обычного текста, размеры установлены в пикселях.

Ничего сверхъестественного: для некоторых абзацев установлен шрифт Helvetica высотой 16 пикселей, неотсортированный список уменьшен до 14 пикселей, а для заголовка h1 задан шрифт Georgia высотой 24 пикселя. Здорово, правда?
Но еще лучше то, что ситуацию можно выгодно обыграть, воспользовавшись одним простым правилом.
body {
font: normal 100% Helvetica, Arial, sans-serif;
}
Когда font-size равен 100%, все элементы на странице масштабируются относительно высоты шрифта по умолчанию в браузере, которая по большей части равняется 16 пикселям. Благодаря изначально заданной в браузере таблице стилей, заголовок h1 выводится большими, жирными, красивыми буквами — но шрифтом Helvetica, слишком крупным. Было бы очень просто дописать атрибут font-family, чтобы исправить ситуацию с шрифтом Helvetica в заголовках, но как же выставить высоту 24 пикселя? Или аккуратно уменьшить высоту текста в списке?
Эти вопросы легко решаются с помощью тэга em. Берем нужное значение font-size для каждого элемента в пикселях и делим его на значение font-size его контейнера (то бишь, контекста). Получаем требуемое значение font-size, выраженное в относительном, удобном для em виде. Если короче, то:
target ÷ context = result
Предположив, что значение шрифта для body по умолчанию равно 16 пикселей, подставим желаемую величину font-size в эту формулу. Теперь, чтобы разместить заголовок в образце, разделим требуемое значение (24 пикселей) на значение font-size контейнера (16 пикселей):
24 ÷ 16 = 1.5
Заголовок в полтора раза шире тела записи, что составляет 1,5em; эта величина может быть включена в таблицу стилей.
h1 {
font-family: Georgia, serif;
font-size: 1.5em; /* 24px / 16px = 1.5em */
}
Чтобы привести список к em-эквиваленту 14 пикселей, используем ту же формулу. Снова предполагая, что значение font-size для body равняется приблизительно 16 пикселям, делим требуемое значение на ширину контекста:
14 ÷ 16 = 0.875
Получаем 0.875em, вставляем в таблицу CSS.
ul { font-size: 0.875em; /* 14px / 16px = 0.875em */ }
После применения этих правил наша модельная страницы гораздо больше походит на оригинал; в качестве последнего штриха проведем небольшую чистку. С помощью формулы target ÷ context = result
Вот так, проведя несколько часов за приведением таблицы стилей моего клиента в процентный вид, я понял, что нашел ответ. Если с высотой шрифтов можно обращаться не как с пиксельными величинами, а как с выражениями в процентах относительно контейнера, почему бы не сделать то же самое и с остальными элементами, натянутыми на таблицу.
Как и раньше, давайте начнем с относительно топорного простого расположения элементов:

Наше расположение элементов на странице
Конечно, наш "дизайн" довольно скромен. Но эти простые стили натянуты на хорошо структурированную сетку: а именно, семь столбцов по 124 пикселя каждый, разделенные промежутками шириной 20 пикселей — всего 988 пикселей. Но давайте забудем об этих гадких пикселях. Сейчас в моде относительность, ведь так? Так будем же гибче.

Для начала давайте обращаться с нашим образцом дизайна, как с любым другим, гибким или жестким: перед тем, как что-то писать, внимательно рассмотрим общую структуру и выделим различные контентные области. Слава Богу, это нетрудно.

Определяем различные контентные области.
На самом высоком уровне распределения: вверху расположен заголовок, ниже — область содержимого, растянувшаяся на 6 колонок, и некая дополнительная информация в самой левой колонке. На основе этой диаграммы можно построить некоторый скелет расположения контента, как структурный, так и семантический.
<div id="page">
<h1>The Ratio Revolution Will Not Be Televised</h1>
<div class="entry">
<h2>Anyone else tired of Helvetica?</h2>
<h3 class="info">A <a href="#">Blog</a> Entry:</h3>
<div class="content">
<div class="main">
<p>Main content goes here. Lorem ipsum etc.</p>
</div><!-- /end .main -->
<div class="meta">
<p>Posted on etc., etc.</p>
</div><!-- /end .meta -->
</div><!-- /end .content -->
</div><!-- /end .entry -->
</div><!-- /end #page -->
Итак, применив определенные правила, мы получили довольно приличную основу. Однако на контейнер #page не наложено никаких ограничений, так что наш контент просто "растечется", заполнив всю ширину окна браузера. Отрегулируем длину строк:
#page {
margin: 40px auto;
padding: 0 1em;
max-width: 61.75em; /* 988px / 16px = 61.75em */
}
Для чистки дизайна мы использовали элементы margin (край) и padding (отступ), попутно установив отступ между границами документа и окна. Но в последней строчке наших условий для определения максимальной ширины документа была использована модификация формулы для font-size. Разделив ширину образца, равную 988 пикселям, на базовое значение font-size, равное 16 пикселям, можно установить максимальную ширину max-width в em'ах и приблизить пиксельные величины нашего макета; это помешает странице выйти за пределы 988 пикселей. Для получения верхнего предела был использован тэг em, поэтому значение max-width будет увеличиваться по мере того, как пользователь будет увеличивать размер текста — этот остроумный трюк работает даже в старых версиях Internet Explorer, если предварительно применить маленький CSS-патч.
Итак, надежно укрепив дизайн в общем, займемся каждым элементом в отдельности, начиная с заголовка страницы. В модели он занимает пять колонок и 4 промежутка между ними — в сумме 700 пикселей. Он также сдвинут от левого края на один столбец и один промежуток, что составляет отступ в 144 пикселя. Если бы мы создавали жесткий дизайн, код выглядел бы весьма прямолинейно:
h1 {
margin-left: 144px;
width: 700px;
}
Но мы работаем в гибком контексте, поэтому фиксированные значения нам не подойдут. В процессе работы над изменением размера шрифтов мне в голову пришла идея: любая часть сетки — и наложенные на нее элементы — могут быть выражены через отношение их размеров к размеру контейнера. Другими словами, как и в случае с изменением размера шрифтов, нас интересует не просто желаемый размер элемента, но отношение его размера к размеру контейнера. Это позволит превратить значения ширины в пикселях в проценты и сохранять пропорции в сетке при изменении ее размеров.
Короче говоря, мы получили гибкую сетку.
Итак, с чего начнем?
target ÷ context = result
Правильно: возвращаемся к старой доброй формуле. Можно использовать тот же анализ пропорций для преобразования ширины столбцов в пикселях в гибкие величины в процентах. Мы отталкиваемся от желаемой ширины заголовка, равной 700 пикселям — но заголовок содержится в контейнере шириной 988 пикселей.

Преобразуем размер заголовка в пикселях в проценты.
То есть, просто делим 700 пикселей (требуемое значение) на 988 пикселей (ширина контекста):
700 ÷ 988 = 0.7085
И вот: 0.7085 переходит в 70.85%, значение ширины, записываемое прямо в таблицу стилей:
h1 {
width: 70.85%; /* 700px / 988px = 0.7085 */
}
Пройдет ли этот трюк с крайним значением в 144 пикселя? О, я так люблю наводящие вопросы:
144 ÷ 988 = 0.14575
Опять-таки, можем взять 0.14575, или 14.575%, и добавить прямо в таблицу стилей как значение margin-left заголовка:
h1 {
margin-left: 14.575%; /* 144px / 988px = 0.14575 */
width: 70.85%; /* 700px / 988px = 0.7085 */
}
И вуаля. Измерив границу заголовка и его ширину относительно контейнера, мы успешно сохранили все пропорции при переносе размеров из сетки в пригодные для CSS процентные величины. Пропорции заголовка будут сохранены в любом случае, даже если он не помещается в окно браузера.
То же преобразование можно применить в нашем примере для расположения самой записи шириной 844 пикселей с отступом 124 пикселя слева. Для записи:
844 ÷ 988 = 0.85425
Для информационной колонки:
124 ÷ 988 = 0.12551
Вот такие быстрые расчеты позволяют перевести в проценты некоторые величины, заносимые впоследствии в таблицу стилей и описывающие расположение элементов на странице:
.entry h2,
.entry .content {
float: right;
width: 85.425%; /* 844px / 988px = 0.85425 */
}
.entry .info {
float: left;
width: 12.551%; /* 124px / 988px = 0.12551 */
}
Таким образом, гибкая сетка обретает форму.
На данный момент мы рассортировали крупные области контента, но осталась еще внутренняя часть Сейчас основной текст и сопутствующая информация занимают всю ширину, отведенную под запись, и находятся друг над другом. Но в исходной модели основной текст записи занимал только пять столбцов, а в самой правой колонке располагалась дополнительная информация.
Вдумчивые читатели наверняка обратили внимание, что в текущей реализации ширина записи совпадает с шириной заголовка страницы (700 пикселей), а боковые отступы имеют такую же ширину, как и обработанный ранее левый столбец (124 пикселей). Итак, работая с рассчитанными ранее размерами, нельзя использовать те же формулы: ведь изменился контекст.
Находясь в границах нового контейнера, нужно учитывать его ширину.
Выше были рассчитываны проценты относительно элемента #page шириной 988 пикселей, сейчас же надо иметь дело с заметно меньшими .entry .content. То есть, требуется переопределить контекст и использовать в качестве точки отсчета заданную ширину .entry .content. Чтобы определить ширину основного текста в процентах, возьмем данную ширину 700 пикселей и разделим на 844 пикселя:
700 ÷ 844 = 0.82938
Для правого столбца шириной 124 пикселей можно брать ту же точку отсчета:
124 ÷ 844 = 0.14692
Теперь каждое из этих измерений включаем в CSS:
.entry .main {
float: left;
width: 82.938%; /* 700px / 844px = 0.82938 */
}
.entry .meta {
float: right;
width: 14.692%; /* 124px / 844px = 0.14692 */
}
Это был последний этап работы, гибкая сетка готова.
Как можно было догадаться по отсутствию примеров на CSS-хаки, при смене браузера этот момент редко вызывал проблемы. Я бы порекомендовал замечательную статью Джона Резига о Проблемах с подпикселями в CSS. В ней описано, как различные браузеры отображают элементы, ширина которых задана в процентах, и процесс обработки величин в подпикселях.
Джон объясняет, что при отображении в современном браузере 4-х элементов шириной 25%, содержащихся в контейнере шириной 50 пикселей, результирующая ширина элементов не будет равна 12.5 пикселям; многие браузеры округлят столбцы вверх или вниз — как удобнее для отображения. Опыт показывает, что Internet Explorer просто округлит дробные значения пикселей вверх, что нарушит раскладку.
Это не вызовет затруднений, если у вашей сетки достаточно широкие границы. Но такое поведение IE может стать причиной ненужного "обтекания" столбцов, заданных в процентах; в этом случае попробуйте уменьшить значение target на один пиксель. Например, если левый край оказался чересчур широким для IE (Internet Explorer), попытайтесь скорректировать расчеты:
124 ÷ 988 = 0.12551
установив параметр target равным 123 пикселям:
123 ÷ 988 = 0.12449
Задайте в таблице стилей для IE ширину 12.449% — это должно решить проблему.
Вышеизложенные советы, конечно же, являются только первым шагом: существуют миллионы других задач, с которыми приходится сталкиваться дизайнерам; большинство из них возникают при необходимости отобразить контент фиксированного размера (изображения, Flash и т.п.) в гибком фреймворке. Я реализовывал несколько экспериментальных вариантов в моем блоге, но уверен, что существуют и лучшие решения.
К тому же, я не утверждаю, что дизайн — гибкий или жесткий — это просто. Но вспоминая, чего мы добились за последние несколько лет — обход таблиц, пропаганда стандартов в наших компаниях и совместных проектах, выдвигаемые к создателям браузеров и коллегам требования по улучшению стандартов — мне хотелось бы, чтобы часть нашей изобретательности была направлена на избавление от "минимального разрешения экрана". В конце концов, пользователи не так постоянны в своих привычках, как предполагают разработчики. Надеюсь, что перспективы использования гибких сеток разбудили ваше воображение: я был бы рад увидеть, как вы совершенствуете мои приемы. Как и наши пользователи.
Как можно было догадаться из моих бессвязных воплей предисловия, я помешан на двух вещах: гибком веб-дизайне и, с недавних пор, хорошо структурированных сетках. Эти увлечения родились благодаря следующим книгам (список отнюдь не является исчерпывающим):
И еще один момент: в прошлом августе я читал доклад о гибких сетках, и в конце кто-то напомнил мне о системе Fluid 960 Grid System. Если вы уже используете открытый CSS-фреймворк, например, 960 Grid System, вас может заинтересовать гибкий "порт".
Комментарии