Модель grid и border – варианты решений
Популярные запросы: Open Graph, плагин Reading Time, тема Quebec, плагин Telegram, набор иконок Analogue
- 167 просмотров +1
- 13 января, 2026
- Обновлено: 16 января, 2026
- admin
- Время чтения: 7 минут
- 1 (Подробно)
Сегодня рассмотрим вопрос по переводу табличной верстки (модель table) в сеточную верстку (модель grid). Обычно это касается верстки форумов и другого контента, который является табличным только визуально.
Преамбула
В общем и целом, вопрос выбора между table и альтернативами не сильно принципиальный, однако в некоторых случаях табличная верстка работает не так, как ожидается. В основном, это касается свойства overflow в довольно экзотических сочетаниях.
Еще один момент – это избыточность HTML-элементов. Сравним:
<table>
<thead>
<tr>
<th>Heading 1</th>
<th>Heading 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
</tbody>
</table>
и
<div>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div>
Praesent convallis est at metus feugiat ultricies.
</div>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div>
Praesent convallis est at metus feugiat ultricies.
</div>
</div>
В первом случае у нас как минимум явный “лишний” контейнер. Не так, чтобы совсем плохо, но можно и лучше. А если учесть thead / tbody, то это уже два “лишних”.
Наконец, самый принципиальный момент – это реализация адаптивности. Для таблиц это, все же чересчур сложный перебор свойств display для вложенных элементов. Конечно, для пользователей Bootstrap есть маленький помощник – класс .table-responsive. Но это еще одна div-оболочка, реализующая горизонтальный скролл. Да, это адаптивно, но хочется иметь нормальное вертикальное перестроение или responsive stackable.
Стоит ли полностью отказываться от табличной верстки? Конечно нет! Но там, где “табличность” это лишь визуал, лучше использовать что-то более современное. В нашем случае – модель grid.
Общий принцип ее применения следующий:
- Схема “родитель – потомки”, без промежуточных или избыточных элементов.
- Основной инструмент – свойство grid-template, определяющее сетку колонок и рядов.
- Вспомогательное свойство – gap, позволяющее определять расстояния между колонками и рядами.
Главный минус смены table на grid состоит в том, что мы теряем привычную стилизацию четных и нечетных рядов. Впрочем, решение все же есть.
В рамках данной статьи мы не будем рассматривать все нюансы grid-модели и остановимся только на алгоритмах решения вопроса применения свойства border так, чтобы полностью имитировать табличную верстку. Это актуально, например, для верстки форумов, где традиционно всегда использовались таблицы, а flex не всегда удобен и прост.
Решение проблемы
Итак, начнем с базовой разметки:
<div class="grids" id="grid-1">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div>
Praesent convallis est at metus feugiat ultricies.
</div>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div>
Praesent convallis est at metus feugiat ultricies.
</div>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div>
Praesent convallis est at metus feugiat ultricies.
</div>
</div>
У нас есть родитель и шесть потомков, которые необходимо разместить в два ряда. Сделать это несложно:
div.grids { display: grid; }
div.grids > div { padding: 1rem 3rem; }
div#grid-1 { grid-template-columns: repeat(2, 1fr); }
Как поступить с обводкой? Если все упростить и применить border: 1px solid #000 к потомкам, получим сдвоенные внутренние линии. Добавим border: 1px solid #000 к родителю, и все станет единообразно, но толщина обводки уже везде составит 2px. Если это ваш вариант, останавливайтесь на нем. Мы же пойдем дальше.
Если подумать, можно обыграть свойства padding, background и gap, и сконструировать на их основе псевдообводку:
div#grid-1 { padding: 1px; background: #666; grid-template-columns: repeat(2, 1fr); gap: 1px; }
div#grid-1 > div { background: #fff; }
В принципе, неплохо: вариант и рабочий и компактный. Но немного смущает заливка для элементов-потомков. Можно ли, все же, вернуться к свойству border? Легко:
div#grid-2 { border: 1px solid #666; grid-template-columns: repeat(2, 1fr); }
div#grid-2 > div { border-right: 1px solid #666; border-top: 1px solid #666; }
div#grid-2 > div:nth-child(2n+2) { border-right: 0; }
div#grid-2 > div:nth-child(1),
div#grid-2 > div:nth-child(2) { border-top: 0; }
Как видим, получилось, и весьма неплохо. Мы получили “родное” свойство border и отсутствие заливок. Можно ли здесь конструировать универсальность? Зависит от ваших задач. Если вы используете компилятор LESS (или SASS), это будет несложно:
.bordered-grid(@cols, @border_size: 1px, @border_style: solid, @border_color: #666) { border: @border_size @border_style @border_color; border-top: 0; grid-template-columns: repeat(@cols, 1fr);
& > div { border-right: @border_size @border_style @border_color; border-top: @border_size @border_style @border_color; }
& > div:nth-child(@{cols}n + @{cols}) { border-right: 0; }
}
Теперь для необходимого селектора достаточно применить наш mixin:
div#grid-3 { .bordered-grid(2, 1px, solid, #666); }
// или компактнее со значениями по умолчанию:
div#grid-3 { .bordered-grid(2); }
Единственный момент – жесткая привязка к равным ширинам потомков. Думается, при желании можно обыграть и этот момент. И еще одно: четные и нечетные ряды. С этим сложнее, и подходов будет два:
- Жестко стилизовать всех потомков с помощью
:nth-child(an+b), что не очень интересно, поскольку требует знания количества колонок и – что хуже – рядов. - Использовать вложенные родительские элементы, что не так уж и страшно.
Для первого варианта получим следующие стили:
div.oddeven-1 > div:nth-child(6n+3),
div.oddeven-1 > div:nth-child(6n+4) {
background-color: #fefefe;
}
div.oddeven-1 > div:nth-child(6n+1),
div.oddeven-1 > div:nth-child(6n+2),
div.oddeven-1 > div:nth-child(6n+5),
div.oddeven-1 > div:nth-child(6n+6) {
background-color: #ddd;
}
Как видим, он совершенно не подходит для случаев, когда количество рядов неизвестно. А именно так и есть в реальности. Так что, если стилизация “чет-нечет” необходима, должен быть введен промежуточный родитель:
<div>
<div class="interim">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div>
Praesent convallis est at metus feugiat ultricies.
</div>
</div>
<div class="interim">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div>
Praesent convallis est at metus feugiat ultricies.
</div>
</div>
<div class="interim">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div>
Praesent convallis est at metus feugiat ultricies.
</div>
</div>
</div>
Укажем для него следующее свойство display:
div.interim { display: contents; }
При такой стилизации промежуточный родитель не будет нарушать grid-модель и сможет принять стили для odd и even-элементов:
div.interim:nth-child(odd) > div {
background-color: #ddd;
}
div.interim:nth-child(even) > div {
background-color: #fefefe;
}
Наша проблема решена. Реализацию можно увидеть здесь.
Вместо заключения
В довольно несложной манере мы смогли решить задачу по переводу табличной верстки в сеточную. Визуально мы получили абсолютно идентичную картину. В главном плюсе имеем адаптивность с простым вертикальным перестроением (responsive stackable), более предсказуемое и простое поведение блочных потомков и – при отсутствии требований к стилизации четных и нечетных позиций – весьма компактную разметку. Впрочем, я бы легко пожертвовал компактностью и все же ввел промежуточного родителя для odd/even стилей.
А стоит ли вообще овчинка выделки? В чистом виде, конечно, нет. Выбор модели для визуального представления элементов не влияет ни на качество контента, ни на его поисковую оптимизацию. Значимость семантичной вёрстки давно канула в лету, поэтому выбор модели определяется веб-разработчиком, исходя исключительно из практических соображений.
Выбор модели не должен быть самоцелью. Это всего лишь вопрос определения оптимального инструмента для визуального представления контента. И именно качество контента по-прежнему остается самым важным фактором в построении контакта с его потребителем. Поэтому начинать работу над улучшением проекта необходимо не с переверстывания ради переверстывания. Думать над этим стоит только тогда, когда решены более важные и глобальные задачи.
Возможно, вас заинтересует также и предыдущий пост, в котором мы разбирали кейс с подтвеждением действий.
Есть такое, просто мы не привыкли ассоциировать такой просмотр с форумами. А выглядит это примерно как лента комментариев.
Не знаю как с Котонти, но просматривать форумы на смартфоне немного непривычно с вертикальным перестроением. Класс table-responsive сподручнее imho
Новый комментарий
Ошибка
Выполнено