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: relative
do pojemnika elastycznego.
Zastosuj position: absolute
do 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 top
i right
przesuń ten element na miejsce.
li:last-child {
position: absolute;
top: 0;
right: 0;
background: #ddd;
}
ul {
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p {
text-align: center;
margin-top: 0;
}
span {
background-color: aqua;
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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 auto
marginesó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ę
D
elementu.
- Umieść go na początku listy.
- Zastosowanie wyginają
auto
marże utrzymują A
, B
i C
skupione, ze oba D
elementy tworząc równowagę z obu końców.
- Zastosuj
visibility: hidden
do duplikatuD
li:first-child {
margin-right: auto;
visibility: hidden;
}
li:last-child {
margin-left: auto;
background: #ddd;
}
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;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
<li>D</li>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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ść D
musi być znana.
- Utwórz pseudoelement o tej samej szerokości co
D
.
- Umieść go na początku pojemnika z
::before
.
- Użyj flex
auto
marże zachować A
, B
i C
całkiem w środku, z pseudo i D
elementy tworząc równowagę z obu końców.
ul::before {
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
}
li:last-child {
margin-left: auto;
background: #ddd;
}
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;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Metoda nr 4: Dodaj flex: 1
do 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: flex
poszczegó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: 1
sprowadza się do tego:
flex-grow: 1
flex-shrink: 1
flex-basis: 0%
Ta jednostka procentowa (%) na flex-basis
powoduje zerwanie tej metody, gdy min-height
jest używana na kontenerze. Dzieje się tak, ponieważ z reguły procentowe wysokości elementów potomnych wymagają jawnego height
ustawienia 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 :
#flex-container {
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
}
#flex-container>div {
background: orange;
margin: 5px;
}
#flex-container>div:first-child {
flex: 1;
}
#flex-container::after {
content: "";
flex: 1;
}
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
Rozwiązaniem jest niestosowanie jednostki procentowej. Spróbuj px
lub 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).
#flex-container {
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
}
#flex-container > div {
background: orange;
margin: 5px;
}
#flex-container > div:first-child {
flex: 1;
flex-basis: 0;
}
#flex-container::after {
content: "";
flex: 1;
flex-basis: 0;
}
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
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; }
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>
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>
źródło
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>
źródło
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.
źródło
Stosując to
display:grid
podejście, możesz po prostu umieścić wszystkieul
dzieci 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>
źródło
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ł!
źródło
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
źródło
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
źródło
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
źródło
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>
źródło