Хабрахабр

[Из песочницы] .container больше не нужен

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

Навигация:

  1. Немного о стандартном .container
  2. Минусы .container
  3. Работа с .container и медиа-запросами
  4. Замена .container одним css-свойством
  5. Комбинация с медиа-запросами
  6. Пример из реальной практики, сравнение методов
  7. Рекомендации
  8. Заключение

image

CSS:

.container { max-width: 1170px; margin: auto; height: 1000px;
}

Немного о стандартном .container

Изображение выше и код наглядно показывают как работает стандартный контейнер в типовой вёрстке сайта. Наверное все знают, что обычно создается тег section, в него помещается div.container и уже в него помещают различный контент. Он занимает всю ширину экрана, например, до 1170px и когда экран становится больше, то играет роль обёртки и фиксирует контент в центре страницы, не давая ему «разбежаться» в стороны.

Если задать эти стили для секции без контейнера, то вроде бы всё смотрится нормально. Так почему бы сразу не задать эти стили для контента?

image

HTML:

<section class="main-section"> <h1 class="main-title">Заголовок страницы</h1> <p class="main-subtitle">Lorem ipsum dolor.</p> <div class="cards"> ... </div>
</section>

Но как только требуется задать фон для секции, ситуация сразу выходит из под контроля:

image

Если задать для секции фон, внутрь секции положить контейнер с его стилями, а в него уже контент, то всё заработает так, как надо:

image

HTML:

<section class="main-section"> <div class="container"> <h1 class="main-title">Заголовок страницы</h1> <p class="main-subtitle">Lorem ipsum dolor.</p> <div class="cards"> ... </div> </div>
</section>

Минусы .container

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

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

Но если на сайте 15 секций или больше? Выше мы рассмотрели самый простой пример. А если нам внутри контейнера нужно разделить секцию еще на две части и сделать их flex-элементами? Это 15 лишних блоков. И уже +2 лишних блока на секцию! Нужно создать div-обёртку, это еще по одному блоку в контейнер. Но возможности css позволяют нам обойтись и без них. Как я уже сказал выше — эти div'ные вложенности «мусорят» в разметке.

Работа с .container и медиа-запросами

Я не так давно в веб-разработке, но уже нашел способ адекватно работать с контейнером и в итоге вообще избавился от него. Я так понимаю .container «родился» в bootstrap и теперь его используют абсолютно везде.

Взяв за основу сетку bootstrap можно значительно упростить себе работу с css медиа-запросами, используя следующий код:

CSS:

.container { padding: 0 15px;
} @media (min-width: 575.98px)
} @media (min-width: 767.98px){ .container { max-width: 720px; }
} @media (min-width: 991.98px) { .container { max-width: 960px; }
} @media (min-width: 1199.98px){ .container { max-width: 1140px; }
}

Что он делает? Если кратко, то держит контент всегда в центре и меняет его размеры на разных экранах:

  1. На экранах до 576px контент растягивается, но боковые отступы в 15px сохраняются.
  2. На экранах от 576px до 768px контент находится в центре и его ширина 540px.
  3. На экранах от 768px до 992px контент в центре и его ширина 720px.
  4. На экранах от 992px до 1200px контент в центре и его ширина 960px.
  5. На экранах от 1200px контент в центре с шириной 1140px.

Такая система сетки даёт явные преимущества:

  1. У нас есть 4 четких медиа-запроса: для больших экранов, для средних экранов, для маленьких экранов, для планшетов.
  2. имеем всего один небольшой промежуток от 320px до 576px, который нужно адаптировать как бы «вручную» — уменьшая по 1px ширины контента.

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

На рисунке ниже изображена работа .container в связке с медиа-запросами, которые я подсмотрел у bootstrap.

image

Замена .container одним css-свойством

Наконец-то мы подошли к самому интересному. Так как же заменить .container? Для начала разберемся что нам нужно сделать. Нам нужно две вещи:

  1. Чтобы контент был фиксированной ширины, например 1180px и не разбегался в стороны.
  2. Чтобы при этом можно было задать цвет или фон для всей секции.

Что может отодвинуть контент в центр секции и при этом фон останется везде внутри? Ответ оказался прост: задаём для секции внутренние отступы — padding. Но padding не простой. Но для примера давайте сначала попробуем задать простой padding.

Смотрим: Допустим нам нужна ширина контента 1180px, значит 1920 — 1180 = 740 / 2 = 370px — будут боковые отступы в нашей секции.

HTML:

<section> <div class="content"> content </div>
</section>

CSS:

section { background-color: pink; height: 1000px; padding: 0 370px;
}

image

При уменьшении экрана, наши отступы сжимают контент. Да уж. Может возможно сделать отступы динамическими? Не годится. И ресурсами одного лишь css! Возможно!

На данный момент css-функция calc() поддерживается на 96. Для этого воспользуемся функцией calc(). Для динамических внутренних отступов нужно выполнить одну математическую операцию. 5%, что всего на 1% меньше, чем flexbox, а это значит, что её можно смело использовать.

Давайте уже скорее посмотрим на пример:

image

Без всяких дополнительных блоков наша секция ведёт себя ровно так же, как с .container. Мне нравится! И это всего лишь одно css-свойство: С уменьшением экрана уменьшаются padding, а контент остается фиксированным по ширине.

