Yalnızca CSS duvar düzeni


134

Oldukça sıradan bir duvar düzeni uygulamam gerekiyor. Ancak, birkaç nedenden dolayı bunu yapmak için JavaScript kullanmak istemiyorum.

Değişken yüksekliğe sahip dikdörtgenlerin birden çok sütunundan oluşan bir ızgara.

Parametreler:

  • Tüm elemanlar aynı genişliğe sahiptir
  • Öğelerin, sunucu tarafında hesaplanamayan bir yüksekliği vardır (bir görüntü artı çeşitli miktarlarda metin)
  • Mecbur kalırsam sabit sayıda sütunla yaşayabilirim

modern tarayıcılarda, çalışan bu önemsiz bir çözüm yoktur mülkiyet.column-count

Bu çözümle ilgili sorun, öğelerin sütunlarda sıralanmasıdır:

En soldaki kutudan başlayarak, aşağıya doğru 1'den 4'e kadar numaralandırılırlar, bir sonraki sütundaki en üstteki kutu 5'tir vb.

Öğelerin satırlar halinde sıralanmasına ihtiyacım olsa da, en azından yaklaşık olarak:

En soldaki kutudan başlayarak, 1'den 6'ya kadar numaralandırılırlar, ancak kutu 5'in altındaki en kısa kutu olduğu için, en soldaki sonraki kutudan daha yüksek bir sıra üzerinde göründüğü için 7'dir.

Denediğim yaklaşımlar işe yaramıyor:

Şimdi olabilir İsterdim yüzden, hataya açık (tarayıcılar sütunlar halinde öğe listesini bölmek karar şekline göre), sunucu tarafında oluşturma ve sütun sayısına göre öğelerin sayısına bölünmesi sipariş öğeleri değiştirmek, ama bu karışık mümkünse önlemek için.

Bunu mümkün kılan yeni çıkmış flexbox büyüsü var mı?


7
Önceden tanımlanmış yüksekliklere bağlı olmayan bir yol düşünemiyorum. JS'yi yeniden düşünürseniz , oldukça basit olan böyle bir çözümü uyguladığım stackoverflow.com/questions/13518653/… adresine bir göz atın .
Gabriele Petrioli

1
@Gaby şu anda çözümünüzü uyguluyor, teşekkür ederim!
Pekka

4
Sadece CSS dediğini anladım. Sadece Masonry'nin artık jQuery gerektirmediğini (küçültülmüş kütüphane 8kb'nin altında) ve sadece html ile başlatılabileceğini belirtmek istiyorum . Sadece referans için jsfiddle.net/wp7kuk1t
59'da kode

1
Satır yüksekliğini, yazı tipi boyutunu (belirli bir yazı tipini sunmanız ve bazı akıllı hesaplamalar yapmanız gerekir), görüntü yüksekliğini, dikey kenar boşluğunu ve dolguyu bilerek öğelerin yüksekliğini önceden belirleyebilirseniz, Bunu yap. Aksi takdirde, bunu yalnızca CSS kullanarak yapamazsınız. Ayrıca, her bir öğeyi önceden işlemek ve bu öğenin yüksekliğini elde etmek için PhantomJS gibi bir şey de kullanabilirsiniz, ancak önemli ek yük / gecikme eklenebilir.
Timothy Zorn

Yanıtlar:


157

flexbox'a

Flexbox ile dinamik bir duvar düzeni, en azından temiz ve verimli bir şekilde mümkün değildir.

Flexbox tek boyutlu bir yerleşim sistemidir. Bu, öğeleri yatay VEYA dikey çizgiler boyunca hizalayabileceği anlamına gelir. Bir esnek öğe, kendi satırı veya sütunuyla sınırlıdır.

Gerçek bir ızgara sistemi iki boyutludur, yani öğeleri yatay VE dikey çizgiler boyunca hizalayabilir. İçerik öğeleri, aynı anda satırlara ve sütunlara yayılabilir, bu esnada esnek öğeler bunu yapamaz.

Flexbox'ın ızgaralar oluşturmak için sınırlı bir kapasiteye sahip olmasının nedeni budur. W3C'nin başka bir CSS3 teknolojisi olan Grid Layout'u geliştirmesinin de bir nedeni bu .


row wrap

Bir esnek kapta flex-flow: row wrap, esnek öğeler yeni satırlara sarılmalıdır .

Bu, bir esnek öğenin aynı satırdaki başka bir öğenin altına sarılamayacağı anlamına gelir .

Div # 3'ün nasıl yeni bir satır oluşturarak div # 1'in altına sarıldığına dikkat edin . Div # 2'nin altına sarılamaz .

