RSS

Гибкая сетка

Автор: Этан Маркотт

Оригинальная статья: A list Apart, 03/03/2009

Переводчик: Галина Касаткина

Translated with the permission of A List Apart Magazine and the author[s].

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

В последние годы такой подход встречается все чаще. Интерес к сеточному дизайну и применение его на веб-сайтах обрели второе дыхание благодаря Марку Боултону , Хою Винху и остальным . Ни капли не преувеличивая, можно утверждать, что идея оказалась более чем успешной: появились миллионы CSS-фреймворков, снабженных разнообразным инструментарием, предназначенным для того, чтобы среднестатитистический дизайнер мог легко освоить новый метод. Впрочем, почему бы и нет? Пятиминутных размышлений достаточно, чтобы признать преимущества использования сеток: дизайнеры получают возможность упорядочивать контент при помощи рационального и структурированного фреймворка, а пользователи наслаждаются четкими удобными сайтами.

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

Минимальное разрешение экрана: маленькая белая ложь

Вместо того, чтобы изучать преимущества гибкого веб-дизайна, мы прибегаем к маленькой хитрости: "минимальному разрешению экрана". Эти три слова имеют поистине магическую силу; под их прикрытием мы штампуем один жесткий дизайн за другим, переделывая их каждые пару лет в соответствии с новыми стандартами ширины - как только это становится достаточно безопасно. "Минимальное разрешение экрана" позволяет проектировать сайты для неких выдуманных пользователей, которые видят ваше творение в соответствии с замыслом Божьим и Фотошопа. У этих пользователей всегда установлено разрешение 1024×768, и они никогда не пользуются, например, ноутбуками OLPC , и не смотрят на мир через монитор, которому больше 4-х лет. Если пользователь не соответствует "минимальному разрешению экрану", ну что ж, для таких придумали полосу прокрутки, разве нет?

Конечно, во время написания сайта мне было не до гневных речей в адрес дизайна с фиксированной шириной страницы. Передо мной стояла другая проблема: мы разработали довольно сложную сетку для размещения всего требуемого контента, но клиент - и, как следствие, его пользователи - хотел получить гибкую сетку. На тот момент все знакомые мне сеточные дизайны были жесткими, поэтому вопрос встал ребром: как создать гибкую сетку?

Как оказалось, все зависит от контекста.

Неужели это заслуга IE?

Оказавшись лицом к лицу с непосильной задачей, я прибег к своей лучшей тактике: попытался ее избежать. Временно отложив вопрос о том, как заставить сетку меняться при изменении параметров страницы, я начал писать то, что знал: сначала стили для цветов и фона, затем для шрифтов.

Скорее всего, вы слышали о часто описываемой проблеме 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, вас может заинтересовать гибкий "порт".

Комментарии:

Вот так автор молодец, все прямо по полочкам разложил подробненько, спасибо!

Алеся

Поправьте, пожалуйста… Ethan Marcotte — это Итан Маркотт (двойную «т» тут даже можно опустить в принципе).

grand-hustler

И всё-таки от "минимального разрешения экрана" не помогает избавится даже гибкая вёрстка. Нельзя же ведь до бесконечности уменьшать ширину. При ширине экрана в 640 пикселей уже трёх-колоночная вёрстка выглядит убого, не говоря уж о 4 и более колонках, а виной всему размер шрифта, который конечно можно уменьшить но... появляется другая проблема. Разрешение экрана в 640 пикселей физически может быть как 15-30см так и 5-10 и при таких малых размерах шрифт становится слишком мелким.

Вывод: в любом случае определённой категорией пользователей придётся пожертвовать, главное чтобы эта категория пользователей была как можно меньшей.

AlexPh

Оставьте свой комментарий:

Подписаться на комментарии
Capcha