CSS:

section { padding: 0 calc(50% - 590px);
}

UPD: Упросил формулу. Спасибо Metotron0.
Таким образом мы задаём боковые внутренние отступы с помощью функции calc(), которая при любом разрешении экрана высчитывает эти отступы так, чтобы контент был 1180px! Вы только попробуйте.

Можно поиграться с корректирующим значением 590px и сделать контент 1140px или 1170px, как угодно!

Посмотрите сравнение этого метода с контейнером прямо сейчас!

Комбинация с медиа-запросами

Было бы очень хорошо встроить это в сетку от bootstrap, чтобы легче было адаптировать сайт.

Давайте попробуем:

CSS:

section{ padding: 0 15px;
} @media (min-width: 575.98px){ section { padding: 0 calc(50% + 270px); }
} @media (min-width: 767.98px){ section { padding: 0 calc(50% + 360px); }
} @media (min-width: 991.98px) { section { padding: 0 calc(50% + 480px); }
} @media (min-width: 1199.98px){ section { padding: 0 calc(50% + 590px); }
}

Результат:

image

Итого на разных размерах экранов мы имеем:

  1. от 320px до 576px авто ширину контента и фиксированные отступы 15px.
  2. от 576px до 768px ширину 540px и динамические отступы.
  3. от 768px до 992px ширину 720px и динамические отступы.
  4. от 992px до 1200px ширину 960px и динамические отступы.
  5. от 1200px ширину 1180px и динамические отступы.

Это же абсолютно тоже самое, что и с div.container! Только без лишних блоков.

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

Всё еще не видите пользы от метода с динамическими отступами? Тогда давайте взглянем на пример из реальной практики. Надевайте очки разработчика — есть следующая секция (кликабельно):

Есть секция, в ней два отдельных блока, чтобы разбросать их по сторонам, хорошо бы задать для секции display: flex и jcsb. Какие мысли? Разве это удобно? Но если использовать .container, то придётся оборачивать два этих блока в ещё один и ему уже задавать df. Пробуем:

HTML:

<section class="brif-section"> <div class="container"> <div class="brif-wrapper"> <div class="brif-text-block"> .... </div> <form action="#" class="brif-form"> .... </form> </div> </div>
</section>

CSS:

.brif-section { background: background;
} .container { max-width: 1180px; margin: auto;
} .brif-wrapper { display: flex; justify-content: space-between;
}

А теперь посмотрите как это выглядит если использовать динамические отступы:

HTML:

<section class="brif-section"> <div class="brif-text-block"> .... </div> <form action="#" class="brif-form"> .... </form>
</section>

CSS:

.brif-section { display: flex; justify-content: space-between; padding: 0 calc(50% + 590px); background: background;
}

Только посмотрите как уменьшился код, он стал чище, читать его стало легче. Получилась секция, которая содержит блок с текстом и форму — ничего лишнего! И это всего лишь одна секция. Повторюсь: а если на сайте 15 секций?

Итак, начинаем подводить итоги:

Плюсы .container:,

  • Контент зафиксирован в центре и имеет нужную ширину.
  • Можно задать нужный фон для всей секции.

Минусы .container:

  • Он является дополнительным div.
  • Иногда нужно создавать еще один дополнительный div.
  • Код «раздувается» и труднее читается.
  • Иногда нужно задавать фон для секции, а другие стили для блока-обёртки.
  • Нужно придумывать какой-то класс для блока-обёртки.

Плюсы padding (относительно .container):

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

Минусы padding:

  • Нужно для секций задавать padding-top и padding-bottom отдельными свойствами.

То есть не:

section { padding: 50px 0;
}

А вот так:

section { padding-top: 50px; padding-bottom: 50px;
}

Иначе они перезапишут динамические отступы.

Рекомендации

Мне нравится метод с динамическими внутренними отступами. Попробуйте его вместо привычной «контейнерной» вёрстки и вы быстро заметите как повысилась чистота вашего кода. Если есть какие-то сомнения в этом методе, то пишите их в комментарии — обсудим!

Чтобы ширина считалась не от родителя, а от ширины области промотора браузера. Рекомендую использовать не %, а vw. Поддержка vw — 96% тут. Так просто надёжнее.

CSS:

section { padding: 0 calc(50vw + 590px);
}

Создайте свой шаблон этих стилей с медиа-запросами, например:

section, header, footer { padding: 0 15px;
} @media (min-width: 575.98px){ section, header, footer { padding: 0 calc(50vw + 270px); }
} @media (min-width: 767.98px){ section, header, footer { padding: 0 calc(50vw + 360px); }
} @media (min-width: 991.98px) { section, header, footer { padding: 0 calc(50vw + 480px); }
} @media (min-width: 1199.98px){ section, header, footer { padding: 0 calc(50vw + 590px); }
}

Заключение

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

Просто начните применять этот метод и в скором времени вы почувствуете некоторое облегчение. Не бойтесь чего-то нового. Используйте css на полную катушку!

S. P. Будем разбираться. Если во время использования этого метода всплывут какие-то подводные камни — опишите их в комментариях!

Теги
Показать больше

Похожие статьи

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

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

Кнопка «Наверх»
Закрыть