Последнее смещение полей / отступов в макете flexbox / grid
У меня есть список элементов, которые я пытаюсь расположить в прокручиваемом горизонтальном макете с помощью flexbox.
Каждый элемент в контейнере имеет поле слева и справа, но правое поле последнего элемента свернуто.
Есть ли способ остановить это или хороший обходной путь?
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 300px;
overflow: auto;
width: 600px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
margin: 0 30px;
white-space: nowrap;
flex-basis: auto;
}
<div class="container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
5 ответов
Потенциальная проблема № 1
Последнее поле не разрушается. Это игнорируется.
overflow
свойство распространяется только на контент. Это не относится к отступам или полям.
Вот что сказано в спецификации:
11.1.1. Переполнение:
overflow
имуществоЭто свойство указывает, обрезается ли содержимое элемента контейнера блока при переполнении поля элемента.
Теперь давайте посмотрим на CSS Box Model:
Источник: W3C
overflow
свойство ограничено областью содержимого поля. Если содержимое переполняет его контейнер, то overflow
применяется. Но overflow
не входит в области отступов или полей (если, конечно, нет больше контента, который следует).
Потенциальная проблема № 2
Проблема с потенциальной проблемой № 1 заключается в том, что она разваливается вне контекста гибкого или сеточного форматирования. Например, в стандартном макете блока последнее поле не выглядит свернутым. Так что, может быть overflow
разрешено покрывать поля / отступы, независимо от того, что говорится в спецификации.
div {
height: 150px;
overflow: auto;
width: 600px;
background: orange;
white-space: nowrap;
}
span {
background: blue;
color: #fff;
padding: 50px;
margin: 0 30px;
display: inline-block;
}
<div class="container">
<span>Item 1</span>
<span>Item 2</span>
<span>Item 3</span>
<span>Item 4</span>
</div>
Следовательно, возможно, проблема вместо этого связана с элементами, которые "чрезмерно ограничены".
10.3.3 Блочные, незаменяемые элементы в нормальном потоке
Следующие ограничения должны соблюдаться среди используемых значений других свойств:
margin-left
+border-left-width
+padding-left
+width
+padding-right
+border-right-width
+margin-right
= ширина вмещающего блокаЕсли
width
не являетсяauto
а такжеborder-left-width
+padding-left
+width
+padding-right
+border-right-width
(плюс любой изmargin-left
или жеmargin-right
это неauto
) больше ширины содержащего блока, то любойauto
значения дляmargin-left
или жеmargin-right
для следующих правил рассматриваются как ноль.Если все вышеперечисленное имеет вычисленное значение, отличное от
auto
значения называются "чрезмерно ограниченными", и одно из используемых значений должно отличаться от его вычисленного значения. Еслиdirection
свойство содержащего блока имеет значениеltr
указанное значениеmargin-right
игнорируется, и значение вычисляется так, чтобы сделать равенство истинным. Если значениеdirection
являетсяrtl
это случается сmargin-left
вместо(выделение добавлено)
Таким образом, в соответствии с моделью визуального форматирования CSS, элементы могут быть "чрезмерно ограничены", и, в результате, выбрасывается правое поле.
Потенциальные обходные пути
Вместо отступа или отступа используйте правую границу последнего элемента:
li:last-child {
border-right: 30px solid orange;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 100px; /* adjusted for demo */
overflow: auto;
width: 600px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
margin: 0 30px;
white-space: nowrap;
flex-basis: auto;
}
li:last-child {
border-right: 30px solid orange;
}
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
Другое решение использует псевдоэлементы вместо полей или отступов.
Псевдоэлементы в флекс-контейнере отображаются как флекс-элементы. Первый элемент в контейнере ::before
и последний пункт ::after
,
ul::after {
content: "";
flex: 0 0 30px;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 100px; /* adjusted for demo */
overflow: auto;
width: 600px;
background: orange;
}
ul li {
margin: 0 30px;
background: blue;
color: #fff;
padding: 90px;
white-space: nowrap;
flex-basis: auto;
}
ul::after {
content: "";
flex: 0 0 30px;
}
ul::before {
content: "";
flex: 0 0 30px;
}
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
Ваша проблема не сама по себе. Это полоса прокрутки, измеряющая только видимое содержимое элемента.
Один из способов решить эту проблему - создать видимый элемент, который занимает поле
Это решение обрабатывает это, используя псевдо на последнем дочернем
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 300px;
overflow: auto;
width: 600px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
margin: 0 30px;
white-space: nowrap;
flex-basis: auto;
position: relative;
}
li:last-child:after {
content: "";
width: 30px;
height: 1px;
position: absolute;
left: 100%;
top: 0px;
}
<div class"container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
Вы можете установить width
а также overflow
на div
контейнер и набор display: inline-flex
скорее, чем flex
на ul
, так что размер гибкого бокса будет рассчитываться на основе элементов внутри, и все отступы и поля будут применяться без каких-либо проблем.
.container {
width: 600px;
overflow: auto;
}
.container ul {
list-style: none;
padding: 0;
margin: 0;
display: inline-flex;
background: orange;
}
.container li {
padding: 60px;
margin: 0 30px;
white-space: nowrap;
background: blue;
color: #fff;
}
<div class="container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
По состоянию на октябрь 2023 года, похоже, эту проблему можно решить без псевдоэлементов, используя комбинациюgap
иpadding
на родительском элементе вместоmargin
.
Смотрите решение. Я удаляю white-space
, flex-basis
а также margin
, чтобы предоставить вам чистое решение flexbox.
Это реле на flex-flow: row
(По горизонтали), justify-content: space-around
(ваше поле) и не более!! width
изменено на 1200px
так как отступ 90px, установите общую ширину блоков больше чем 600px (определено в вашем фрагменте).
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
flex-flow: row ;
justify-content: space-around;
height: 300px;
overflow: auto;
width: 1200px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
}
<div class"container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>