Wyśrodkuj jeden i prawy / lewy wyrównaj inny element flexbox

167

Chciałbym mieć A Bi Cwyrównać w środku.

Jak mogę Dprzejść całkowicie w prawo?

PRZED:

wprowadź opis obrazu tutaj

PO:

wprowadź opis obrazu tutaj

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/

zamglony
źródło

Odpowiedzi:

239

Poniżej znajduje się pięć opcji osiągnięcia tego układu:

  • Pozycjonowanie CSS
  • Flexbox z niewidocznym elementem DOM
  • Flexbox z niewidocznym pseudoelementem
  • Flexbox z flex: 1
  • Układ siatki CSS

Metoda nr 1: Właściwości pozycjonowania CSS

Zastosuj position: relativedo pojemnika elastycznego.

Zastosuj position: absolutedo pozycji D.

Teraz ten przedmiot jest absolutnie umieszczony w pojemniku elastycznym.

Mówiąc dokładniej, element D jest usuwany z przepływu dokumentów, ale pozostaje w granicach najbliższego umieszczonego przodka .

Użyj właściwości przesunięcia CSS topi rightprzesuń ten element na miejsce.

Jedynym zastrzeżeniem do tej metody jest to, że niektóre przeglądarki mogą nie usunąć całkowicie pozycjonowanego elementu elastycznego z normalnego przepływu. Zmienia to ustawienie w niestandardowy, nieoczekiwany sposób. Więcej szczegółów: Absolutnie pozycjonowany element elastyczny nie jest usuwany z normalnego przepływu w IE11


Metoda nr 2: Flex Auto Margins & Invisible Flex Item (element DOM)

Dzięki połączeniu automarginesów i nowego, niewidocznego elementu elastycznego można uzyskać układ.

Nowy element elastyczny jest identyczny z elementem D i jest umieszczony na przeciwległym końcu (lewa krawędź).

Mówiąc dokładniej, ponieważ wyrównanie flex jest oparte na rozkładzie wolnej przestrzeni, nowy element jest niezbędną przeciwwagą, aby trzy środkowe pola były wyśrodkowane w poziomie. Nowy element musi mieć taką samą szerokość jak istniejący element D, w przeciwnym razie środkowe pola nie będą dokładnie wyśrodkowane.

Nowy element jest usuwany z widoku za pomocą visibility: hidden.

W skrócie:

  • Utwórz kopię Delementu.
  • Umieść go na początku listy.
  • Zastosowanie wyginają automarże utrzymują A, Bi Cskupione, ze oba Delementy tworząc równowagę z obu końców.
  • Zastosuj visibility: hiddendo duplikatuD


Metoda nr 3: Flex Auto Margins & Invisible Flex Item (pseudoelement)

Ta metoda jest podobna do # 2, z wyjątkiem tego, że jest bardziej przejrzysta semantycznie, a szerokość Dmusi być znana.

  • Utwórz pseudoelement o tej samej szerokości co D.
  • Umieść go na początku pojemnika z ::before.
  • Użyj flex automarże zachować A, Bi Ccałkiem w środku, z pseudo i Delementy tworząc równowagę z obu końców.


Metoda nr 4: Dodaj flex: 1do lewej i prawej pozycji

Zaczynając od metody nr 2 lub nr 3 powyżej, zamiast martwić się o równą szerokość lewego i prawego elementu, aby zachować równą równowagę, po prostu podaj każdy z nich flex: 1. Zmusi to ich obu do wykorzystania dostępnej przestrzeni, w ten sposób wyśrodkowując środkowy element.

Następnie możesz dodać display: flexposzczególne elementy, aby wyrównać ich zawartość.

UWAGA dotycząca korzystania z tej metody w przypadku min-height: Obecnie w Chrome, Firefox, Edge i prawdopodobnie innych przeglądarkach reguła skrótuflex: 1sprowadza się do tego:

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

Ta jednostka procentowa (%) na flex-basispowoduje zerwanie tej metody, gdy min-heightjest używana na kontenerze. Dzieje się tak, ponieważ z reguły procentowe wysokości elementów potomnych wymagają jawnego heightustawienia właściwości elementu nadrzędnego.

Jest to stara reguła CSS z 1998 roku ( CSS poziom 2 ), która do pewnego stopnia nadal obowiązuje w wielu przeglądarkach. Aby uzyskać szczegółowe informacje, zobacz tutaj i tutaj .

Oto ilustracja problemu opublikowanego w komentarzach przez użytkownika2651804 :

Rozwiązaniem jest niestosowanie jednostki procentowej. Spróbuj pxlub po prostu nic ( co tak naprawdę zaleca specyfikacja , pomimo faktu, że przynajmniej niektóre z głównych przeglądarek dodały jednostkę procentową z dowolnego powodu).


Metoda nr 5: Układ siatki CSS

To może być najczystsza i najbardziej wydajna metoda. Nie ma potrzeby pozycjonowania absolutnego, fałszywych elementów ani innych hakerów.

