Esnek kutu öğeleri sütun modunda sarıldığında, kap genişliğini büyütmez


168

Aşağıdaki gibi çalışması gereken bir iç içe flexbox düzeni üzerinde çalışıyorum:

En dıştaki seviye ( ul#main), daha fazla öğe eklendiğinde sağa doğru genişlemesi gereken yatay bir listedir. Çok büyürse, yatay bir kaydırma çubuğu olmalıdır.

#main {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    /* ...and more... */
}

Bu listenin ( ul#main > li) her öğesinin bir başlığı ( ul#main > li > h2) ve bir iç listesi ( ul#main > li > ul.tasks) vardır. Bu iç liste dikeydir ve gerektiğinde sütunlara sarılmalıdır. Daha fazla sütuna sarılırken, daha fazla öğeye yer açmak için genişliği artmalıdır. Bu genişlik artışı, dış listenin içerdiği öğeye de uygulanmalıdır.

.tasks {
    flex-direction: column;
    flex-wrap: wrap;
    /* ...and more... */
}

Benim sorunum, pencerenin yüksekliği çok küçük olduğunda iç listelerin kaymaması. CSS-Tricks'teki yönergeleri titizlikle takip etmeye çalışırken, tüm esnek özelliklerle çok fazla uğraşmayı denedim , ama şans yok.

Bu JSFiddle şimdiye kadar sahip olduğum şeyi gösteriyor.

Beklenen sonuç (istediğim) :

İstediğim çıktı

Gerçek sonuç (ne elde ederim) :

Mevcut çıkışım

Eski sonuç (2015'te ne aldım) :

Eski çıktım

GÜNCELLEME

Biraz araştırmadan sonra, bu daha büyük bir konu gibi görünmeye başlıyor. Tüm büyük tarayıcılar aynı şekilde davranır ve flexbox tasarımımın iç içe yerleştirilmesiyle hiçbir ilgisi yoktur. Daha basit flexbox sütun düzenleri bile, öğeler sarıldığında listenin genişliğini artırmayı reddeder.

Bu diğer JSFiddle sorunu açıkça göstermektedir. Chrome, Firefox ve IE11'in mevcut sürümlerinde, tüm öğeler doğru bir şekilde sarılır; listenin yüksekliği rowmodda artar , ancak genişliği columnmodda artmaz . Ayrıca, bir columnmodun yüksekliğini değiştirirken hiçbir elemanın anında yeniden akışı yoktur , ancak rowmodda vardır.

Bununla birlikte, resmi özellikler (özellikle örnek 5'e bakın) yapmak istediğim şeyin mümkün olması gerektiğini gösteriyor.

Birisi bu soruna geçici bir çözüm bulabilir mi?

GÜNCELLEME 2

Yeniden boyutlandırma etkinlikleri sırasında çeşitli öğelerin yüksekliğini ve genişliğini güncellemek için JavaScript'i kullanarak çok sayıda denemeden sonra, bu şekilde çözmeye çalışmanın çok karmaşık ve çok fazla sorun olduğu sonucuna vardım. Ayrıca, JavaScript eklemek kesinlikle mümkün olduğunca temiz tutulması gereken flexbox modelini kırıyor.

Şimdilik, overflow-y: autoyerine geri düşüyorum , flex-wrap: wrapböylece iç kap gerektiğinde dikey olarak kayıyor. Güzel değil, ancak en azından kullanılabilirliği çok fazla kırmaması bir yol.


2
Sadece bir sidenote, ancak Chrome'da akışı ayarlanmış bir kabın column wrapsarma sırasında genişliğini genişletmemesine neden olan bir hata var. Daha fazla bilgi için code.google.com/p/chromium/issues/detail?id=247963 adresine bakın .
Gerrit Bertier

Ben de IE11 çalışmak için alınamıyor. Orada, en içteki öğeler sarılır, ancak iç liste ve kabı (dış öğe) genişliklerini arttırmaz. Şu anda iç listelerin kaydırılmasına geri dönüyorum, ancak iyi bir uzun vadeli çözüm değil ve gerçekten bunun için JavaScript eklemekten kaçınmak istiyorum.
Anders Tornblad

Yanıtlar:


171

Sorun

Bu esnek düzende temel bir eksikliğe benziyor.

Sütun yönündeki esnek bir kap, ilave sütunlara uyacak şekilde genişlemeyecektir. (Bu sorun değil flex-direction: row.)

Bu soru birçok kez sorulmuştur (aşağıdaki listeye bakınız), CSS'de net cevaplar yoktur.

Sorun tüm büyük tarayıcılarda oluştuğu için bunu bir hata olarak sabitlemek zordur. Ama şu soruyu gündeme getiriyor:

Tüm büyük tarayıcıların esnek kabın satır yönünde genişlemesini ancak sütun yönünde olmamasını nasıl sağlarım?

Bunlardan en az birinin doğru olduğunu düşünürdünüz. Sadece neden üzerinde spekülasyon yapabilirim. Belki teknik olarak zor bir uygulamaydı ve bu tekrar için rafa kaldırıldı.

GÜNCELLEME: Sorun Edge v16'da giderilmiş gibi görünüyor.


Problemin İllüstrasyonu

OP sorunu gösteren faydalı bir demo hazırladı. Buradan kopyalıyorum: http://jsfiddle.net/nwccdwLw/1/


Geçici Çözüm Seçenekleri

Stack Overflow topluluğundan Hacky çözümleri:


Daha Fazla Analiz


Aynı Sorunu Açıklayan Diğer Yayınlar


2
Hata raporu yorumlarına göre, yeni düzen motorları LayoutNG
Ben.12

5
Sağladığınız ve kategorilere ayırdığınız bağlantıların sayısı gerçekten harika. Çoğu insanın bu şekilde cevap yazmasını diliyorum. Mükemmel cevap.
Vignesh

4
İşte onlar için birkaç Flexbox hata ve geçici çözümleri listeleyen yararlı bir repo: Bu hata # 14
Ben.12

CSS ızgarasını kullanarak bu sorunu çözebilir miyiz?
Ismail Farooq

bir başka geçici çözüm seçeneği: codepen.io/_mc2/pen/PoPmJRP Bazı açılardan yazma modu yaklaşımını daha iyi buldum
michalczerwinski

38

Partiye geç kaldı, ancak yıl sonra hala bu konuya giriyordu. Izgara kullanarak bir çözüm bulma sona erdi. Konteyner üzerinde kullanabilirsiniz

display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(6, auto);

CodePen üzerinde flexbox sorunu ve ızgara düzeltme arasında geçiş yapan bir örnek var: https://codepen.io/MandeeD/pen/JVLdLd


1
Şimdiye kadar gördüğümde bu zarif bir çözüm! Sadece şebekeye giriyorum ve çözümünüzü seviyorum, bunun için teşekkür ederim.
Albert

Bulun! Sorunumu çözdü.
Celestin Bochis

Chrome'da bu sorunla ilgili sorun devam ediyor. Bir ızgara geçici çözüm kullanmaktan kaçınmayı umuyordum. Başkalarının bu yaklaşımı kullandığını bilmek güzel!
trukvl

hayat kurtarıcı. Daha grid-row-end: span X;fazla satır almak için bazı öğelere ihtiyacınız varsa da kullanabilirsiniz .
Meirion Hughes

0

Birçok büyük tarayıcının yıllar sonra bu hatadan muzdarip olması talihsiz bir durumdur. Bir Javascript geçici çözümü düşünün. Tarayıcı penceresi yeniden boyutlandırıldığında veya öğeye içerik eklendiğinde, uygun genişliğe yeniden boyutlandırılmasını sağlamak için bu kodu yürütün. Bunu yapmak için çerçevenizde bir yönerge tanımlayabilirsiniz.

    element.style.flexBasis = "auto";
    element.style.flexBasis = `${element.scrollWidth}px`;

0

Burada gerçekten harika bir SAF CSS çözümü buldum.

https://jsfiddle.net/gcob492x/3/

Zor: writing-mode: vertical-lrlist div writing-mode: horizontal-tböğesinde, sonra list öğesinde ayarlanır . Ben JSFiddle stilleri tweak gerekiyordu (çözüm için gerekli olmayan hizalama stilleri, bir sürü kaldırmak).

Not: Yorum, Firefox'ta değil, yalnızca Chromium tabanlı tarayıcılarda çalıştığını söylüyor. Yalnızca kişisel olarak Chrome'da test ettim. Diğer tarayıcılarda çalışmasını sağlamak için bunu değiştirmenin bir yolu var ya da söz konusu tarayıcılarda bu işi yapan güncellemeler var.

Bu yoruma büyük açıklama: Flexbox öğeleri sütun modunda sarıldığında, kap genişliği genişlemez . Bu konu dizisini incelemek beni https://bugs.chromium.org/p/chromium/issues/detail?id=507397#c39 adresine yönlendirdi, bu da beni bu JSFiddle'a götürdü.


-1

Henüz bir çözüm veya uygun bir çözüm önerilmediğinden, istenen davranışı biraz farklı bir yaklaşımla elde etmeyi başardım. Düzeni 3 farklı div'e ayırmak yerine, tüm öğeleri 1 div'e ekliyorum ve aradaki daha fazla div ile ayırma oluşturuyorum.

Önerilen çözüm sabit kodlanmıştır, 3 bölümümüz olduğu varsayılarak genel bir bölüme genişletilebilir. Ana fikir, bu düzeni nasıl başarabileceğimizi açıklamaktır.

  1. Tüm öğeleri öğeleri sarmak için flex kullanan 1 konteyner div içine ekleme
  2. Her "iç kabın" ilk öğesi (buna bir bölüm diyeceğim), her bölümün ayrılmasını ve stilini oluşturan bazı manipülasyonlar yapmamıza yardımcı olan bir sınıfa sahip olacaktır.
  3. :beforeHer ilk öğeyi kullanarak , her bölümün başlığını bulabiliriz.
  4. Kullanımı spacebölümler arasındaki boşluğu oluşturur
  5. Beri spaceben de ekliyorum bölümün tam yüksekliğini karşılamayacaktır :aftermutlak pozisyon ve beyaz arka plan ile konumlandırma böylece bölümlere.
  6. Her bölümün arka plan rengini biçimlendirmek için her bölümün ilk öğesinin içine başka bir div ekliyorum. Ben de mutlak bir pozisyonda olacağım vez-index: -1 .
  7. Her bir arka planın doğru genişliğini elde etmek için JS kullanıyorum, doğru genişliği ayarlıyorum ve ayrıca yeniden boyutlandırmak için bir dinleyici ekliyorum.

function calcWidth() {
  var size = $(document).width();
  var end = $(".end").offset().left;

  var todoWidth = $(".doing-first").offset().left;
  $(".bg-todo").css("width", todoWidth);

  var doingWidth = $(".done-first").offset().left - todoWidth;
  $(".bg-doing").css("width", doingWidth);

  var doneWidth = $(".end").offset().left - $(".done-first").offset().left;
  $(".bg-done").css("width", doneWidth + 20);

}

calcWidth();

$(window).resize(function() {
  calcWidth();
});
.container {
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  height: 120px;
  align-content: flex-start;
  padding-top: 30px;
  overflow-x: auto;
  overflow-y: hidden;
}

.item {
  width: 200px;
  background-color: #e5e5e5;
  border-radius: 5px;
  height: 20px;
  margin: 5px;
  position: relative;
  box-shadow: 1px 1px 5px 0px rgba(0, 0, 0, 0.75);
  padding: 5px;
}

.space {
  height: 150px;
  width: 10px;
  background-color: #fff;
  margin: 10px;
}

.todo-first:before {
  position: absolute;
  top: -30px;
  height: 30px;
  content: "To Do (2)";
  font-weight: bold;
}

.doing-first:before {
  position: absolute;
  top: -30px;
  height: 30px;
  content: "Doing (5)";
  font-weight: bold;
}

.doing-first:after,
.done-first:after {
  position: absolute;
  top: -35px;
  left: -25px;
  width: 10px;
  height: 180px;
  z-index: 10;
  background-color: #fff;
  content: "";
}

.done-first:before {
  position: absolute;
  top: -30px;
  height: 30px;
  content: "Done (3)";
  font-weight: bold;
}

.bg-todo {
  position: absolute;
  background-color: #FFEFD3;
  width: 100vw;
  height: 150px;
  top: -30px;
  left: -10px;
  z-index: -1;
}

.bg-doing {
  position: absolute;
  background-color: #EFDCFF;
  width: 100vw;
  height: 150px;
  top: -30px;
  left: -15px;
  z-index: -1;
}

.bg-done {
  position: absolute;
  background-color: #DCFFEE;
  width: 10vw;
  height: 150px;
  top: -30px;
  left: -15px;
  z-index: -1;
}

.end {
  height: 150px;
  width: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">

  <div class="item todo-first">
    <div class="bg-todo"></div>
    Drink coffee
  </div>
  <div class="item">Go to work</div>

  <div class="space"></div>

  <div class="item doing-first">
    <div class="bg-doing"></div>
    1
  </div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>

  <div class="space"></div>

  <div class="item done-first">
    <div class="bg-done"></div>
    1
  </div>
  <div class="item">2</div>
  <div class="item">3</div>

  <div class="end"></div>

</div>


-2

Olası JS çözümü ..

var ul = $("ul.ul-to-fix");

if(ul.find("li").length>{max_possible_rows)){
    if(!ul.hasClass("width-calculated")){
        ul.width(ul.find("li").eq(0).width()*ul.css("columns"));
        ul.addClass("width-calculated");
     }
}

Bu, maalesef, bireysel unsurların yükseklikleri değişebileceğinden yardımcı olmaz. Öyleyse eleman sayısı ilginç değil ... Ancak columnsstyle özelliğini kullanmak, çalışan bir çözüm için bir başlangıç ​​noktası olabilir. Belki de sütun sayısını ayarlayarak ve ul genişliğini.
Anders Tornblad

1
Ayrıca üzerinde çalıştığım bir React uygulaması için bu soruna bir JS çözümü ile gidiş sona erdi. Her boyutta ve değişen boyutta elemanlarla çalışmak üzere tasarlanmıştır. Burada örnek: djskinner.github.io/react-column-wrap . Kaynak kodu burada: github.com/djskinner/react-column-wrap
djskinner
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.