Sonuç olarak, öğeler satırdaki en uzun değilse, beyaz boşluk kalır ve çirkin boşluklar oluşturur.


column wrap

Geçiş yaparsanız flex-flow: column wrap, ızgara benzeri bir düzen daha elde edilebilir. Bununla birlikte, sütun yönündeki bir konteynerin hemen hemen dört potansiyel sorunu vardır:

  1. Flex öğeleri yatay olarak değil dikey olarak akar (bu durumda ihtiyacınız olduğu gibi).
  2. Kap, dikey olarak değil (Pinterest düzeni gibi) yatay olarak genişler.
  3. Kabın sabit bir yüksekliğe sahip olmasını gerektirir, böylece öğeler nereye sarılacağını bilir.
  4. Bu yazı itibariyle , kapsayıcının ek sütunları barındırmak için genişlemediği tüm büyük tarayıcılarda bir eksikliğe sahiptir .

Sonuç olarak, sütun yönlü bir kap bu durumda ve diğer birçok durumda bir seçenek değildir.


Öğe boyutları tanımlanmamış CSS Izgarası

Izgara Düzeni , içerik öğelerinin çeşitli yükseklikleri önceden belirlenebiliyorsa , sorununuz için mükemmel bir çözüm olacaktır . Diğer tüm gereksinimler Grid'in kapasitesi dahilindedir.

Çevreleyen öğelerle boşlukları kapatmak için ızgara öğelerinin genişliği ve yüksekliği bilinmelidir.

Dolayısıyla, yatay akan bir duvar düzeni oluşturmak için CSS'nin sunduğu en iyi olan Grid, bu durumda yetersiz kalıyor.

Aslında, boşlukları otomatik olarak kapatabilen bir CSS teknolojisi gelene kadar, genel olarak CSS'nin bir çözümü yoktur. Bunun gibi bir şey muhtemelen belgenin yeniden düzenlenmesini gerektirecektir, bu nedenle ne kadar yararlı veya verimli olacağından emin değilim.

Bir senaryoya ihtiyacınız olacak.

JavaScript çözümleri, içerik öğelerini boşluk olmadan yeniden düzenlemek için belge akışından kaldıran mutlak konumlandırma kullanma eğilimindedir. İşte iki örnek:


Öğe boyutları tanımlanmış CSS Izgarası

İçerik öğelerinin genişliğinin ve yüksekliğinin bilindiği mizanpajlar için, saf CSS'de yatay olarak akan bir duvar mizanpajı:

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 demosu


Nasıl çalışır

  1. Blok düzeyinde bir ızgara konteyneri oluşturun. ( inline-griddiğer seçenek olabilir)
  2. grid-auto-rowsMülkiyet otomatik olarak oluşturulan satırların yüksekliğini ayarlar. Bu ızgarada her satır 50 piksel uzunluğundadır.
  3. grid-gapMülkiyet için bir kısaltmadır grid-column-gapve grid-row-gap. Bu kural, ızgara öğeleri arasında 10 piksellik bir boşluk ayarlar . (Öğeler ve kap arasındaki alan için geçerli değildir.)
  4. grid-template-columnsMülkiyet açıkça tanımlanmış sütunların genişliğini ayarlar.

    repeatNotasyonu tekrar sütunların (ya da sıraların) bir model tanımlar.

    auto-fillİşlev kabı taşan mümkün olduğu kadar çok sayıda sütun (veya satır) hizalamak için kılavuz anlatır. (Bu, esnek düzenlere benzer bir davranış oluşturabilir flex-wrap: wrap.)

    minmax()Fonksiyon her bir kolonu (ya da arka arkaya) için minimum ve maksimum boyut aralığını belirler. Yukarıdaki kodda, her bir sütunun genişliği, kabın minimum% 30'u ve mevcut boş alanın maksimum genişliği olacaktır.

    frBirim ızgara kabında boş alan bir bölümünü temsil eder. Flexbox'ın flex-growmülkü ile karşılaştırılabilir .

  5. İle grid-rowve spangrid öğelerine kaç satır yayılmaları gerektiğini söylüyoruz.


CSS Grid için Tarayıcı Desteği

  • Chrome - 8 Mart 2017 itibarıyla tam destek (sürüm 57)
  • Firefox - 6 Mart 2017 itibarıyla tam destek (sürüm 52)
  • Safari - 26 Mart 2017 itibarıyla tam destek (sürüm 10.1)
  • Edge - 16 Ekim 2017 itibarıyla tam destek (sürüm 16)
  • IE11 - mevcut spesifikasyon desteği yok; eski sürümü destekler

İşte resmin tamamı: http://caniuse.com/#search=grid


