Использование отрицательных полей для управления пространством в гибкой коробке
Я читал на гибких коробках, чтобы решить проблему, с которой я столкнулся. Основная статья, которую я прочитал/использовал в качестве исследования проблемы, this.
Недавно я опубликовал эту тему в этом и этом, и благодаря помощи @Michael_B, было разработано, как центрировать элемент (в данном случае <h2>
) в flex-box, если всегда есть только три гибких элемента в flex-box (в этом макете: <div><h2><div>
).
Я хотел расширить эти точки, поскольку я понял, что может быть решение, которое могло бы решить, если есть больше или (более реалистично) меньше, чем 3 общих элемента flex.
Он включает использование полей. Если вы используете margin: auto;
на элементе flex, он действует, чтобы центрировать элемент на главной оси (см. Следующий рисунок о том, как работает гибкая коробка).
img {
width: 100%;
height: 100%;
}
<img src="http://i.stack.imgur.com/9Oxw7.png" alt="flex-box demo" />
Ответы
Ответ 1
Я установил хакерский способ справиться с этим
- Сделать упаковку гибкого контейнера
- Добавить псевдо-элемент для принудительного переноса строки, где установлено
- добавить свойства сортировки, чтобы в первой строке был только центральный элемент, за которым следует псевдоопределение, которое заставляет wrap
- Сделайте прокрутку на второй строке, начиная с прошивки и конца строки.
- Сделайте какой-то трюк трансформации, чтобы сделать то, что на самом деле есть 2 строки, как одна строка.
- И, конечно, центрируйте элемент центра с автоматическими полями
Первый контейнер в фрагменте центрируется как обычно, как сравнение.
Второй контейнер, как больше элементов слева, чем справа, но работает нормально:
div {
display: flex;
background-color: lemonchiffon;
margin-top: 10px;
}
h2 {
margin: auto;
}
span {
border: solid 1px red;
padding: 3px;
}
.container {
flex-wrap: wrap;
transform: scaleY(0.5);
}
.container:after {
content: "";
height: 0px;
width: 100%;
flex-shrink: 1;
background-color: green;
order: 10;
}
.container span {
transform-origin: center top;
transform: translateY(-100%) scaleY(2);
position: relative;
order: 20;
}
.center {
transform-origin: center top;
transform: scaleY(2) ;
}
.center ~ span {
order: 30;
}
.center + span {
margin-left: auto;
}
<div>
<span>I'm a span!</span>
<span>I'm a span!</span>
<h2>I'm an h2</h2>
<span>I'm a span!</span>
<span>I'm a span!</span>
</div>
<div class="container">
<span>I'm a span!</span>
<span>I'm a span!</span>
<span>I'm a span!</span>
<h2 class="center">I'm an h2</h2>
<span>I'm a span!</span>
<span>I'm a span!</span>
</div>
Ответ 2
Один из способов - вывести центральный элемент из нормального гибкого потока.
Это возможно путем абсолютного позиционирования его внутри контейнера.
Недостатком этого является то, что гибкий контейнер больше не учитывает высоту абсолютного позиционированного элемента.
codepen
.container {
position: relative;
display: flex;
width: 500px;
justify-content: flex-start;
align-items: center;
outline: 1px solid blue;
}
.item {
flex: 0 0 auto;
outline: 1px solid red;
margin: 0;
}
.item--center {
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.item--right {
margin-left: auto;
}
<div class="container">
<span class="item">I'm a span!</span>
<span class="item">I'm a span!</span>
<h2 class="item item--center">I'm an h2</h2>
<span class="item item--right">I'm a span!</span>
</div>
Ответ 3
Я не совсем понимаю, почему бы вам просто не использовать justify-content: center;
, как показано ниже:
div{
align-items: center;
display: flex;
justify-content: center;
}
<div>
<h2>I'm an h2</h2>
</div>
Ответ 4
Решение 1: отрицательное margin-top
- Не связано с позиционированием (изменена структура HTML).
- Нативный flex
h2
скрыт и установлен на flex: 1;
, чтобы оставить пространство для центрирования h2
.
- Центрированный
h2
заменит собственный flex h2
отрицательным margin-top
.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
div {
display: flex;
flex-flow: row wrap;
background: gainsboro;
}
div h2 {
flex: 1;
color: transparent;
}
h2.center {
color: black;
text-align: center;
background: transparent;
margin-top: -28px;
}
span {
border: 1px solid gray;
display: flex;
justify-content: flex-start;
align-items: center;
}
<div>
<span>I'm a span!</span>
<span>I'm a span!</span>
<h2>I'm an h2</h2>
<span>I'm a span!</span>
</div>
<h2 class="center">I'm an h2</h2>
Ответ 5
Итак, просто наткнулся на этот вопрос. Я немного неясен о том, что вы пытаетесь сделать, но я опишу его, насколько это возможно.
Для произвольного количества элементов внутри контейнера
- Назначить элемент всегда в центре массива
- Сохранять использование макета
flex
- Не используйте JavaScript
Как это работает
- Мы разбиваем элемент
h2
из потока контейнера, предоставляя ему позицию absolute
.
- Мы устанавливаем элемент контейнера в позицию
relative
, чтобы его дочерние элементы располагались относительно себя.
- Мы сообщим элементу
h2
, что мы хотим его в центре элемента контейнера, установив свойства top
и left
в 50%
.
- Мы корректируем смещение элемента (из-за его отслеживания на основе верхнего левого порядкового номера), установив свойство
transform: translate(-50%, -50%)
на h2
. Значения translate
относятся к размеру затронутого элемента, сообщая ему о скольжении 50%
его ширины влево и 50%
его высоты вверху.
- Мы добавляем элемент "dummy" для имитации абсолютно упорядоченного порядка
h2
в потоке. Мы даем фиктивный элемент размеру зарезервированного пространства, но вы можете так же легко добавить текст или другое значение, чтобы обеспечить его расположение.
- Мы устанавливаем видимость фиктивного элемента на
hidden
. Использование visibility: hidden
в элементе скрывает его от отображения, но сохраняет его пространство в потоке документа.
В процессе создания этого макета я сломал кнопки на вашем примере, однако я немного очистил ваш JS, чтобы сделать его более читаемым. Если кнопки важны для вашего понимания, я с радостью их исправлю.
Соответствующий CSS следует:
div {
position: relative;
}
h2 {
position:absolute;
margin: 0;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
line-height: 40px;
}
h3.filler {
height: 40px;
visibility: hidden;
}