Отзывчивые сеточные системы. Являются ли они решением?

Перевод статьи: Responsive grid systems; a solution?
Автор:  Harry Roberts.

Сеточные системы, так называемые сетки, являются самой актуальной темой в сфере отзывчивого дизайна. Множество людей пытаются освоить их, но как мне кажется, мы еще достаточно далеки от цели.

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

Прежде чем начать знакомство с фреймворком, давайте вкратце коснемся некоторых проблем и требований, с которыми мы сталкиваемся в процессе работы с отзывчивыми сеточными системами:

  • Для различных доступных размеров должны быть предусмотрены разные варианты компоновки. Так, к примеру, вам нужно позаботиться о том, чтобы определенная колонка занимала всю ширину рабочей области на устройствах с узким экраном и половину ее ширины при отображении на более широких экранах.
  • Размеры компонентов макета должны гибко подстраиваться под размеры экрана, находящиеся между контрольными точками, так как нам нужно охватить все платформы.
  • Необходимо обеспечить достаточный контроль выбора участвующих в процессе трансформации колонок и при достижении каких контрольных точек это должно происходить. Так, допустим, такое безоговорочное правило как «все колонки в половину ширины при достижении определенной контрольной точки должны разворачиваться в полную ширину» не эффективно, так как в определенный момент нам может понадобиться развернуть лишь некоторые из колонок, а остальные оставить без изменений, т.е. в половину ширины экрана.
  • Используемые классы должны быть идеально адаптированы под любой вариант макета, активируемый по достижении определенной контрольной точки. То есть, допустим, класс .span-6 будет вводить в заблуждение после того как он, при сужении экрана будет выполнять функции, свойственные классу с именем .span-12 (*Здесь имеется в виду, что класс .span-6 устанавливает ширину колонки равной шести единицам сеточной системы, т.е. половины из 12-ти доступных, а класс .span-12 в полную ширину, т.е. с участием всех 12-ти единиц сеточной системы).

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

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

Если вы используете SASS, то неплохо было-бы сделать нечто подобное:

.content{
@extend .span-12;
@media screen and (min-width:720px){
@extend .span-6;
}
@media screen and (min-width:1200px){
@extend .span-8;
}
}

Хотя в этом случае вы, конечно же, не сможете применять директивы @extend  для наследования свойств других селекторов, находящихся в рамках различных медиа запросов (*Если селектор определен в рамках одного из медиа запросов, то расширять соответствующий ему набор свойств с помощью директивы @extend можно только внутри того же блока медиа запроса, а из других блоков такие действия будут невозможны).

Почему же мы сталкиваемся с подобными трудностями?

Делаем выводы.

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

Если переформулировать нашу проблему на более простом языке, то в результате она будет выглядеть следующим образом:

Я хочу, чтобы при достижении дизайном определенных контрольных точек элементы приобретали различные, противоречивые формы.

В принципе, все, что нам нужно, так это чтобы одна сущность (колонка сеточной модели) выступала в роли нескольких сущностей (принимая различные значения ширины) при различных состояниях (контрольных точках).

Простейший способ заставить сущность выглядеть и вести себя по-разному – просто привязать к ней несколько стилей (то есть классов). Иными словами, для того чтобы адаптировать поведение одного интересующего нас объекта под различные ситуации (к тому же противоположные — помните, что сетка не может быть в двух состояниях одновременно: в полную ширину и занимать лишь ее половину), нужно для каждой из них создать отдельный класс.

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

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

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

Истинные HTML пуристы, прошу вас, доверьтесь мне!

Создание сеточной системы.

В целях борьбы с неподходящими именами классов типа .span-12, мы должны рассмотреть вариант применения таких классов как .one-whole, .three-fifths, .five-twelfths  (*.одна-целая, .три-пятых, .пять-двенадцатых ширины экрана) и им подобных. А это означает, что если ранее имя класса сообщало нам о совмещении X колонок, то теперь мы говорим о заполнении X процентов доступной ширины экрана.

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

<img src="foo.jpg" alt="" class="one-half">

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

Из этого следует, что архитектура сетки сама по себе очень легкая и содержит всего лишь несколько плавающих и пару отменяющих обтекание элементов, а также некоторые, образующие промежуточные пространства элементы. (*Наглядно стержень структуры можно увидеть в примере на ресурсе jsFiddle.net.)

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

Но у нас все еще есть проблема, заключающаяся в том, что класс с именем .one-half (*одна-вторая) теряет свой смысл в том случае, если при достижении некоторой контрольной точки мы хотим применить его как .one-whole (*одна-целая)…

Определение контрольных точек.

Секрет безупречности высокоуровневой компоновки страницы (то есть сеточной системы) заключается в том, что она производится исходя из размеров устройства/экрана/вьюпорта.

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

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

  • Palm — все то, что умещается у нас на ладони (устройства, подобные телефонам);
  • Lap — устройства, не являющиеся КПК, а находящиеся в следующей весовой категории или «наколенные» устройства (подобные планшетам);
  • Portable — под эту категорию попадают оба упомянутых выше типа устройств;
  • Desk — стационарные устройства (такие как телевизоры, настольные компьютеры и им подобные).

Допуская такое обобщение, мы тем самым можем создать несколько классов ширины таких как .one-half, .palm-one-half, определенных в рамках блоков медиа запросов:

