Сохранение иерархии контента с помощью хореографии

Сохранение иерархии контента по мере того как меняется размер и расположение элементов на экране — одна из проблем отзывчивого дизайна, которая заслуживает особого внимания. Первым о ней заговорил Трэнт Уолтон (Trent Walton) в своей статье «Хореография контента», в которой он показал как по мере смещения колонок друг под друга теряется визуальная иерархия.

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

Что такое хореография контента?

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

Схема

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

Когда количество колонок сокращается до одной, последовательность контента зависит от исходной последовательности блоков с контентом в разметке HTML. Колонка, которая идет первой в HTML, отображается самой верхней; колонка, идущая следом, располагается сразу под ней, и так дальше.

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

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

Примеры

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

Левая часть рисунка демонстрирует типичное смещение колонок. По мере уменьшения количества колонок в макете до одной, контент в каждом контейнере или колонке смещается под весь контент другого контейнера.

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

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

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

Две проблемы в одной

На самом деле мы имеем дело с двумя проблемами:

В одноколоночном макете блоки контента располагаются в том же порядке что и в HTML. К сожалению, последовательность контента, идеальная для одного варианта макета, может не подойти для другого.

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

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

Попробуем разобраться с проблемой последовательности контента в коде

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

Вот три спецификации которые мы скорее всего будем использовать в скором времени:

Вторая и третья спецификации почти не поддерживаются современными браузерами. Невероятно, но Internet Explorer является самым прогрессивным в этом плане. IE 10 поддерживает области и сеточные макеты с указанием вендорного префикса -ms. Никакие другие браузеры их не поддерживают, так что прежде чем использовать эти спецификации придется подождать.

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

Opera mini и IE старше 10-ой версии не поддерживают ни один из синтаксисов flexbox. Но чтобы обеспечить поддержку в IE можно использовать полифил Flexie. Flexie использует старый синтаксис flexbox, но он обеспечивает поддержку IE вплоть до 6 версии. Для того чтобы подробно описать flexbox потребуется целая статья, так что я укажу ссылки на статьи которые я написал о старом синтаксисе и новом синтаксисе, а также на статью с подробным объяснением как использовать новый синтаксис для создания отзывчивого макета, в которой предложено решение проблемы с исходной последовательностью контента в коде.

Говоря в общем, с помощью одного свойства CSS можно задать порядок блоков, отличный от того в котором они идут в HTML. Джордан Мур (Jordan Moore) также писал о flexbox и хореографии контента и даже создал демо.

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

Решение проблемы перемешивания контента

В отличии от проблемы исходной последовательности, для перемешивания контента разных колонок нет технического решения. Решение зависит от нас и, в конечном счёте, нам придется отказаться от оборачивания контента в большое количество HTML-контейнеров.

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

Модели визуального форматирования в CSS

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

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

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

С помощью некоторых размышлений и CSS, вам наверняка удастся найти способ перегруппировать элементы внутри контейнеры так, как вам хочется. Подумав еще немного, вы даже можете сделать так, чтобы элементы размещенные в одном контейнере казались размещенными в другом контейнере, для этого вам вероятно понадобится применить более сложный CSS и то, что Гарри Робертс (Harry Roberts) называет «магическими числами».

Если это новый термин для вас, магические числа - это числа которые мы применяем чтобы заставить что-то работать в конкретной ситуации. Они обычно перестают работать как только меняется какое-то соседнее значение, а соседние значения меняются постоянно в силу природы отзывчивого дизайна. Магических чисел в CSS лучше избегать.

Нам нужно отказаться от контейнеров-обёрток

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

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

Другими словами, вместо этого…

<div id="container">
  <div>Content here</div>
  <div>Content here</div>
  <div>Content here</div>
</div>

… нам нужно делать так:

<div class="container">Content here</div>
<div class="container">Content here</div>
<div class="container">Content here</div>

Каждому контейнеру можно присвоить соответствующий класс и даже не один. Это предоставляет бóльшую гибкость при их перегруппировке. В первом же примере контейнеры всегда будут ограничены своим родителем.

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

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

Примеры

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

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

Личный пример

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

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

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

Скриншот

Мой сайт когда ширина окна браузера позволяет вместить две колонки

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

Ниже вы видите ту же страницу в одноколоночном представлении на более узком экране. Метаинформация переместилась из левой колонки под заглавие статьи в правой колонке, но над всем остальным содержимым правой колонки. Обе «колонки» на самом деле все это время находились в общем контейнере.

Скриншот2

Мой веб-сайт в одноколоночном представлении на более узком экране

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

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

Схема2

Более абстрактный взгляд на происходящее.

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

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

Веб-сайт The Next Web

На The Next Web колонки в основном смещаются вниз в процессе перехода от трех колонок к одной, однако некоторые элементы в верхней части страницы все же перемешиваются.

Скриншот3

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

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

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

Веб-сайт Time

На сайте журнала Time перемешивается контент из разных колонок и контейнеров. Обратите внимание что раздел «Latest Headlines» (в зеленом контейнере) при переходе к одной колонке перемещается из верхней части правой колонки прямо под главную иллюстрацию и ссылки в статье.

Скриншот4

Хоть этого и не видно на изображении выше, ряд из четырех изображений справа следует за «Latest Headlines» в одноколоночном представлении. Остальной контент из правой колонки смещается далеко вниз. На это можно посмотреть прямо на их сайте.

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

Сайт ресторана Enoch’s Fish & Chips

Навигация на сайте ресторана Enoch’s Fish & Chips соединена с логотипом и описанием ресторана в одноколоночном макете:

Скриншот5

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

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

Скриншот6

Подведем итог

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

При необходимости сохранения иерархии мы сталкиваемся с двумя проблемами. Первая - сохранение исходной последовательности, прописанной в HTML, при переходе на одноколоночное представление. Решение этой проблемы чисто техническое и скоро будет доступно нам в виде новых спецификаций CSS, которые позволяют последовательности отображения элементов отличаться от их исходной последовательности, заданной в HTML.

Вторая проблема менее технична и для ее решения нужно задуматься над организацией HTML и в особенности над тем, как мы используем контейнеры. Элементы не могут перемещаться из одного контейнера в другой. Эту проблему можно обойти используя сложный CSS, или же можно использовать JavaScript для внесения изменений в DOM; однако в конечном счёте если нам нужна возможность перемешивать элементы, лучше использовать меньшее количество HTML-контейнеров для создания колонок. Вместо дополнительных контейнеров-обёрток лучше использовать CSS для создания виртуальных колонок.

Это решение не ограничивает наши элементы структурными контейнерами и позволяет проще перемещать элементы в разных макетах.