Esnek bir kap nasıl ortalanır, ancak esnek öğeler nasıl sola hizalanır


91

Esnek öğelerin ortalanmasını istiyorum, ancak ikinci bir çizgimiz olduğunda, 5'in (aşağıdaki görüntüden) 1'in altında olmasını ve üst öğede ortalanmamasını istiyorum.

görüntü açıklamasını buraya girin

İşte sahip olduğum şeylere bir örnek:

ul {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  margin: 0;
  padding: 0;
}
li {
  list-style-type: none;
  border: 1px solid gray;
  margin: 15px;
  padding: 5px;
  width: 200px;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

http://jsfiddle.net/8jqbjese/2/

Yanıtlar:


79

Flexbox Zorluğu ve Sınırlaması

Buradaki zorluk, bir grup esnek öğeyi ortalamak ve bunları sarmada sola hizalamaktır. Ancak, satır başına sabit sayıda kutu olmadığı ve her kutu sabit genişlikte olmadığı sürece, bu şu anda flexbox ile mümkün değildir.

Söz konusu yayınlanmıştır kodu kullanarak, mevcut esnek kabı (sarar yeni esnek konteyner yaratabilir ulbizi ortalamak için izin verecek), ulile justify-content: center.

Daha sonra esnek öğeler ulile sola hizalanabilir justify-content: flex-start.

#container {
    display: flex;
    justify-content: center;
}

ul {
    display: flex;
    justify-content: flex-start;
}

Bu, ortalanmış bir sola hizalı esnek öğeler grubu oluşturur.

Bu yöntemle ilgili sorun, belirli ekran boyutlarında sağ tarafında ulartık ortalanmış görünmeyen bir boşluk oluşmasıdır .

görüntü açıklamasını buraya girin görüntü açıklamasını buraya girin

