В наши дни есть основа для всего, и кажется, что прежде чем мы сможем даже переварить один, выпускается еще один. Это особенно верно, когда речь идет о макетах 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:
  На этот раз нам нужно установить свойство displayflexflex-flow  Полные определения и описания этих свойств доступны в документации по flexbox для MDN .  В нашей отзывчивой точке останова мы переключаем ширину столбцов, а flexbox обрабатывает все остальное.  Ухоженная! 
Заворачивать
Мы рассмотрели 4 уникальных способа создания адаптивной системы сетки CSS, каждый из которых имеет свои преимущества. Не существует «лучшего» способа что-либо сделать, и я часто оказываюсь в ситуациях, когда один более эффективен, чем другой, или мне нужно комбинировать оба. Методы 1 и 2 — мои предпочтительные, и я часто их использую в одних и тех же проектах (определение основных макетов с помощью метода 1 и адаптивных сеток с помощью метода 2).
Метод 3 также имеет свои преимущества, как упомянуто выше, но я лично склоняюсь к макетам на основе таблиц, только когда это абсолютно необходимо. Метод 4 просто прекрасен, и я с нетерпением жду того дня, когда смогу свободно применять его во всех проектах. Flexbox находится в движении, но поддерживается только IE10 и выше. Доступны полифилы, но я предпочитаю вообще избегать их. Знайте свой рынок, хотя; Сегодня существуют сценарии, когда flexbox действительно предлагает идеальное решение.
Каждый из этих методов легко масштабируется и расширяется. С мыслительными процессами, представленными выше, у вас не должно быть никаких проблем при настройке сетки, адаптированной для вашего проекта с минимальным количеством CSS. Модуль CSS Grid также в разработке, но пройдет некоторое время, прежде чем мы рассмотрим его реализацию. Надеюсь, вам понравилось это читать, и теперь вы менее напуганы сетками CSS!