Po prostu utwórz siatkę z wieloma kolumnami. Następnie umieść przedmioty w środkowej i końcowej kolumnie. Zasadniczo zostaw pierwszą kolumnę pustą.

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>

Michael Benjamin
źródło
1
Bardzo ładnie, dziękuję za wyjaśnienie! Myślę, że nowo dodane fragmenty kodu skorzystałyby na skróceniu przykładowego tekstu, ponieważ z danych wyjściowych nie wynika, że ​​treść jest wyśrodkowana / nie wyśrodkowana ze względu na mały obszar roboczy. Tylko ja?
user2651804
„Nowy element musi mieć taką samą szerokość jak istniejący element D, w przeciwnym razie środkowe pola nie będą dokładnie wyśrodkowane”. - szkoda, że ​​musi być tej samej szerokości, ale dzięki Bogu za siatkę CSS :)
Vucko
Używając techniki Grid, elementy nie znajdują się w martwym punkcie, czy jest sposób, aby element logo był martwy w środku? imgur.com/a/SVg9xsj
J86
Nie dość zaznajomiony z rozwiązaniem kratki, chociaż działa jak urok i jest najczystszy. Jedno pytanie, które mam, to jak dać więcej miejsca środkowej kolumnie, która nie jest równa wszystkim trzem.
Saba Ahang
6

Najłatwiejszy sposób

.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>

Razib Hossain
źródło
3

Najprostszym rozwiązaniem będzie justowanie-content center do kontenera nadrzędnego i nadanie margin-left auto pierwszemu i ostatniemu elementowi podrzędnemu.

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>

Suhail AKhtar
źródło
1
@Ason Masz rację, ponieważ miałem tylko mały przedmiot po prawej stronie, nie zauważyłem go.
Surjith SM
2

Jeśli chcesz go wyrównać, możesz po prostu dołączyć pustą rozpiętość i podzielić na nie trzy przęsła podrzędne.

Ali Korkmaz
źródło
3
czy możesz dostarczyć krótkie demo, aby potwierdzić swoje oświadczenie?
klewis
nie używaj dodatkowego kodu HTML tylko do osiągnięcia czegoś w wyglądzie i działaniu, może
uszkodzić
1

Stosując to display:gridpodejście, możesz po prostu umieścić wszystkie uldzieci w tej samej komórce, a następnie ustawić 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>

Steven Spungin
źródło
0

Zainspirowany Metodą nr 5: Układ siatki CSS rozwiązania @Michal Benjamin i ponieważ używam Tailwind i nadal nie mam domyślnie dostępu do wszystkich opcji siatki. To wydaje się działać:

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: Nie jestem pewien, czy pomieszanie flexu i gridu w ten sposób to dobry pomysł!

Saba Ahang
źródło
1
nie mieszasz grid i flex, justifty-content to właściwość siatki CSS ORAZ właściwość flexbox (taka sama dla align-self)
Temani Afif
-1

Bardzo jasne pytanie. Nie mogłem się powstrzymać przed opublikowaniem odpowiedzi po kilku godzinach kopania. Mogliśmy to rozwiązać za pomocą tabel, komórek tabeli, pozycji bezwzględnych, transformacji, ale po prostu musieliśmy to zrobić za pomocą flexboksa :)

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

.center {
  margin: auto;
}

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

rgfx
źródło
8
To tak naprawdę nie wyśrodkowuje środkowe elementy, ponieważ bierze pod uwagę tylko pozostałą przestrzeń, a nie całą przestrzeń. codepen.io/anon/pen/QKGrRk
Michael Benjamin
@Michael_B, twoje prawo tego nie zauważyło, moja wina. Wracając do używania pozycji absolutnych :( Może z twoim wysokim powtórzeniem powinieneś ustawić nagrodę, aby rozwiązać ten problem na dobre. Chciałbym, ale mam bardzo niską
liczbę
Żadna nagroda nie doda nowego zachowania do modelu flexbox, podana przez Michaela_B odpowiedź jest tak dobra, jak to możliwe ... dzisiaj.
Ason
-1

I rozszerzony na Michael_B „s odpowiedź

.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>Center</li>
    <li>this</li>
  </span>
  <span>
    <li>Accusamus</li>
    <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>Center</li>
    <li>this</li>
  </span>
  <span>
    <li>Accusamus</li>
    <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>Accusamus</li>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
  <span>
    <li>Center</li>
    <li>this</li>
  </span>
</ul>

<br><br>
1 of 1
<ul class="center-flex__1-of-1">
  <span>
    <li>Center</li>
    <li>this</li>
  </span>
</ul>

Tutaj z pomocą SASS jako codepen

yunzen
źródło
-2

Zaakceptowaną odpowiedź można nieco zmienić, ponieważ możesz użyć obszarów szablonu siatki i zrobić to bez fałszywego elementu

grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr
repozytorium
źródło
-2
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>
SUDHIR KUMAR
źródło