Написать пост

Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений

Аватарка пользователя Яна Лазарева

Рассказываем о свойстве float, разнице между флексами и гридами, об адаптивной и респонсивной вёрстке и методологиях вёрстки.

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

Поэтому поговорим о том, как начиналась веб-вёрстка, познакомимся с таблицами и свойством float, поговорим о том, как флексы боролись с гридами за внимание к себе и почему в этом нет никакого смысла, чем адаптивная вёрстка отличается от респонсивной, как различные методологии экономят драгоценное время разработчика и, наконец, какие практики стоит использовать при вёрстке.

Можно задаться вопросом: а зачем в принципе весь этот скучный исторический экскурс?

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

Табличная вёрстка

Вёрстка на таблицах, когда она впервые была представлена миру, стала неотъемлемой базой для большинства веб-страниц и использовалась в ситуациях, когда нужно было разбить страницу на структурные единицы — хедер, футер, блок с контентом и так далее. Безусловно, это выглядит лаконично, но, к сожалению, при таком решении позиционирование определяет html-структура, что уже не так привычно и очевидно. Например, рассмотрим такой код:

Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 1
Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 2

Это устаревший способ вёрстки: в нём легко запутаться, он выглядят громоздко и используется не по прямому назначению — для визуализации табличной информации. HTML-код в привычном понимании не должен стилизовать или позиционировать контент, он отвечает прежде всего за формирование структуры веб-страницы, которую впоследствии позиционируют правила стилей CSS.

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

«Обтекаемый» float

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

Свойство float решало проблему табличной вёрстки — структура html-документа оставалась линейной и воспринималась разработчиками как что-то естественное и более понятное.

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

Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 3
Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 4

Как мы видим, тег main имеет свойство float, что заставляет остальные теги «обтекать» его: информация в теге aside расположилась правее.

Блок footer также должен был встать правее main, но в его стилях содержится свойство clear со значением left, что отменяет любое обтекание им других блоков по левой стороне. Такой способ позволяет, например, выстраивать блоки по горизонтали, как это доступно в flexbox.

Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 5
Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 6

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

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

Противостояние Flexbox и Grid

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

Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 7
Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 8

Как мы видим, нет необходимости настраивать обтекаемость для блоков aside и восстанавливать расположение footer в нормальном потоке. Теперь header, main и footer идут друг за другом, а блоки aside располагаются по горизонтали внутри main, и их позиционирование никак не затрагивает остальные компоненты. Если добавить сюда свойства flexbox, которые отвечают за выравнивание, порядок, ориентацию и отступы дочерних элементов, получается довольно мощный инструмент, который оставляет разметку семантически простой и при этом не усложняет стили изменениями основного потока.

Другое значение display-свойства — grid — дало возможность настраивать двумерные сетки, представляя информацию в виде наборов строк и столбцов. Это бы мало чем отличалось от табличной вёрстки, если бы html-структура при этом не оставалась линейной, а разметка сеток не настраивалась через стили. Чтобы повторить предыдущий пример классической разметки, нужно добавить следующие стили:

Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 9
Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 10

Чтобы настроить сетку, помимо свойства display: grid у блока-контейнера, нужно задать размер и количество колонок и строк (свойства grid-template-column и grid-template-row), а также то, каким образом блоки их занимают (свойства grid-row и grid-column). Такие настройки позволяют адаптивно настраивать сетки, которые визуально подстраиваются под размер экрана, самостоятельно распределяя доступное пространство. Больше нет необходимости настраивать обтекаемость блоков; настройка сеток через задание их параметров легче поддерживается и масштабируется, а определение основного потока и обтекаемости становится интуитивно понятным.

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

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

Адаптив и респонсив — в чём отличия и что выбрать?

После того как смартфоны, планшеты и прочие гаджеты с доступом в Интернет прочно вошли в нашу жизнь, возникла проблема адаптивности сайтов и веб-приложений под мобильные устройства. Ведь помимо функциональности или внешних атрибутов приложение должно правильно работать на разных устройствах. Такую проблему решают два подхода — адаптивный веб-дизайн (Adaptive Web Design) и отзывчивый веб-дизайн (Responsive Web Design), которые для краткости называют соответственно адаптивом и респонсивом.

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

Респонсивный дизайн приложения использует механизм «резинового макета», гибкой страницы, элементы которой не имеют фиксированного размера (чаще всего задаются в процентах). То есть если размер страницы уменьшить в несколько раз, то её контент также пропорционально автоматически уменьшится. Например, чтобы добиться отзывчивого дизайна, используют медиавыражения (они же «медиазапросы» или media-queries), систему гибких сеток и изображений.

Например, рассмотрим пример медиазапросов, которые меняют стилизацию кнопки в зависимости от размера экрана.

Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 11

Просмотреть, как изменяется размер кнопки в зависимости от размера экрана, можно по данной ссылке.

В данном случае можно было бы воспользоваться свойством max-width в классе button. Но для наглядности в примере использован медиазапрос, который изменяет ширину кнопки, если ширина видимой части страницы меньше 500 пикселей. Конструкция @media screen and (max-width: 500px) проверяет, меньше или равна ширина viewport (видимая часть веб-страницы) 500, и если так и есть, применяются описанные CSS-стили.

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

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

Семантические теги и семантическая вёрстка — стоит ли заморачиваться?

