Выровнять элементы flexbox по центру и правому краю


148

Хотелось бы иметь A Bи Cвыровнять по середине.

Как мне Dполностью уйти вправо?

ПЕРЕД:

введите описание изображения здесь

ПОСЛЕ:

введите описание изображения здесь

ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  /* magic to throw to the right*/
}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>

https://jsfiddle.net/z44p7bsx/

Ответы:


215

Ниже приведены пять вариантов достижения этой схемы:

  • CSS Позиционирование
  • Flexbox с невидимым элементом DOM
  • Flexbox с невидимым псевдоэлементом
  • Flexbox с flex: 1
  • CSS Grid Layout

Метод # 1: свойства позиционирования CSS

Применить position: relativeк гибкому контейнеру.

Применить position: absoluteк элементу D.

Теперь этот элемент находится внутри гибкого контейнера.

В частности, элемент D удаляется из потока документов, но остается в границах ближайшего позиционированного предка .

Используйте свойства смещения CSS topи, rightчтобы переместить этот элемент на место.

Одно предостережение в отношении этого метода заключается в том, что некоторые браузеры могут не полностью удалить абсолютно позиционированный гибкий элемент из обычного потока. Это изменяет выравнивание нестандартным, неожиданным образом. Подробнее: Абсолютно позиционированный гибкий элемент не удаляется из обычного потока в IE11.


Метод # 2: гибкие автоматические поля и невидимый гибкий элемент (элемент DOM)

Макет может быть достигнут с помощью комбинации autoполей и нового невидимого гибкого элемента.

Новый гибкий элемент идентичен элементу D и размещается на противоположном конце (левый край).

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

Новый элемент удаляется из просмотра с помощью visibility: hidden.

Коротко:

  • Создайте дубликат Dэлемента.
  • Поместите его в начало списка.
  • Использование гибкого autoполя , чтобы сохранить A, Bи по Cцентру, причем оба Dэлемента создания равного баланса с обоих концов.
  • Применить visibility: hiddenк дубликатуD


Метод # 3: гибкие автоматические поля и невидимый гибкий элемент (псевдоэлемент)

Этот метод похож на метод №2, за исключением того, что он семантически более чистый и ширина Dдолжна быть известна.

  • Создайте псевдоэлемент той же ширины, что и D.
  • Поместите его в начало контейнера с ::before.
  • Используйте гибкие autoграницы для A, Bи Cцентровку с псевдо и Dэлементы , создающие равный баланс с обоих концов.


Метод №4: добавить flex: 1к левому и правому элементам

Начиная с метода №2 или №3, описанного выше, вместо того, чтобы беспокоиться об одинаковой ширине левого и правого предметов для поддержания равного баланса, просто дайте каждому по одному flex: 1. Это заставит их обоих использовать доступное пространство, таким образом центрируя средний элемент.

Затем вы можете добавить display: flexк отдельным элементам, чтобы выровнять их содержимое.

ПРИМЕЧАНИЕ об использовании этого метода с min-height: В настоящее время в Chrome, Firefox, Edge и, возможно, других браузерах сокращенное правилоflex: 1сводится к следующему:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0%

Этот процент единица (%) по flex-basisпричинам этот метод , чтобы сломать , когда min-heightиспользуется на контейнере. Это связано с тем, что, как правило, процентная высота дочерних элементов требует явной heightнастройки свойства родительского элемента.

Это старое правило CSS, датируемое 1998 годом ( уровень CSS 2 ), которое в той или иной степени все еще действует во многих браузерах. Полную информацию смотрите здесь и здесь .

Вот иллюстрация проблемы, опубликованная в комментариях user2651804 :

Решение состоит в том, чтобы не использовать процентную единицу. Попробуйте pxили совсем ничего ( что на самом деле рекомендует спецификация , несмотря на то, что по крайней мере некоторые из основных браузеров добавили процентную единицу по какой-либо причине).


Метод # 5: макет сетки CSS

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

Просто создайте сетку из нескольких столбцов. Затем разместите свои предметы в средних и конечных столбцах. Как правило, просто оставьте первый столбец пустым.

ul {
  display: grid;
  grid-template-columns: 1fr repeat(3, auto) 1fr;
  grid-column-gap: 5px;
  justify-items: center;
}

li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }

/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p  { text-align: center; }
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>| true center |</span></p>


1
Очень красиво, спасибо за объяснение! Я предполагаю, что недавно добавленные фрагменты кода выиграют от сокращения текста примера, поскольку из выходных данных не видно, что контент центрирован / не центрирован из-за небольшого окна просмотра. Только я?
user2651804

«Новый элемент должен иметь ту же ширину, что и существующий элемент D, иначе средние поля не будут точно центрированы». - отстой, что он должен быть такой же ширины, но слава богу за CSS-сетку :)
Vucko

Используя технику сетки, элементы не находятся в мертвой точке, есть ли способ сделать так, чтобы элемент логотипа был мертвым в центре? imgur.com/a/SVg9xsj
J86

