CSS - Реагирующая сетка с равными полями и блоками фиксированного размера

Я пытаюсь ограничить пределы CSS, чтобы реплицировать то, что было бы общим сетчатым макетом в печати. ​​

Требования:

  • Поля между блоками и между блоками и краем контейнера должны быть равны.
  • Макет должен быть отзывчивым, а количество блоков в каждой строке должно соответствовать размеру окна.
  • Последняя строка должна быть выровнена влево
  • фиксируется ширина/высота блоков.
  • не использовать пустые не семантические HTML-элементы
  • чистое решение CSS, нет JS

Итак, у меня есть разметка, которая выглядит так:

<ul>
    <li>
       <img src="thumbnail.jpg">
       <span>Introduction and Curriculum</span>
    </li>
    <li>
       <img src="thumbnail.jpg">
       <span>Equipment and Workspace Prep</span>
    </li>
    ...
</ul>

Вот макет того, что я собираюсь.

grid layout with equal margins

Ответ 1

Вы можете использовать функцию CSS calc(). Хотя он не будет препятствовать использованию медиа-запросов, он может вычислять границу между элементами и контейнерами.

DEMO

В этой демонстрации используются:

  • calc() функция CSS. В этом контексте он будет поддерживаться IE9+. Возможно, вы захотите добавить префикс -webkit- для некоторых браузеров webkit. для получения дополнительной информации см. canIuse.
  • 4 мультимедийных запроса, чтобы изменить количество элементов, отображаемых в одной строке и полях соответственно.
  • встроенный блок. Это связано с пробелом (в демо я использовал технику размера шрифта, но вы можете использовать другую, см. Здесь).

Объяснение:

Точки прерывания медиа-контента:

Они рассчитываются по ширине элементов. Поскольку каждый элемент имеет ширину 200px, я должен был выбрать точки останова в screen width = 400px/600px/800px/1000px, но поскольку медиа-запросы включают полосу прокрутки, с этими значениями, элементам не хватило бы места и перекрывать друг друга.

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

Вот пример этого поведения с "логическими" точками прерывания медиа-контента.

Расчет маржи:

Прежде всего процентные поля и отступы всегда рассчитываются в соответствии с оставшейся шириной контейнера (исключение), поэтому верхнее и нижнее поля/прокладки имеют одинаковый расчет как левые/правые.

В принципе, вычисление размера полей:

(remaining width (=100%) - the sum of grid elements width) / number of gaps 

Но

Слева и верхние зазоры заполняются из контейнера, а остальные промежутки - правым и нижним краем элемента блока. Расчет маржи для блоков должен учитывать это, а деление - на number of gaps -1.


HTML:

<ul id="container">
    <li class="block">...</li>
    <li class="block">...</li>
    ...
</div>

CSS:

#container{
    font-size:0;    
    padding-top: calc((100% - 1000px)/6);
    padding-left:calc((100% - 1000px)/6);}

.block {
    font-size:20px;
    width: 200px;
    height: 200px;
    display:inline-block;
    margin-right: calc((100% - 1000px)/5);
    margin-bottom: calc((100% - 1000px)/5);
}

@media screen and (max-width: 430px) {
    .block {
        margin: calc(50% - 100px);
    }
}

@media screen and (min-width: 431px) and (max-width: 630px) {
    #container{
        padding-top: calc((100% - 400px)/3);
        padding-left:calc((100% - 400px)/3);
    }
    .block {
        margin-right: calc((100% - 400px)/2);
        margin-bottom: calc((100% - 400px)/2);
    }
}
@media screen and (min-width: 631px) and (max-width: 830px) {
    #container{
        padding-top: calc((100% - 600px)/4);
        padding-left:calc((100% - 600px)/4);
    }
    .block {
        margin-right: calc((100% - 600px)/3);
        margin-bottom: calc((100% - 600px)/3);
    }
}
@media screen and (min-width: 831px) and (max-width: 1030px) {
    #container{
        padding-top: calc((100% - 800px)/5);
        padding-left:calc((100% - 800px)/5);
    }
    .block {
        margin-right: calc((100% - 800px)/4);
        margin-bottom: calc((100% - 800px)/4);
    }
}

Ответ 2

Nth-child и реализация на соответствующих контрольных точках, вероятно, будут лучшим методом и самым легким решением.

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

... и т.д..