После появления нового стандарта HTML5 появилась возможность при задании разметки сайта использовать новые теги — семантические. Вёрстка с использованием таких тегов также называется семантической. Самыми популярными среди них являются теги, определяющие основные части сайта, его смысловые разделы: например, header, footer, main, aside и так далее. Помимо крупных смысловых тегов можно выделить следующие группы:

  • мелкие смысловые элементы: параграфы (p), списки (ul, ol), формы (form), цитаты (blockquote) и так далее;
  • элементы заголовков для документа или разделов (h1, h2, …, h6);
  • фразовые элементы: изображения (img), кнопки (button), ссылки (a) и так далее.

Помимо структурных тегов существуют стилизующие теги, которые легко спутать с семантическими — например, теги i (курсивное начертание текста), b (выделение текста жирным шрифтом) или u (нижнее подчеркивание). Отличие в том, что они не несут смысловой нагрузки для поисковых систем и не добавляют смысла выделенному тексту.

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

Использование семантических тегов облегчает читаемость кода и навигацию по структурным элементам страницы. Например, код div class=»header» несколько сложнее в понимании, чем лаконичный тэг header.

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

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

Методологии веб-разработки — очередные правила или «разделяй и властвуй»?

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

● Повторяющийся код трудно отрефакторить, так как его удаление повлечёт за собой изменение в других участках кода.

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

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

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

● Блок — независимый компонент веб-приложения, который может быть переиспользован. Блок отражает смысл находящегося в нём контента, не влияет на окружение и одновременно не зависит от него. Допустим, если блок называется button, он должен содержать внутри только элементы кнопки (например, название блока red-button неверно, так как теперь отражает не только суть блока, но и то, как он выглядит). Также блок должен быть готов к переиспользованию: кнопку можно добавлять в разные части приложения, и это не должно сказываться ни на самой кнопке, ни на приложении.

● Элемент — зависимая часть блока (но не другого элемента), которая отражает смысл контента блока-родителя. Например, в блок button можно вложить элемент button__text (обратите внимание на нейминг).

● Модификатор — сущность, определяющая внешний вид, состояние или поведение элемента или блока. Его задача — добавлять особенности, которые отличают один элемент или блок от других. Например, если блок button в какой-то момент становится неактивным, к нему следует добавить модификатор button—disabled.

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

Рассмотрим пример, после которого всё станет немного понятнее.

Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 12

В данном примере был создан блок form, который содержит в себе элементы заголовка (form__title), поля текстового ввода (form__text-input) и кнопок (form__button). Наименование стилей элементов содержит название блока, в котором они содержатся (form), и самого элемента (через двойное подчёркивание). Таким образом, форму можно использовать повторно: стили блока никак не влияют на контекст, в котором он расположен.

Помимо элементов в примере используется модификатор для кнопки form__button—disabled. В нём будут прописаны стили, которые визуально делают кнопку недоступной. Можно создать множество других модификаторов, которые будут добавлять стили в зависимости от нового состояния элемента (например, form__button—small, чтобы сделать кнопку меньше, или form__button—outlined, чтобы добавить к ней обводку).

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

Почему же «разделяй и властвуй»? Потому что, разделив макет на отдельные части-блоки (формы, кнопки, заголовки, карточки и так далее), мы получаем чистую и строгую структуру. Не примени мы правила, код превратился бы в кашу из классов, использовать и поддерживать которую в дальнейшем было бы очень сложно и в какой-то степени «больно«.

Как же всё-таки сверстать макет правильно?

Итак, мы определились с основными понятиями и особенностями вёрстки. Осталось теперь разобраться с тем, как это применять на практике. Здесь не будет примера вёрстки полноценного макета, будет лишь несколько основных моментов, на которые хотелось бы обратить особое внимание.

Во-первых, перед вёрсткой нужно внимательно визуально просмотреть макет. Практически всегда он представляет собой набор вложенных друг в друга блоков. Некоторые из них можно переиспользовать — например, карточки или кнопки. Напрашивается мысль о применении какой-либо методологии — например, БЭМ, которую мы рассмотрели выше. Рассмотрим часть одного из макетов.

Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 13

Его можно разбить на две части — каталог с товарами и галерею с работами, — которые можно вынести в отдельные блоки. Каталог с товарами содержит набор однотипных блоков-карточек, содержащих элементы названий, цен, кнопок и так далее. Скорее всего, такие карточки будут повторяться и в других частях приложения, поэтому лучше вынести их в отдельный компонент. Галерея с работами — отдельный блок, содержащий блоки-изображения. Причём галерея — это сетка, которую лучше реализовать через Grid. Блоки-изображения одинаковы по структуре (картинка, подпись в синей рамочке), но в то же время отличаются формой, так как расположены по разные части сетки. Как их разграничить? Это можно сделать с помощью модификаторов из методологии БЭМ, которые будут задавать каждому отдельному блоку-изображению свои координаты в сетке.

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

Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 14

Пример

В данном примере мы к классу content добавили свойство margin, которое свойством auto располагает его ровно по центру body. Также через медиазапросы было задано «резиновое» значение ширины в процентах для мобильных устройств.

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

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

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

Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 15
Если вы умеете «покрасить кнопочку», но хотите узнать больше о вёрстке веб-приложений 16

Здесь помимо стилизации мы расположили элемент-заголовок в левом нижнем углу. Мы задали блоку gallery-element свойство position: relative, а элементу gallery-element__title то же свойство, но со значением absolute. Теперь заголовок располагается относительно блока-родителя в его системе координат, причём границы для заголовка — это границы карточки gallery-element.

Также блоку gallery-element было добавлено свойство display: inline-block, чтобы его размеры подстраивались под внутренний контент (картинку в нашем случае).

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

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

Вместо заключения ?

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

Веб-разработка
CSS
HTML
Гостевая публикация
2187