Bunun nedeni, esnek mizanpajda (ve aslında genel olarak CSS'de) kap:

  1. bir öğenin ne zaman sarmalandığını bilmez;
  2. önceden işgal edilmiş bir alanın artık boş olduğunu bilmiyor ve
  3. dar düzeni daraltmak için genişliğini yeniden hesaplamaz.

Sağdaki beyaz alanın maksimum uzunluğu, kabın orada olmasını beklediği esnek öğenin uzunluğudur.

Aşağıdaki demoda, pencereyi yatay olarak yeniden boyutlandırarak beyaz alanın gelip gittiğini görebilirsiniz.

DEMO


Daha Pratik Bir Yaklaşım

Flexbox kullanmadan inline-blockve ortam sorguları olmadan istenen düzen elde edilebilir .

HTML

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
</ul>

CSS

ul {
    margin: 0 auto;                  /* center container */
    width: 1200px;
    padding-left: 0;                 /* remove list padding */
    font-size: 0;                    /* remove inline-block white space;
                                        see https://stackoverflow.com/a/32801275/3597276 */
}

li {
    display: inline-block;
    font-size: 18px;                 /* restore font size removed in container */
    list-style-type: none;
    width: 150px;
    height: 50px;
    line-height: 50px;
    margin: 15px 25px;
    box-sizing: border-box;
    text-align: center;
}

@media screen and (max-width: 430px) { ul { width: 200px; } }
@media screen and (min-width: 431px) and (max-width: 630px) { ul { width: 400px; } }
@media screen and (min-width: 631px) and (max-width: 830px) { ul { width:600px;  } }
@media screen and (min-width: 831px) and (max-width: 1030px) { ul { width: 800px; } }
@media screen and (min-width: 1031px) and (max-width: 1230px) { ul { width: 1000px; } }

Yukarıdaki kod, aşağıdaki gibi sola hizalanmış alt öğelere sahip yatay olarak ortalanmış bir kap oluşturur:

görüntü açıklamasını buraya girin

DEMO


Diğer seçenekler


3
Evet, insanların yapmak istedikleri ve sonunda flexbox'ı kullanmak istediklerinin çoğu aslında sadece bir ızgara oluşturmaktır. Neyse ki, bu erişim daha kesin hale geldiğinde bu CSS Izgaraları tarafından ele alınacaktır.
TylerH

1
Bu gönderiyi sizinkine bağladı. Aynı sorunun nasıl çözüleceğine dair bir sürüm daha var, yine de, bir dupe olabilir, bu yüzden bir göz atın ve bu şekilde kapatmak isteyip istemediğinize kendiniz karar verin. Ve bu büyük açıklama için artı 1.
Ason

Belki de başka bir fikir, margin:0 autoher şeyin sayfada ortalanması için bir ebeveyn sarıcı üzerinde yapmaktır . Bu noktadan sonra, tüm alt bileşenler (yani ilk esnek-kapsayıcı) normal akış sırası sürecini mi sürdürüyor? Görünüşe göre bu basit hale getirilebilir.
klewis

12

Bunu CSS Grid ile elde edebilirsiniz, sadece kullanın repeat(autofit, minmax(width-of-the-element, max-content))

ul {
       display: grid;
       grid-template-columns: repeat(auto-fit, minmax(210px, max-content));
       grid-gap: 16px;
       justify-content: center;
       padding: initial;
}

li {
    list-style-type: none;
    border: 1px solid gray;
    padding: 5px;
    width: 210px;
}
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
</ul>

http://jsfiddle.net/rwa20jkh/


İlginç. Ancak sağdaki boşluğu ortadan kaldırmaz veya ızgarayı ortalamaz
Kırmızı

2
@Red Bir sorun vardı. Değiştim justify-items: centeriçin justify-content:centerve şimdi mükemmel ortalar.
Joe82

210pxİçerideki kısmı anlamıyorum minmax. Yapay bir kısıtlama olmadan aynı şeyi nasıl yapabilirim 210px? Flexbox ile böyle bir kısıtlama yoktur. Flexbox ile tamamen aynı sonucu istiyorum, ancak içerik alanı çözümünüzdeki gibi ortalanmalıdır.
Andrey Mikhaylov - lolmaus

1
Merhaba @ AndreyMikhaylov-lolmaus, bu yöntem, tüm öğelere sabit bir genişlik ayarlamak istediğinizde çalışır. Söz olarak, olarak ifade edilir width:200pxBen belirtildiği gibi, ve benim örnekte width:210px, söylemek zorunda iyi olduğu gibi minmaxkısmen
Joe82

@ Joe82 Açıklığa kavuşturduğunuz için teşekkürler! 🙏 Keyfi genişlikteki öğeler için çalışmasını sağlamanın bir yolunu biliyor musunuz?
Andrey Mikhaylov - lolmaus

0

@Michael'ın önerdiği gibi, bu mevcut flexbox ile bir sınırlamadır. Ama yine de flexve kullanmak istiyorsanız justify-content: center;, bunu bir kukla lieleman ekleyerek ve atayarak çözebiliriz margin-left.

    const handleResize = () => {
        const item_box = document.getElementById('parentId')
        const list_length  = item_box.clientWidth
        const product_card_length = 200 // length of your child element
        const item_in_a_row = Math.round(list_length/product_card_length)
        const to_be_added = item_in_a_row - parseInt(listObject.length % item_in_a_row) // listObject is the total number items
        const left_to_set = (to_be_added - 1 ) * product_card_length // -1 : dummy item has width set, so exclude it when calculating the left margin 
        const dummy_product = document.querySelectorAll('.product-card.dummy')[0]
        dummy_product.style.marginLeft = `${left_to_set}px`
    }
    handleResize() // Call it first time component mount
    window.addEventListener("resize", handleResize); 

Referans için bu keman (yeniden boyutlandırın ve görün) veya videoyu kontrol edin


0

İstenilen stili kenar boşluklarıyla elde etmenin bir yolu, aşağıdakileri yapmaktır:

#container {
    display: flex;
    justify-content: center;
}

#innercontainer {
    display: flex;
    flex: 0.9; -> add desired % of margin
    justify-content: flex-start;
}

0

Diğerleri ile aynı sınıfa sahip görünmez öğeleri yerleştirebilirsiniz (örneğin, sergileme amacıyla kaldırılmıştır) ve yüksekliği 0'a ayarlanmıştır. Bununla, öğeleri ızgaranın en başına hizalayabilirsiniz.

Misal

<div class="table-container">
  <div class="table-content">
    <p class="table-title">Table 1</p>
    <p class="mesa-price">$ 20</p>
  </div>
  
  <!-- Make stuff justified start -->
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
</div>

Sonuç

görüntü açıklamasını buraya girin


-1

React Native ile kodlama yaparken bu problemle karşılaştım. FlexBox kullanarak sahip olabileceğiniz zarif bir çözüm var. Benim özel durumumda, alignItems kullanarak üç esnek kutuyu (Flex: 2) başka birinin içine ortalamaya çalışıyordum. Bulduğum çözüm, her biri Flex: 1 içeren iki boş s kullanmaktı.

<View style={{alignItems: 'center', flexWrap: 'wrap', flexDirection: 'row'}}>
  <View style={{flex: 1}} />
    // Content here
  <View style={{flex: 1}} />
</View>

Web / CSS'ye dönüştürmek için yeterince kolay.


Soruyu yanlış anladınız. OP 3 öğenin nasıl ortalanacağını sormaz, tüm öğeler bir grup olarak ortalanırken öğeleri 2. satırda nasıl bırakacaklarını sorarlar ve bunun için çözümünüz çalışmaz.
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.