Не достаточно знаком с сеткой, хотя она работает как шарм и является самой чистой. У меня один вопрос: как дать больше места средней колонке, а не всем трем?
Саба Аханг

5

Самый простой способ

.box{
  display:flex;
  justify-content:center;
}
.item1{
   flex:1;
   display: flex;
   justify-content: center;
   transform: translateX(10px);/*D element Width[if needed]*/
}
 <div class="box">
   <div class="item1">
      <div>A</div>
      <div>B</div>
      <div>C</div>
   </div>
   <div class="item2">D</div>
 </div>


2

Если вы хотите выровнять его, вы можете просто присоединить пустой промежуток и разделить на него три дочерних промежутка.


2
Можете ли вы предоставить короткую демонстрацию в подтверждение своего утверждения?
klewis

2

Самым простым решением будет выровнять центр содержимого для родительского контейнера и дать маржу слева для первого и последнего дочернего элемента.

ul {
  display:flex;
  justify-content:center;
}


.a,.d {
  margin-left:auto;
}
<ul>
  <li class="a">A</li>
  <li>B</li>
  <li>C</li>
  <li class="d">D</li>
</ul>


1

Используя этот display:gridподход, вы можете просто поместить всех ulдочерних элементов в одну ячейку, а затем установить justify-self:

ul {
  display: grid;
}

ul > * {
  grid-column-start: 1;
  grid-row-start: 1;
  justify-self:center;
}

ul > *:last-child {
  justify-self: right;
}

/* Make Fancy */
li {
  display:inline-block;
  margin: 1px;
  padding: 5px;
  background: #bbb;
}
<ul>
  <span>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  </span>
  <li>D</li>
</ul>


0

Очень четкий вопрос. Я не мог не опубликовать ответ после нескольких часов копания. Мы могли бы решить эту проблему с помощью таблиц, ячеек таблицы, абсолютных позиций, преобразований, но нам просто нужно было сделать это с помощью flexbox :)

.parent {
  display: flex;
  justify-content: flex-end;
}

.center {
  margin: auto;
}

http://codepen.io/rgfx/pen/BLorgd


8
Это не совсем центрирует средние элементы, потому что учитывается только оставшееся пространство, а не все пространство. codepen.io/anon/pen/QKGrRk
Майкл Бенджамин

@Michael_B, твоя правая не заметила этого, моя беда. Вернемся к использованию абсолютных позиций :( Может быть, с вашей высокой репутацией вам следует установить награду, чтобы решить эту проблему навсегда. Я бы хотел, но у меня очень низкая репутация, даже ниже, сейчас пытаюсь вам помочь.
rgfx

Никакая награда не собирается добавлять новое поведение в модель flexbox, Майкл_Б, данный ответ так хорош, как и сегодня ...
Асон

0

Я расширил Michael_B «s ответ

.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3) {
  flex: 1;
}
.center-flex__2-of-3 > :nth-child(1) {
  justify-content: flex-start;
}
.center-flex__2-of-3 > :nth-child(3) {
  justify-content: flex-end;
}
.center-flex__1-of-2 > :nth-child(1) {
  margin: auto;
}
.center-flex__1-of-2 > :nth-child(2) {
  flex: 1;
  justify-content: flex-end;
}
.center-flex__2-of-2 > :nth-child(1) {
  flex: 1;
  justify-content: flex-start;
}
.center-flex__2-of-2 > :nth-child(2) {
  margin: auto;
}
.center-flex__1-of-2:before, .center-flex__1-of-1:before {
  content: '';
  flex: 1;
}
.center-flex__1-of-1:after, .center-flex__2-of-2:after {
  content: '';
  flex: 1;
}

[class*=center-flex] {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  border: 10px solid rgba(0, 0, 0, 0.1);
}
[class*=center-flex] > * {
  display: flex;
}
li {
  padding: 3px 5px;
}
2 of 3
<ul class="center-flex__2-of-3">
  <span>
    <li>Accusamus</li>
    <li>Porro</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

<br><br>
1 of 1
<ul class="center-flex__1-of-1">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

Здесь с помощью SASS в качестве кода


0

На основе метода № 5: CSS Grid Layout решения @Michal Benjamin , а также потому, что я использую Tailwind и на данный момент все еще не имею доступа ко всем параметрам сетки по умолчанию. Это похоже на работу:

ul {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
li:nth-child(1) { justify-content: flex-start; } // OR: margin-right: auto
li:nth-child(3) { justify-content: flex-end; } // OR: margin-left:auto
li: {align-self: center;}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>

PS: Не уверен, что смешивание гибкости и сетки - это хорошая идея!


1
вы не смешиваете сетку и гибкость, justifty-content - это свойство сетки CSS И свойство flexbox (то же самое для align-self)
Темани Афиф

-1

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

grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr

-1
ul { 
  padding: 0; 
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  position:absolute;
  right:10px;

}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.