В наши дни есть основа для всего, и кажется, что прежде чем мы сможем даже переварить один, выпускается еще один. Это особенно верно, когда речь идет о макетах CSS-сетки, и нет недостатка в фреймворках, которые считаются «лучшими, самыми легкими на сегодняшний день». Эта передозировка информации может сбить нас с толку и заставить нас задуматься о том, действительно ли фреймворки, такие как HTML9 Responsive Boilerstrap JS , действительно подходят.
Давайте сделаем шаг назад, немного вздохнем и зададимся вопросом: действительно ли мы будем использовать каждый из этих 24 вариантов и миллион подвариантов, с которыми поставляется «Тот Великий каркас»? Часто нам нужно только простое гибкое решение с несколькими вариантами для работы в нашем проекте, и с сильным знанием основ мы можем расширять его по своему усмотрению. Я собираюсь представить четыре различных метода для разработки вашей собственной сетки CSS, и каждый из них легко расширяется. Вот четыре метода:
- Адаптивный макет сетки, v1 (с использованием отрицательных полей)
- Адаптивный макет сетки, v2 (с использованием
box-sizing: border-box
- Адаптивный макет сетки с использованием отображения таблицы
- Адаптивное расположение сетки с использованием flexbox
Я собираюсь упростить эти методы, используя минимальное количество простого и понятного CSS. Демонстрация CodePen будет предоставляться с каждым примером, так что вы можете раскошелиться и / или поиграть с CSS в демоверсиях. Давайте погрузимся в.
Примечание: я включил встроенные демонстрации для каждого, но для того, чтобы увидеть полную адаптивность каждого метода, лучше всего просмотреть демонстрации CodePen в полноэкранном режиме, нажав ссылку «Изменить на CodePen» в верхней части каждой демонстрации.
Общий CSS
Прежде чем мы углубимся в каждый метод, давайте рассмотрим некоторые распространенные CSS, которые мы будем использовать. Мы будем использовать объявление box-sizing: border-box
.clearfix
очистки чисел с плавающей точкой . Вот наш базовый CSS:
/* resets */
*,
*:before,
*:after {
box-sizing: border-box;
}
.clearfix:after {
content: "";
display: table;
clear: both;
}
В случае, если нужны какие-либо префиксы от поставщиков, мы будем использовать функцию автопрефиксера CodePen, чтобы заполнить их для нас. Давайте теперь перейдем к первому из наших четырех методов.
Способ 1: использование отрицательных полей
Этот метод использует отрицательные поля для создания блоков сетки CSS с фиксированным отступом между каждым блоком. Отрицательное поле изменяется в зависимости от положения блока сетки, а поле между блоками сетки остается фиксированным. Давайте сначала посмотрим на HTML:
<div class="row-2 clearfix">
<div class="col-1-2"></div>
<div class="col-1-2"></div>
</div><!-- /.row -->
<div class="row-4 clearfix">
<div class="col-1-4"></div>
<div class="col-1-4"></div>
<div class="col-1-4"></div>
<div class="col-1-4"></div>
</div><!-- /.row -->
<div class="row-8 clearfix">
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
</div><!-- /.row -->
И наш CSS:
/* grid */
[class*="row-"] {
margin-bottom: 20px;
}
[class*="row-"]:last-child {
margin-bottom: 0;
}
[class*="col-"] {
}
@media all and ( min-width: 768px ) {
/* all cols margin */
[class*="col-"] {
margin-right: 20px;
}
[class*="col-"]:last-child {
margin-right: 0;
}
/* make the columns responsive */
.col-1-2 {
float: left;
width: 50%;
}
.col-1-4 {
float: left;
width: 25%;
}
.col-1-8 {
float: left;
width: 25%;
}
/* 2 span rows */
.row-2 {
padding-left: 20px;
}
.row-2 [class*="col-"]:first-child {
margin-left: -20px;
}
/* 4 span rows */
.row-4 {
padding-left: 60px;
}
.row-4 [class*="col-"]:first-child {
margin-left: -60px;
}
/* 8 span rows */
.row-8 {
padding-left: 60px;
}
.row-8 [class*="col-"]:nth-child(4n+1) {
margin-left: -60px;
}
.row-8 [class*="col-"]:nth-child(5n-1) {
margin-right: 0;
}
.row-8 [class*="col-"]:nth-child(6n-1) {
clear: both;
}
}
@media all and ( min-width: 1200px ) {
/* adjust width */
.col-1-8 {
float: left;
width: 12.5%;
}
/* 8 span rows */
.row-8 {
padding-left: 140px;
}
/* reset these... */
.row-8 [class*="col-"]:nth-child(4n+1) {
margin-left: 0;
}
.row-8 [class*="col-"]:nth-child(5n-1) {
margin-right: 20px;
}
.row-8 [class*="col-"]:nth-child(6n-1) {
clear: none;
}
/* and add this */
.row-8 [class*="col-"]:nth-child(1) {
margin-left: -140px;
}
}
А вот демоверсия CodePen:
Как вы можете видеть, когда мы достигаем чувствительной точки останова, слева от строки добавляется фиксированное значение поля (назовем его x), умноженное на количество столбцов минус 1 (n-1). Каждый столбец имеет правое поле x, кроме последнего дочернего элемента. И первый ребенок имеет отрицательное поле (n-1) * (x).
Недостатки и ошибки
Для этого метода требуется некоторая математика, которая становится непрактичной по мере увеличения количества элементов сетки. Кроме того, когда мы расширяем его на нескольких шагах столбца (например, переходя от 1 к строке, к 4, к 8), мы должны сбросить CSS, и в него вовлечено много математики nth-child
Еще одна интересная ошибка возникает, когда есть несколько плавающих элементов. Суммарная сумма полей в некоторой точке сталкивается, сталкивая столбцы в конце на новую строку. Это можно увидеть в сценарии с 8 столбцами. Если мы изменим минимальную ширину окончательного медиазапроса менее чем на 1200 пикселей, мы увидим ошибку в действии. Будьте внимательны к этому. Однако у этой техники есть свои преимущества.
Преимущества и использование в реальном мире
Настоящая красота этой техники заключается в создании комбинаций фиксированных / текучих сеток. В качестве примера, давайте представим область первичного содержимого ширины жидкости и вторичную область фиксированной ширины. Наш HTML может выглядеть так:
<div class="container clearfix">
<div class="primary">
<h2>Primary</h2>
Lorem ipsum dolor...
</div>
<div class="secondary">
<h2>Secondary</h2>
Lorem ipsum dolor...
</div>
</div><!-- /.container -->
И наш CSS так:
/* layout */
.primary {
margin-bottom: 20px;
}
@media all and ( min-width: 600px ) {
.container {
padding-right: 300px;
}
.primary {
float: left;
padding-right: 60px;
width: 100%;
}
.secondary {
float: right;
margin-right: -300px;
width: 300px;
}
}
Вот демонстрация CodePen, чтобы увидеть его в действии:
Способ 2: использование box-sizing: border-box
Этот метод использует всю мощь объявления box-sizing: border-box
Поскольку эта функция позволяет нам дополнить элемент, не добавляя его к общей ширине, мы все равно можем создать гибкую сетку с фиксированными «полями». На этот раз, вместо использования свойства margin
Давайте посмотрим на некоторые HTML:
<div class="row clearfix">
<div class="col-1-2"></div>
<div class="col-1-2"></div>
</div><!-- /.row -->
<div class="row clearfix">
<div class="col-1-4"></div>
<div class="col-1-4"></div>
<div class="col-1-4"></div>
<div class="col-1-4"></div>
</div><!-- /.row -->
<div class="row clearfix">
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
</div><!-- /.row -->
Здесь нам также не понадобится сумасшедшая математика, поэтому наш CSS становится действительно простым. Вот оно, до восьми столбцов:
/* grid */
.row {
margin: 0 -10px;
margin-bottom: 20px;
}
.row:last-child {
margin-bottom: 0;
}
[class*="col-"] {
padding: 10px;
}
@media all and ( min-width: 600px ) {
.col-2-3 {
float: left;
width: 66.66%;
}
.col-1-2 {
float: left;
width: 50%;
}
.col-1-3 {
float: left;
width: 33.33%;
}
.col-1-4 {
float: left;
width: 25%;
}
.col-1-8 {
float: left;
width: 12.5%;
}
}
Отрицательные поля слева и справа в каждом ряду должны компенсировать заполнение столбцов. При указанной минимальной ширине медиазапроса наши элементы сетки принимают собственную ширину и перемещаются внутри своих контейнеров. Вы можете изменить эту ширину по своему усмотрению, и указание другой точки останова для медиа-запроса для разных групп элементов сетки также не составит труда.
Вот демо:
Расширение этого метода
Допустим, вы хотели, чтобы .col-8
Немного подумав, это очень просто. Предполагая ту же разметку, что и выше, наш CSS будет выглядеть так:
@media all and ( min-width: 600px ) {
.col-1-8 {
float: left;
width: 25%;
}
.col-1-8:nth-child(4n+1) {
clear: both;
}
}
@media all and ( min-width: 960px ) {
.col-1-8 {
width: 12.5%;
}
.col-1-8:nth-child(4n+1) {
clear: none;
}
}
Вот демо:
Метод 3: Использование отображения таблицы
Этот метод реализует устаревшую функциональность table
В этом методе видимые элементы по умолчанию являются блочными. Но в определенной точке останова строки сетки становятся таблицами, а столбцы — ячейками таблицы. Давайте посмотрим на разметку — она похожа на метод 2, но не требуется никаких исправлений:
<div class="row">
<div class="col-1-2"></div>
<div class="col-1-2"></div>
</div><!-- /.row -->
<div class="row">
<div class="col-1-4"></div>
<div class="col-1-4"></div>
<div class="col-1-4"></div>
<div class="col-1-4"></div>
</div><!-- /.row -->
<div class="row">
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
</div><!-- /.row -->
А вот и CSS:
/* grid */
.row {
margin: 0 -10px;
margin-bottom: 10px;
}
.row:last-child {
margin-bottom: 0;
}
[class*="col-"] {
padding: 10px;
}
@media all and ( min-width: 600px ) {
.row {
display: table;
table-layout: fixed;
width: 100%;
}
[class*="col-"] {
display: table-cell;
}
/* set col widths */
.col-2-3 {
width: 66.66%;
}
.col-1-2 {
width: 50%;
}
.col-1-3 {
width: 33.33%;
}
.col-1-4 {
width: 25%;
}
.col-1-8 {
width: 12.5%;
}
}
И наша демка:
Этот метод может показаться запутанным, но есть и преимущества. Для начала, мы не нарушаем семантику, используя традиционные макеты таблиц, и нам не нужно очищать числа с плавающей точкой. Столбцы с одинаковой высотой также очень просты. Гибкие и гибкие комбинации? Нет проблем. Тем не менее, отображение таблиц приносит свои проблемы и является моим наименее любимым из этих четырех методов, хотя иногда это хороший вариант.
Способ 4: Flexbox
Последний метод, который я представлю, использует модуль flexbox. Согласно MDN :
Гибкая коробка CSS3, или flexbox, представляет собой режим макета, обеспечивающий расположение элементов на странице таким образом, что элементы ведут себя предсказуемо, когда макет страницы должен соответствовать разным размерам экрана и разным устройствам отображения.
Flexbox предоставляет нам множество различных функций, которые дают нам мощный арсенал вариантов компоновки. Создание адаптивного модуля flexbox — абсолютный бриз. Как и прежде, наша разметка выглядит так:
<div class="row">
<div class="col-1-2"></div>
<div class="col-1-2"></div>
</div><!-- /.row -->
<div class="row">
<div class="col-2-3"></div>
<div class="col-1-3"></div>
</div><!-- /.row -->
<div class="row">
<div class="col-1-4"></div>
<div class="col-1-4"></div>
<div class="col-1-4"></div>
<div class="col-1-4"></div>
</div><!-- /.row -->
<div class="row">
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
<div class="col-1-8"></div>
</div><!-- /.row -->
Вот посмотрите сейчас на наш CSS:
/* grid */
.row {
display: flex;
flex-flow: row wrap;
margin: 0 -10px;
margin-bottom: 10px;
}
.row:last-child {
margin-bottom: 0;
}
[class*="col-"] {
padding: 10px;
width: 100%;
}
@media all and ( min-width: 600px ) {
/* set col widths */
.col-2-3 {
width: 66.66%;
}
.col-1-2 {
width: 50%;
}
.col-1-3 {
width: 33.33%;
}
.col-1-4 {
width: 25%;
}
.col-1-8 {
width: 12.5%;
}
}
И демонстрация CodePen:
На этот раз нам нужно установить свойство display
flex
flex-flow
Полные определения и описания этих свойств доступны в документации по flexbox для MDN . В нашей отзывчивой точке останова мы переключаем ширину столбцов, а flexbox обрабатывает все остальное. Ухоженная!
Заворачивать
Мы рассмотрели 4 уникальных способа создания адаптивной системы сетки CSS, каждый из которых имеет свои преимущества. Не существует «лучшего» способа что-либо сделать, и я часто оказываюсь в ситуациях, когда один более эффективен, чем другой, или мне нужно комбинировать оба. Методы 1 и 2 — мои предпочтительные, и я часто их использую в одних и тех же проектах (определение основных макетов с помощью метода 1 и адаптивных сеток с помощью метода 2).
Метод 3 также имеет свои преимущества, как упомянуто выше, но я лично склоняюсь к макетам на основе таблиц, только когда это абсолютно необходимо. Метод 4 просто прекрасен, и я с нетерпением жду того дня, когда смогу свободно применять его во всех проектах. Flexbox находится в движении, но поддерживается только IE10 и выше. Доступны полифилы, но я предпочитаю вообще избегать их. Знайте свой рынок, хотя; Сегодня существуют сценарии, когда flexbox действительно предлагает идеальное решение.
Каждый из этих методов легко масштабируется и расширяется. С мыслительными процессами, представленными выше, у вас не должно быть никаких проблем при настройке сетки, адаптированной для вашего проекта с минимальным количеством CSS. Модуль CSS Grid также в разработке, но пройдет некоторое время, прежде чем мы рассмотрим его реализацию. Надеюсь, вам понравилось это читать, и теперь вы менее напуганы сетками CSS!