Muszę zaimplementować dość spływy układ murarski. Jednak z wielu powodów nie chcę do tego używać JavaScript.
Parametry:
- Wszystkie elementy mają tę samą szerokość
- Elementy mają wysokość, której nie można obliczyć po stronie serwera (obraz plus różne ilości tekstu)
- Jeśli zajdzie taka potrzeba, mogę żyć ze stałą liczbą kolumn
jest rozwiązanie trywialne do tego, że działa w nowoczesnych przeglądarek, w column-count
nieruchomości.
Problem z tym rozwiązaniem polega na tym, że elementy są uporządkowane w kolumnach:
Chociaż potrzebuję elementów do zamówienia w rzędach, przynajmniej w przybliżeniu:
Podejścia, które wypróbowałem, nie działają:
- Tworzenie przedmiotów
display: inline-block
: marnuje przestrzeń w pionie. - Robienie przedmiotów
float: left
: lol, nie.
Teraz mógł zmienić renderowania po stronie serwera i uporządkować elementy podzielenie liczby pozycji przez liczbę kolumn, ale to skomplikowane, podatne na błędy (na podstawie sposobu przeglądarek decydują się podzielić z listy element do kolumn), więc chciałbym aby tego uniknąć, jeśli to możliwe.
Czy jest jakaś nowomodna magia flexbox, która to umożliwia?
Odpowiedzi:
Flexbox
Dynamiczny układ muru nie jest możliwy w przypadku flexbox, przynajmniej nie w czysty i wydajny sposób.
Flexbox to jednowymiarowy system układu. Oznacza to, że może wyrównywać elementy wzdłuż linii poziomych LUB pionowych. Element flex jest ograniczony do swojego wiersza lub kolumny.
Prawdziwy system siatki jest dwuwymiarowy, co oznacza, że może wyrównywać elementy wzdłuż linii poziomych ORAZ pionowych. Elementy treści mogą jednocześnie obejmować wiersze i kolumny, czego nie mogą robić elementy flex.
Dlatego flexbox ma ograniczoną zdolność do budowania kratek. Jest to również powód, dla którego W3C opracowało inną technologię CSS3, Grid Layout .
row wrap
W kontenerze elastycznym z
flex-flow: row wrap
elementami elastycznymi należy zawijać do nowych rzędów .Oznacza to, że element flex nie może być zawijany pod innym elementem w tym samym wierszu .
Zauważ powyżej, jak div # 3 zawija się poniżej div # 1 , tworząc nowy wiersz. Nie może zawijać się pod div # 2 .
W rezultacie, gdy przedmioty nie są najwyższe w rzędzie, pozostaje biała przestrzeń, tworząc brzydkie luki.
column wrap
Jeśli przełączysz się na
flex-flow: column wrap
, bardziej osiągalny jest układ przypominający siatkę. Jednak kontener w kierunku kolumn ma od razu cztery potencjalne problemy:W rezultacie kontener w kierunku kolumn nie jest opcją w tym przypadku, a także w wielu innych przypadkach.
Siatka CSS z wymiarami pozycji undefined
Układ siatki byłby idealnym rozwiązaniem problemu, gdyby można było z góry określić różne wysokości elementów treści . Wszystkie inne wymagania mieszczą się w granicach możliwości Gridu.
Szerokość i wysokość elementów siatki musi być znana, aby zamknąć luki między otaczającymi elementami.
Tak więc Grid, który jest najlepszym CSS, jaki ma do zaoferowania do tworzenia poziomego układu murów, nie spełnia w tym przypadku problemów.
W rzeczywistości, dopóki nie pojawi się technologia CSS z możliwością automatycznego zamykania luk, CSS ogólnie nie ma rozwiązania. Coś takiego prawdopodobnie wymagałoby ponownego załadowania dokumentu, więc nie jestem pewien, czy byłoby to użyteczne lub wydajne.
Będziesz potrzebował scenariusza.
Rozwiązania JavaScript mają tendencję do stosowania pozycjonowania bezwzględnego, które usuwa elementy treści z przepływu dokumentu w celu ponownego uporządkowania ich bez przerw. Oto dwa przykłady:
Desandro Masonry
Jak zbudować witrynę, która działa jak Pinterest
Siatka CSS ze zdefiniowanymi wymiarami pozycji
W przypadku układów, w których znana jest szerokość i wysokość elementów treści, oto poziomy układ masonry w czystym CSS:
grid-container { display: grid; /* 1 */ grid-auto-rows: 50px; /* 2 */ grid-gap: 10px; /* 3 */ grid-template-columns: repeat(auto-fill, minmax(30%, 1fr)); /* 4 */ } [short] { grid-row: span 1; /* 5 */ background-color: green; } [tall] { grid-row: span 2; background-color: crimson; } [taller] { grid-row: span 3; background-color: blue; } [tallest] { grid-row: span 4; background-color: gray; } grid-item { display: flex; align-items: center; justify-content: center; font-size: 1.3em; font-weight: bold; color: white; }
<grid-container> <grid-item short>01</grid-item> <grid-item short>02</grid-item> <grid-item tall>03</grid-item> <grid-item tall>04</grid-item> <grid-item short>05</grid-item> <grid-item taller>06</grid-item> <grid-item short>07</grid-item> <grid-item tallest>08</grid-item> <grid-item tall>09</grid-item> <grid-item short>10</grid-item> <grid-item tallest>etc.</grid-item> <grid-item tall></grid-item> <grid-item taller></grid-item> <grid-item short></grid-item> <grid-item short></grid-item> <grid-item short></grid-item> <grid-item short></grid-item> <grid-item tall></grid-item> <grid-item short></grid-item> <grid-item taller></grid-item> <grid-item short></grid-item> <grid-item tall></grid-item> <grid-item short></grid-item> <grid-item tall></grid-item> <grid-item short></grid-item> <grid-item short></grid-item> <grid-item tallest></grid-item> <grid-item taller></grid-item> <grid-item short></grid-item> <grid-item tallest></grid-item> <grid-item tall></grid-item> <grid-item short></grid-item> </grid-container>
jsFiddle demo
Jak to działa
inline-grid
byłaby inna opcja)grid-auto-rows
Właściwość ustala wysokość automatycznie generowanych wierszy. W tej siatce każdy wiersz ma 50 pikseli wysokości.grid-gap
Nieruchomość jest skrótemgrid-column-gap
igrid-row-gap
. Ta reguła ustawia odstęp 10 pikseli między elementami siatki. (Nie dotyczy obszaru między przedmiotami a pojemnikiem).grid-template-columns
Właściwość określa szerokość wyraźnie zdefiniowanych kolumnach.repeat
Oznaczenie określa wzór powtarzających kolumn lub rzędów ().auto-fill
Funkcja opowiada siatki wyrównać taką liczbę kolumn (lub wierszy), jak to możliwe bez przepełnienia pojemnika. (Może to spowodować podobne zachowanie do układu flexflex-wrap: wrap
).minmax()
Funkcji wyznacza zakres maksymalnej i minimalnej wielkości dla każdej kolumny (lub wiersza). W powyższym kodzie szerokość każdej kolumny będzie wynosić minimum 30% kontenera i maksimum wolnego miejsca.fr
Urządzenie stanowi część wolnej przestrzeni w zbiorniku siatki. Jest to porównywalne zflex-grow
właściwością flexboxa .Za pomocą
grid-row
ispan
mówimy elementom siatki, ile wierszy powinny obejmować.Wsparcie przeglądarek dla siatki CSS
Oto pełny obraz: http://caniuse.com/#search=grid
Fajna funkcja nakładki siatki w przeglądarce Firefox
W narzędziach programistycznych Firefox dla deweloperów podczas sprawdzania kontenera siatki w deklaracji CSS znajduje się mała ikona siatki. Po kliknięciu wyświetla zarys twojej siatki na stronie.
Więcej szczegółów tutaj: https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Examine_grid_layouts
źródło
Jest to niedawno odkryta technika wykorzystująca flexbox: https://tobiasahlin.com/blog/masonry-with-css/ .
Artykuł ma dla mnie sens, ale nie próbowałem go używać, więc nie wiem, czy są jakieś zastrzeżenia, poza wymienionymi w odpowiedzi Michaela.
Oto próbka z artykułu wykorzystująca
order
właściwość w połączeniu z:nth-child
.Fragment stosu
.container { display: flex; flex-flow: column wrap; align-content: space-between; /* Your container needs a fixed height, and it * needs to be taller than your tallest column. */ height: 960px; /* Optional */ background-color: #f7f7f7; border-radius: 3px; padding: 20px; width: 60%; margin: 40px auto; counter-reset: items; } .item { width: 24%; /* Optional */ position: relative; margin-bottom: 2%; border-radius: 3px; background-color: #a1cbfa; border: 1px solid #4290e2; box-shadow: 0 2px 2px rgba(0,90,250,0.05), 0 4px 4px rgba(0,90,250,0.05), 0 8px 8px rgba(0,90,250,0.05), 0 16px 16px rgba(0,90,250,0.05); color: #fff; padding: 15px; box-sizing: border-box; } /* Just to print out numbers */ div.item::before { counter-increment: items; content: counter(items); } /* Re-order items into 3 rows */ .item:nth-of-type(4n+1) { order: 1; } .item:nth-of-type(4n+2) { order: 2; } .item:nth-of-type(4n+3) { order: 3; } .item:nth-of-type(4n) { order: 4; } /* Force new columns */ .break { flex-basis: 100%; width: 0; border: 1px solid #ddd; margin: 0; content: ""; padding: 0; } body { font-family: sans-serif; } h3 { text-align: center; }
<div class="container"> <div class="item" style="height: 140px"></div> <div class="item" style="height: 190px"></div> <div class="item" style="height: 170px"></div> <div class="item" style="height: 120px"></div> <div class="item" style="height: 160px"></div> <div class="item" style="height: 180px"></div> <div class="item" style="height: 140px"></div> <div class="item" style="height: 150px"></div> <div class="item" style="height: 170px"></div> <div class="item" style="height: 170px"></div> <div class="item" style="height: 140px"></div> <div class="item" style="height: 190px"></div> <div class="item" style="height: 170px"></div> <div class="item" style="height: 120px"></div> <div class="item" style="height: 160px"></div> <div class="item" style="height: 180px"></div> <div class="item" style="height: 140px"></div> <div class="item" style="height: 150px"></div> <div class="item" style="height: 170px"></div> <div class="item" style="height: 170px"></div> <span class="item break"></span> <span class="item break"></span> <span class="item break"></span> </div>
źródło
order
właściwości, dzięki czemu wygląda ona tak, jakby elementy przepływały od lewej do prawej. Jednak jego główna sztuczka polega na tymflex-flow: column wrap
, o czym wspomina powyższa odpowiedź. Ponadto nie może przepływać elementów tak, jak robi to prawdziwy mur, np. Jeśli trzeci i czwarty element zmieściłyby się w trzeciej kolumnie, to połączone nie. Ale znowu, jak powiedziałem, wszystko zależy od wymagań, aw tym przypadku (to pytanie) nie zadziała tak, jak się prosi.