Firefox'ta harika ızgara yer paylaşımı özelliği

Firefox geliştirme araçlarında, ızgara kabını incelediğinizde, CSS bildiriminde küçük bir ızgara simgesi vardır. Tıklandığında, sayfada kılavuzunuzun bir taslağını görüntüler.

Daha fazla ayrıntı burada: https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Examine_grid_layouts


5
Harika cevap! "Öğe boyutları tanımlanmış CSS Izgarası" çözümüyle, bir hücrenin yüksekliğini hücre genişliğinin yüzdesi olarak ifade etmek mümkün müdür? Bu, en boy oranının bilindiği görüntüleri görüntülemek için yararlı olacaktır. En boy oranını her zaman korumak istiyoruz.
Oliver Joseph Ash

Teşekkürler. Görüntüler için en boy oranı sorunu ile ilgili olarak, "hücre genişliğinin yüzdesi" yöntemi (yüzde dolgu hilesi?), Grid veya Flexbox'ta bu konuda güvenilir değildir. Buraya ve buraya bakın . @OliverJosephAsh
Michael Benjamin

Evet, yüzde doldurma numarasına atıfta bulunuyorum. Duvar düzeni çözümünüzle birlikte geçici çözümlerden herhangi birini kullanmak mümkün mü? Bağlam için, unsplash.com'daki resimler için yalnızca CSS duvar düzeni uygulamak istiyoruz .
Oliver Joseph Ash

1
Maalesef bunun için JS kullanmak bir seçenek değil. Performans ve SEO nedenleriyle sunucu tarafı oluşturmayı etkinleştirmek istiyoruz. Bu, mizanpajın istemci tarafı JavaScript indirilmeden, ayrıştırılmadan ve yürütülmeden önce oluşturulması gerektiği anlamına gelir. Bunun imkansız olduğu göz önüne alındığında, hat üzerinde bir yerden bir ticaret yapmamız gerekecek! Yardımınız için teşekkürler :-)
Oliver Joseph Ash

1
Spesifikasyon Güncellemesi: Flexbox'ta, yüzde marjları ve dolgular artık konteynerin satır içi boyutunu yeniden çözmek için ayarlandı. drafts.csswg.org/css-flexbox/#item-margins @OliverJosephAsh
Michael Benjamin

13

Bu, flexbox'ı içeren yakın zamanda keşfedilen bir tekniktir: https://tobiasahlin.com/blog/masonry-with-css/ .

Makale bana mantıklı geliyor, ancak onu kullanmayı denemedim, bu yüzden Michael'ın cevabında belirtilenler dışında herhangi bir uyarı var mı bilmiyorum.

İşte makaleden bir örnek, ordermülkün kullanımıyla birlikte :nth-child.

Yığın snippet

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


Öncelikle, bağlantı yalnızca yanıtlar kötüdür, örneğin bu tür bağlantı öldüğünde yanıt da öyle. İkincisi, verilen cevabı daha dikkatli okursanız, bağlantınızda bahsedilenlerin kapsanmış olduğunu göreceksiniz. Basitçe söylemek gerekirse, yukarıda bahsedilen bir sorun olmadığı sürece, Flexbox'ı tek başına kullanırken çok fazla sınırlama vardır.
Ason

3
Kabul edilen cevabı iyice okudum - altına eklediğim bazı yorumları bile göreceksiniz. Bağlandığım flexbox yaklaşımı benzersizdir ve bu yanıtın kapsamına girmez. Makaleyi tekrarlamak istemiyorum çünkü çok karmaşık ve makale bunu örtmek için harika bir iş çıkarıyor.
Oliver Joseph Ash

Bağlantının farklı yaptığı tek şey, ordermülkten yararlanmak ve nesnelerin soldan sağa doğru akıyor gibi görünmesini sağlamaktır. Yine de, ana püf noktası flex-flow: column wrap, yukarıdaki cevapta belirtilen. Buna ek olarak, öğeleri gerçek bir duvarın yaptığı gibi akıtamaz, örneğin 3. ve 4. öğe 3. sütuna sığarsa, yapar, bağlantılı olan olmaz. Ama yine söylediğim gibi, her şey gereksinimlerin ne olduğuna bağlı ve bu durumda (bu soru), istenen şekilde çalışmayacak.
Ason

Dahası, mesele "makaleyi tekrarlamak istemezsiniz" ile ilgili değildir , bir cevap kodun temel kısmını içermelidir, böylece bağlantılı kaynak öldüğünde hala geçerli olacaktır.
Ason

3
Onu güncelledim, makaleden bir örnek + bir oy ekledim.
Ason
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.