Центрируйте и выровняйте по центру
У меня есть гибкий контейнер (синий квадрат) со следующими свойствами:
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
Поэтому его дети (голубые квадраты) располагаются так, как вы видите ниже. Тем не менее, я хотел бы добавить другого дочернего элемента (зеленый квадрат) из нормального потока и расположить его относительно своего родителя. Чтобы разместить его так, как вы видите ниже, я бы идеально написал что-то вроде bottom: 20px;
а также margin: auto;
,
Я пытался поиграть с z-index
но безрезультатно. Как мне подойти к этому? Должен ли я прибегнуть к созданию другого родительского элемента?
3 ответа
Ниже приведены пять вариантов достижения этого макета:
- CSS Позиционирование
- Flexbox с невидимым элементом DOM
- Flexbox с невидимым псевдоэлементом
- Flexbox с
flex: 1
- CSS Grid Layout
Метод № 1: CSS свойства позиционирования
Применять position: relative
в гибкий контейнер.
Применять position: absolute
к зеленому гибкому предмету.
Теперь зеленый квадрат абсолютно расположен внутри гибкого контейнера.
Более конкретно, зеленый квадрат удаляется из потока документов, но остается в границах ближайшего расположенного предка.
Используйте свойства смещения CSS top
, bottom
, left
а также right
переместить зеленый квадрат вокруг.
flex-container {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
position: relative;
border: 4px solid blue;
height: 300px;
width: 300px;
}
flex-container > flex-item:first-child {
display: flex;
}
flex-container > flex-item:first-child > flex-item {
border: 4px solid aqua;
height: 50px;
width: 50px;
margin: 0 5px;
}
flex-container > flex-item:last-child {
position: absolute;
bottom: 40px;
left: 50%;
transform: translateX(-50%); /* fine tune horizontal centering */
border: 4px solid chartreuse;
height: 50px;
width: 50px;
}
<flex-container>
<flex-item><!-- also flex container -->
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-item>
<flex-item></flex-item>
</flex-container>
Одно предостережение: некоторые браузеры не могут полностью удалить абсолютно позиционированный элемент Flex из обычного потока. Это меняет выравнивание нестандартным, неожиданным способом. Более подробная информация: Абсолютно позиционированный гибкий элемент не удаляется из обычного потока в Firefox и IE11
Метод № 2: Сгибание авто полей и невидимый изгиб (элемент DOM)
С комбинацией auto
поля и новый, невидимый гибкий элемент макета может быть достигнута.
Новый гибкий элемент идентичен нижнему элементу и расположен на противоположном конце (верхний).
Более конкретно, поскольку гибкое выравнивание основано на распределении свободного пространства, новый элемент является необходимым противовесом, чтобы держать три синих прямоугольника по центру. Новый элемент должен иметь ту же высоту, что и существующий зеленый элемент, иначе синие прямоугольники не будут точно отцентрированы.
Новый элемент удаляется из вида с visibility: hidden
,
Короче:
- Создайте дубликат зеленой коробки.
- Поместите это в начало списка.
- Используйте flex
auto
поля, чтобы держать синие прямоугольники по центру, при этом оба зеленых прямоугольника создают равный баланс с обоих концов. - Применять
visibility: hidden
в дубликат зеленой коробке.
flex-container {
display: flex;
flex-direction: column;
align-items: center;
border: 4px solid blue;
height: 300px;
width: 300px;
}
flex-container > flex-item:first-child {
margin-top: auto;
visibility: hidden;
}
flex-container > flex-item:nth-child(2) {
margin-top: auto;
display: flex;
}
flex-container > flex-item:last-child {
margin-top: auto;
margin-bottom: auto;
}
flex-container > flex-item:first-child,
flex-container > flex-item:last-child {
border: 4px solid chartreuse;
height: 50px;
width: 50px;
}
flex-container > flex-item:nth-child(2) > flex-item {
border: 4px solid aqua;
height: 50px;
width: 50px;
margin: 0 5px;
}
<flex-container>
<flex-item></flex-item>
<flex-item><!-- also flex container -->
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-item>
<flex-item></flex-item>
</flex-container>
Метод № 3: Сгибать автоматические поля и невидимый изгиб (псевдоэлемент)
Этот метод аналогичен #2, за исключением того, что он семантически чище и высота зеленого поля должна быть известна.
- Создайте псевдоэлемент с той же высотой, что и существующее зеленое поле.
- Поместите его в начале контейнера с
::before
, - Используйте flex
auto
поля для центрирования синих прямоугольников, с зелеными псевдоэлементами и элементами DOM, создающими равный баланс с обоих концов.
flex-container {
display: flex;
flex-direction: column;
align-items: center;
border: 4px solid blue;
height: 300px;
width: 300px;
}
flex-container::before {
content: "";
margin-top: auto;
height: calc(50px + 8px); /* height + borders */
visibility: hidden;
}
flex-container > flex-item:first-child {
margin-top: auto;
display: flex;
}
flex-container > flex-item:last-child {
margin-top: auto;
margin-bottom: auto;
border: 4px solid chartreuse;
height: 50px;
width: 50px;
}
flex-container > flex-item:first-child > flex-item {
border: 4px solid aqua;
height: 50px;
width: 50px;
margin: 0 5px;
}
<flex-container>
<flex-item><!-- also flex container -->
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-item>
<flex-item></flex-item>
</flex-container>
Способ № 4: Добавить flex: 1
к верху и низу предметов
Начиная с метода № 2 или № 3 выше, вместо того, чтобы беспокоиться о равной высоте для верхнего и нижнего элементов, чтобы поддерживать равный баланс, просто дайте каждому flex: 1
, Это заставит их обоих занимать доступное пространство, таким образом центрируя средний элемент.
Вы можете добавить display: flex
к нижнему пункту, чтобы выровнять содержимое.
Метод № 5: CSS Grid Layout
Это может быть самый чистый и самый эффективный метод. Нет необходимости в абсолютном позиционировании, поддельных элементах или других взломах.
Просто создайте сетку из трех рядов. Затем выровняйте по центру элементы во втором и третьем рядах. Первый ряд может оставаться пустым.
grid-container {
display: grid;
grid-template-rows: repeat(3, 1fr);
align-items: center;
justify-items: center;
border: 4px solid blue;
height: 300px;
width: 300px;
}
grid-item:nth-child(2) {
display: flex;
}
grid-item:nth-child(2)>flex-item {
width: 50px;
height: 50px;
margin: 0 5px;
border: 4px solid aqua;
}
grid-item:nth-child(3) {
border: 4px solid chartreuse;
height: 50px;
width: 50px;
}
<grid-container>
<grid-item></grid-item>
<grid-item><!-- also flex container -->
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</grid-item>
<grid-item></grid-item>
</grid-container>
Пусть контейнер с position: relative
и зеленый квадрат с position:absolute;
body {
margin: 0;
}
#container {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
width: 192px;
height: 192px;
border: 4px solid indigo;
position: relative;
background: lavender;
}
.blue {
margin: 10px;
width: 30px;
height: 30px;
outline: 4px solid skyblue;
background: honeydew;
}
#green {
position: absolute;
width: 30px;
height: 30px;
left: 0;
right: 0;
margin: auto;
bottom: 20px;
outline: 4px solid yellowgreen;
background: greenyellow;
}
<div id=container>
<div class=blue></div><div class=blue></div><div class=blue></div>
<div id=green></div>
</div>
Вы можете использовать псевдо для перемещения вниз на одну строку первые три контейнера, а затем применить margin:auto
до последнего
div {
display:flex;
flex-wrap:wrap;
border:#0066FD solid;;
width:200px;
height:200px;
justify-content:space-around;
/* show me box center */
background:linear-gradient(to top,rgba(0,0,0,0.2) 50%, transparent 50%),linear-gradient(to left,rgba(0,0,0,0.2) 50%, transparent 50%)
}
span, div:before {
width:50px;
height:50px;
border:solid #01CDFF;
margin:0 auto 0;
}
span:last-of-type , div:before{
margin: 12px auto;
border:solid #01FE43;
}
div:before {
content:'';
width:100%;
border:none;
}
span {
/* show me box center */
background:linear-gradient(45deg,rgba(0,0,0,0.1) 50%, transparent 50%),linear-gradient(-45deg,rgba(0,0,0,0.1) 50%, transparent 50%)
}
<div>
<span></span>
<span></span>
<span></span>
<span></span>
</div>