/**
* Устройства категории Palm
*/
@media screen and (min-width:[выбранное вами значение ширины]){
.palm-one-whole{
width:100%;
}

}

/**
* Устройства категории Lap
*/
@media screen and (min-width:[выбранное вами значение ширины]){
.lap-one-whole{
width:100%;
}

}

И так далее…

Теперь мы имеем ряд классов, которые нужны лишь для выполнения отдельных функций при достижении определенных размеров экрана, привязанных к целевым устройствам:

<div class="one-whole lap-three-fifths desk-one-half">
Имейте ввиду: по праву считается (и вполне справедливо), что совсем не нужно привязывать медиа запросы к размерам устройств, а основываться при этом на том, «что выглядит лучше». В большинстве случаев это правило справедливо, но, тем не менее, нужно мыслить прагматично. Если нам необходимо создать действительно гибкую, многоразовую и эффективную сеточную систему, то нам не обойтись без абсолютных понятий.

Поскольку мы делаем сеточную систему, которая должна определенным образом реагировать на события достижения контрольных точек, то очень важно учитывать следующие моменты:

  1. Убедитесь в том, что используемые вами значения для контрольных точек не привязаны жестко к размерам реальных устройств (например, iPhone в вертикальной ориентации), а отталкиваются от наиболее подходящих значений, при которых макет сайта выглядит наилучшим образом.
  2. Позаботьтесь о том, чтобы ваша сеточная система сохраняла свою гибкость даже между фиксированными контрольными точками, таким образом, что если не происходит переформатирование макета сайта, то производится как минимум изменение размеров его компонентов.

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

Множество CSS классов.

Проблема, как вы возможно уже заметили, заключается в том, что сейчас мы создаем практически отдельную сеточную систему для каждой конкретной, определенной нами контрольной точки. И теперь уже не существует просто классов типа .one-whole, .one-half, .one-quarter и т.д., а в рамках каждого, предусмотренного нами блока медиа запроса мы имеем каждый из этих классов. На первый взгляд все выглядит очень сложно.

Имея такую повторяющуюся структуру классов можно добиться максимального сжатия кода. Мы прекрасно понимаем важность сжатия открытых текстовых фрагментов, что в нашей ситуации особо актуально. Gzip сжатие наилучшим образом работает с повторяющимися текстовыми строками, то есть чем больше повторяющихся фрагментов кода вы имеете, тем больше коэффициент сжатия получите в результате. Хотя с другой стороны повторение кода, это плохой признак (как правило, усложняющий процесс обслуживания кода, снижающий его эффективность и вызывающий другие проблемы), но с точки зрения его компрессии дает положительный результат. В ходе экспериментов по сжатию классов, определяющих настройки ширины элементов, рассматриваемых в данной статье, мне удалось добиться их сжатия до значения 81%. Что, в общем-то, говорит о том, что результирующий размер сжатого кода классов на самом деле меньше чем пятая доля его общего оригинального объема, передаваемого по сети. Другими словами пять отдельных классов, соответствующих пяти переходным точкам, сжатых до объема меньшего, чем один не сжатый класс, вполне оправдывают такой подход.

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

Реализация.

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

<div class="content one-whole desk-three-quarters">

</div>
<div class="sub-content one-whole desk-one-quarter">

</div>

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

Что мы имеем в результате?

Что ж, для того, чтобы убедится в правильности выбранного пути, давайте еще раз остановимся на результатах наших действий…

  • У нас есть ряд контрольных точек, позволяющих классифицировать устройства пользователя (мобильные, настольные и т.д.).
  • Каждый блок медиа запроса, соответствующий определенной контрольной точке содержит свойственные ей классы ширины (к примеру, .desk-one-tenth, .palm-two-thirds и т.п.).
  • У нас есть возможность использовать эти классы в нашем HTML коде, зная при этом, что они будут работать только при условиях, удовлетворяющих ограничениям медиа запроса, в которых они определяются.

Множество имен классов в HTML коде.

Многие люди вздрагивают при мысли о том, с каким количеством классов придется сталкиваться в исходном HTML коде документа, но не все так ужасно…

Хотя мы не можем расширять классы с помощью свойства @extend за пределами блоков медиа запросов, мы можем это делать не выходя за их рамки.

Это означает, что вместо такой вот конструкции:

<div class="content one-whole desk-three-quarters">

вы можете использовать следующий фрагмент SASS кода:

.content{
@extend .one-whole;
@extend .desk-three-quarters;
}

Еще более благоприятная ситуация складывается, если в своем коде вы используете предусмотренные в SASS silent классы (*так называемые «тихие классы», не включаемые в стили до тех пор, пока они не будут активированы с помощью декларации @extend):

.content{
@extend %one-whole;
@extend %desk-three-quarters;
}

Это означает, что указанные таким образом классы не будут задействованы в CSS коде и у вас нет необходимости указывать их в HTML разметке. Таким образом, если вы используете SASS и предусмотренные в нем silent классы, то у вас в распоряжении будет класс, выполняющий необходимое форматирование для каждой контрольной точки, но при этом он не будет создан до тех пор, пока в нем реально не возникнет необходимость. То есть он создается только при достижении определенных условий (*ширины, привязанной к соответствующей контрольной точке).

Заключение.

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

Все это было реализовано мной в рамках собственной микро библиотеки под названием csswizardry-grids, которая всегда к вашим услугам и вы можете попробовать ее на практике.

* Примечание переводчика.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *