CSS-live.ru

Лучший способ реализовать «обёртки» в CSS

Перевод статьи The Best Way to Implement a “Wrapper” in CSS с сайта css-tricks.com для CSS-live.ru, автор — Калоян Косев

Иногда первое, что мы пишем на странице — это элемент, оборачивающий всё остальное на странице. Термин «Обёртка» типичен для этого. Мы задаём ему класс, отвечающий за инкапсуляцию всех визуальных элементов на странице.

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

Перед тем, как пойти дальше, сначала рассмотрим разницу между «обёрткой» (wrapper) и «контейнером» (container).

«Обёртка» против «Контейнера»

Я вижу разницу между элементом-обёрткой и элементом-контейнером.

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

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

Обёртка ассоциируется с <div>, который содержит весь остальной HTML в документе. Уверен, что многие помнят то время, когда мы устанавливали для <div> ширину 960px и центрировали основной контент. Обёртки так же были полезны, чтобы прижать футер.

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

Термины «Обёртка» и «Контейнер» также могут означать одно и то же в зависимости от разработчика и его целей. Могут быть и другие соглашения, так что лучший совет, как правило — делать так, как вам самим логичнее. Но помните, что наименование — одна из наиглавнейших фундаментальных вещей в практике разработчика. Система наименования делает код читабельнее и предсказуемее. Выбирайте тщательнее!

Вот пример общей обёртки страницы:

/**
 * 1. Центрируем содержимое. Да, это немножко вкусовщина.
 * 2. См. раздел «width против max-width»
 * 3. См. раздел «Дополнительные внутренние отступы»
 */
.wrapper {
  margin-right: auto; /* 1 */
  margin-left:  auto; /* 1 */

  max-width: 960px; /* 2 */

  padding-right: 10px; /* 3 */
  padding-left:  10px; /* 3 */
}

width против max-width

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

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

See the Pen CSS-Tricks: The Best Way to Implement a CSS Wrapper by Максим (@psywalker) on CodePen.

С точки зрения отзывчивости max-width лучший выбор!

Дополнительные внутренние отступы

Я видел, как многие разработчики забывали один граничный случай. Допустим, есть обёртка с max-width: 980px. Этот граничный случай проявляется при экране устройства 980px. Поэтому, её содержимое прилипнет точно к краям экрана, не оставляя «воздуха».

photogallery

Эта проблема нехватки «воздуха»

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

.wrapper {
  max-width: 960px; /* на 20px меньше, чтобы уместить отступы по краям. */

  padding-right: 10px;
  padding-left: 10px;

  /* ...  */
}

Вот почему добавление padding-left и padding-right к обёртке будет хорошей идеей, особенно на мобильных устройствах.

Или подумайте о box-sizing, чтобы отступы вообще не влияли на общую ширину.

Какой HTML-элемент выбрать

У обёртки нет семантики. В ней просто находятся все визуальные элементы и контент на странице. Он всего лишь просто контейнер. С точки зрения семантики, <div> — лучший выбор. У <div> тоже нет семантического значения, это просто контейнер

Невольно возникает вопрос, а может ли для этой цели подойти элемент <section>. Однако, спецификация W3C говорит вот что:

Элемент <section> не замена общему элементу-контейнеру. Если элемент нужен чисто для оформительских целей или как вспомогательное средство для скриптов, то рекомендуется использовать <div>. Общее правило таково: элемент раздела подходит в случае, когда содержимое элемента явно указано в схеме документа.

Элемент <section> несёт в себе собственную семантику. Он подходит для тематической группировки контента. В каждом разделе должен быть заголовок (элемент h1-h6) в качестве дочернего элемента (прим. перев.: это не строгое правило, но крайне желательно соблюдать его).

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

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

Тег <body> против дополнительного <div>

Следует отметить, что в качестве обёртки иногда может подойти <body>. Вот такая реализация отлично работает:

body {
  margin-right: auto;
  margin-left:  auto;
  max-width: 960px;
  padding-right: 10px;
  padding-left:  10px;
}

И в результате у вас в разметке будет одним элементом меньше, поскольку удалён ненужный обёрточный <div>.

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

  • Вам нужно «прибить» футер к концу документа (к низу окна, если документ короткий). И если даже воспользоваться flexbox в качестве современного способа, всё равно не обойтись без обёрточного <div> (прим. перев.: на самом деле можно задать display: flex самому body, тем более в примере по ссылке так и сделано).
  • Вам требуется установить background-color целой странице. Поскольку у body есть max-width, то его нельзя использовать. Но тогда можно установить фон тегу <html>. Но тут я сомневаюсь. После прочтения статьи HTML vs Body in CSS это звучит для меня немного необычно. Однако, я не слышал каких-то проблем или трудностей с применением цвета фона для элемента <html>. Но это по-прежнему звучит немного странно, да? (Прим. перев.: проблема с фоновым цветом преувеличена, поскольку по стандарту CSS любой фон, указанный для <body>, и так применяется ко всему <html>, если тому явно не задан собственный фон. Но могут быть другие проблемы, например, со сторонними скриптами, позиционирующими всплывающие окна и т.п. именно относительно <body>)

Лично я склоняюсь к тому, что для реализации обёртки всё же лучше использовать дополнительный <div>. Таким образом, если требования спецификации позже изменятся, то потом не придётся добавлять обёртку и переписывать стили. В конце концов, речь же об одном-единственном добавочном DOM-элементе.

P.S. Это тоже может быть интересно:

4 комментария

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

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

    1. Вот не надо, пожалуйста, слои предлагать! Уже «раскладки» хватает =). Как раз обертка и контейнер по смыслу понятнее (хотя это все субъективно). Я бы даже сказал что это то же самое. Просто обычно бывает либо просто wrapper как вспомогательный элемент, либо wrapper-container, т.к сходные по смыслу элементы обычно всегда группируются.

      1. Как я уже сказал, во всех языках, слово контейнер означает хранилище, в человеческом понимании — коробка. Если Вы закрасили коробку, вложенности не видно. Но в css это не так. Поэтому слово контейнер не подходит логически для стилей. Скажите, если я Вам покажу свой iphone обернутый в газету, Вы сможете сказать какого он цвета? А если я квадрат оберну в контейнер или обертку, Вы сможете сказать какого он цвета?

  2. Контейнер может быть пластиковый, а вместо газеты быть полиэтиленовая пленка.
    Я согласен, что коробка — это контейнер, а обертка — враппер. Я просто хотел сказать, что мы изначально имеем кучу вещей и раскладываем их по нескольким коробкам и у нас оказывается, допустим 3 коробки. Для одной из них, внезапно, нам понадобилась обертка (газета), так как цвет не подошел и пр. Но у нас нет вещей без коробки, если это не единственная вещь.
    Т.е в этом плане коробка служит для объединения вещей по смыслу, а обертка как вспомогательный элемент для оформления. (Блок в БЭМ, например. А обертка это вспомогательный блок (wrapper))
    Это субъективное мнение. Для меня разница как между и , примерно.

    Термин слои часто употребляется в контексте z-index, отрисовки в бразере.

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

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

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