Yan öğeler farklı genişliklere sahip olduğunda orta öğeyi ortada tutun


162

resim açıklamasını buraya girin

Noktaların kutular arasındaki boşluğu temsil ettiği aşağıdaki düzeni düşünün:

[Left box]......[Center box]......[Right box]

Sağ kutuyu kaldırdığımda, orta kutunun hala merkezde olmasını istiyorum, şöyle:

[Left box]......[Center box].................

Sol kutuyu kaldıracaksam da aynı şey geçerli.

................[Center box].................

Artık orta kutudaki içerik uzadığında, ortalanmış olarak kalırken gerektiği kadar kullanılabilir alan kaplar. Sol ve sağ kutu asla büzülmez ve böylece boş alan kalmadığında overflow:hiddenve text-overflow: ellipsisiçeriği kırmak için devreye girer;

[Left box][Center boxxxxxxxxxxxxx][Right box]

Yukarıdakilerin hepsi benim ideal durumum, ancak bu etkiyi nasıl başaracağım konusunda hiçbir fikrim yok. Çünkü böyle esnek bir yapı oluşturduğumda:

.parent {
    display : flex; // flex box
    justify-content : space-between; // horizontal alignment
    align-content   : center; // vertical alignment
}

Sol ve sağ kutu tam olarak aynı boyutta olursa, istenen efekti elde ederim. Ancak ikisinden biri farklı boyuttaysa, ortalanmış kutu artık tam olarak ortalanmamıştır.

Bana yardım edebilecek biri var mı?

Güncelleme

A iyi justify-selfolurdu, bu ideal olurdu:

.leftBox {
     justify-self : flex-start;
}

.rightBox {
    justify-self : flex-end;
}

3
Temel olarak ... yapamazsınız. Bu flexboxşekilde çalışması gerekmiyor. Başka bir metodoloji deneyebilirsiniz.
Paulie_D

1
Tho olsaydı gerçekten flexbox tamamlayacaktı. Çünkü flexbox tamamen alan dağıtmak ve öğelerin nasıl davrandığıyla ilgilidir.
Mark

1
justify-selfBugün daha önce tartıştık , bu yüzden bu ilginç bulabilirsiniz: stackoverflow.com/questions/32551291/…
Michael Benjamin

Yanıtlar:


130

Sol ve sağ kutular tam olarak aynı boyutta olursa, istenen efekti elde ederim. Ancak, ikisinden biri farklı boyutta olduğunda, ortalanmış kutu artık tam olarak ortalanmamıştır. Bana yardım edebilecek biri var mı?

Kardeşlerin genişliğinden bağımsız olarak orta öğeyi ortalamak için flexbox kullanan bir yöntem.

Ana Özellikler:

  • saf CSS
  • mutlak konumlandırma yok
  • JS / jQuery yok

İç içe geçmiş esnek kaplar ve autokenar boşlukları kullanın :

.container {
  display: flex;
}
.box {
  flex: 1;
  display: flex;
  justify-content: center;
}

.box:first-child > span { margin-right: auto; }

.box:last-child  > span { margin-left: auto;  }

/* non-essential */
.box {
  align-items: center;
  border: 1px solid #ccc;
  background-color: lightgreen;
  height: 40px;
}
p {
  text-align: center;
  margin: 5px 0 0 0;
}
<div class="container">
  <div class="box"><span>short text</span></div>
  <div class="box"><span>centered text</span></div>
  <div class="box"><span>loooooooooooooooong text</span></div>
</div>
<p>&#8593;<br>true center</p>

Şöyle çalışır:

  • Üst düzey div ( .container) esnek bir kaptır.
  • Her alt div ( .box) şimdi esnek bir öğedir.
  • Her .boxmadde flex: 1konteyner alanını eşit olarak dağıtmak için verilmiştir ( daha fazla detay ).
  • Şimdi öğeler sıradaki tüm alanı tüketiyor ve eşit genişlikte.
  • Her öğeyi (iç içe) esnek bir kap yapın ve ekleyin justify-content: center.
  • Şimdi her spanöğe ortalanmış bir esnek öğedir.
  • autoDış spantarafları sola ve sağa kaydırmak için esnek kenar boşluklarını kullanın .

Ayrıca, yalnızca kenar boşluklarını kaldırabilir justify-contentve kullanabilirsiniz auto.

Ancak justify-contentburada çalışabilir, çünkü autokenar boşlukları her zaman önceliğe sahiptir.

8.1. auto Kenar boşluklarıyla hizalama

İle hizalanabilmektedir önce justify-contentve align-selfherhangi bir pozitif serbest alanının boyutunun otomatik kenar dağıtılır.


5
Bu çözümler widthbelirtilmesine izin vermiyor
Alex G

@AlexG, nasıl yani? Bir örnek verebilir misiniz?
Michael Benjamin

4
Alanı dağıtmak için esnek elemanların genişliklerini değiştirmek OP'nin sorusunu tamamen kaçırır. Sorularının öğeler arasında boşluk var. Örn: "Noktaların kutular arasındaki boşluğu temsil ettiği aşağıdaki düzeni düşünün." Metni eşit boyutta 3 öğede ortalamak önemsizdir.
Leland

1
Yemin ederim, seni şimdi öpebilirim! Tam da ihtiyacım olan şeydi ve anlayamadım.
eliotRosewater

1
Bu, MacOS tarzı pencere başlık çubuklarını uygulamak için tam olarak ihtiyacım olanı yaptı. Ekleme white-space: nowrapalan çok küçük aldığında sarma metin önlemek için bulmacanın son parçası idi.
Geo1088

32
  1. Kapta üç esnek eşya kullanın
  2. flex: 1İlk ve sonuncuyu ayarlayın . Bu, ortadaki kalan boş alanı doldurmak için eşit olarak büyümelerini sağlar.
  3. Böylece, ortadaki merkezleme eğilimindedir.
  4. Ancak, ilk veya son öğe geniş bir içeriğe sahipse, bu esnek öğe yeni min-width: autobaşlangıç ​​değeri nedeniyle de büyür .

    Not Chrome bunu gerektiği gibi uygulamıyor. Ancak, ayarlayabilirsiniz min-widthiçin -webkit-max-contentya -webkit-min-contentve çok çalışacaktır.

  5. Sadece bu durumda orta eleman merkezden dışarı itilir.

.outer-wrapper {
  display: flex;
}
.item {
  background: lime;
  margin: 5px;
}
.left.inner-wrapper, .right.inner-wrapper {
  flex: 1;
  display: flex;
  min-width: -webkit-min-content; /* Workaround to Chrome bug */
}
.right.inner-wrapper {
  justify-content: flex-end;
}
.animate {
  animation: anim 5s infinite alternate;
}
@keyframes anim {
  from { min-width: 0 }
  to { min-width: 100vw; }
}
<div class="outer-wrapper">
  <div class="left inner-wrapper">
    <div class="item animate">Left</div>
  </div>
  <div class="center inner-wrapper">
    <div class="item">Center</div>
  </div>
  <div class="right inner-wrapper">
    <div class="item">Right</div>
  </div>
</div>
<!-- Analogous to above --> <div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item animate">Center</div></div><div class="right inner-wrapper"><div class="item">Right</div></div></div><div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item">Center</div></div><div class="right inner-wrapper"><div class="item animate">Right</div></div></div>


Teşekkürler, bu cevap kabul edilen yanıtın aksine OP sorusunu başarıyla cevaplıyor
Blowsie

8

Flexbox'ı kullanmak yerine varsayılan olarak kullanmak, ızgarayı kullanmak, üst düzey çocuklarda ek işaretleme olmadan 2 satır CSS'de çözer.

HTML:

<header class="header">
  <div class="left">variable content</div>
  <div class="middle">variable content</div>
  <div class="right">variable content which happens to be very long</div>
</header>

CSS:

.header {
  display: grid;
  grid-template-columns: [first] 20% auto [last] 20%;
}
.middle {
  /* use either */
  margin: 0 auto;
  /* or */
  text-align: center;
}

Flexbox sallanır, ancak her şeyin cevabı olmamalıdır. Bu durumda ızgara açıkça en temiz seçenektir.

Test keyfiniz için bir kodlama bile yaptı: https://codepen.io/anon/pen/mooQOV


2
+1, flexher şeyden başka seçenekler olabileceğini kabul etmek için. Tek itirazım, align-items: centeröğelerinizin farklı yüksekliklerde olması ve hizalanması gerektiğinde flex ( ) kullanarak dikey hizalamanın daha kolay hale gelmesidir
Felipe

1
Bu çözümü ve bu sorun için ızgara kullanma fikrini seviyorum, ancak çözümünüzün bazı önemli dezavantajları olduğunu düşünüyorum. Birincisi, dış hücrelerin içeriğinden herhangi biri% 20'den büyükse, içerik ya orta hücreye sarılacak ya da taşacaktır. İkincisi, merkez% 60'tan büyükse, içerik kutusunun dışında büyüyecek ve son hücreyi sarabilir veya itebilir. Son olarak, merkez dış hücrelere yer açmak için kaymaz. Sadece sarmaya / taşmaya zorlar. Kötü bir çözüm değil, ama IMO, "açıkça en temiz seçenek" değil.
Chris

6

Bunu şu şekilde yapabilirsiniz:

.bar {
    display: flex;    
    background: #B0BEC5;
}
.l {
    width: 50%;
    flex-shrink: 1;
    display: flex;
}
.l-content {
    background: #9C27B0;
}
.m { 
    flex-shrink: 0;
}
.m-content {    
    text-align: center;
    background: #2196F3;
}
.r {
    width: 50%;
    flex-shrink: 1;
    display: flex;
    flex-direction: row-reverse;
}
.r-content { 
    background: #E91E63;
}
<div class="bar">
    <div class="l">
        <div class="l-content">This is really long content.  More content.  So much content.</div>
    </div>
    <div class="m">
        <div class="m-content">This will always be in the center.</div>
    </div>
    <div class="r">
        <div class="r-content">This is short.</div>
    </div>
</div>


2

İşte flexbox yerine grid kullanan bir cevap. Bu çözüm, HTML'de kabul edilen cevap gibi ekstra torun öğeleri gerektirmez. Ve 2019'daki ızgara cevabının aksine, bir taraftaki içerik merkeze taşacak kadar uzun olduğunda bile doğru çalışır.

Bu çözümün yapmadığı tek şey, soruda açıklandığı gibi bir üç nokta göstermek veya orta kutudaki fazladan içeriği gizlemektir.

section {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
}

section > *:last-child {
  white-space: nowrap;
  text-align: right;
}

/* not essential; just for demo purposes */
section {
  background-color: #eee;
  font-family: helvetica, arial;
  font-size: 10pt;
  padding: 4px;
}

section > * {
  border: 1px solid #bbb;
  padding: 2px;
}
<section>
  <div>left</div>
  <div>center</div>
  <div>right side is longer</div>
</section>

<section>
  <div>left</div>
  <div>center</div>
  <div>right side is much, much longer</div>
</section>

<section>
  <div>left</div>
  <div>center</div>
  <div>right side is much, much longer, super long in fact</div>
</section>


1

İşte bunu display: flexebeveynler ve çocuklarda kullanarak yapmanın başka bir yolu :

.Layout{
    display: flex;
    justify-content: center;
}
.Left{
    display: flex;
    justify-content: flex-start;
    width: 100%;
}
.Right{
    display: flex;
    justify-content: flex-end;
    width: 100%;
}
<div class = 'Layout'>
    <div class = 'Left'>I'm on the left</div>
    <div class = 'Mid'>Centered</div>
    <div class = 'Right'>I'm on the right</div>
</div>


0

orta eleman için tam orta hizalamaya ulaşmak için bu basit yolu da kullanabilirsiniz:

.container {
    display: flex;
    justify-content: space-between;
}

.container .sibling {
    display: flex;
    align-items: center;
    height: 50px;
    background-color: gray;
}

.container .sibling:first-child {
    width: 50%;
    display: flex;
    justify-content: space-between;
}

.container .sibling:last-child {
    justify-content: flex-end;
    width: 50%;
    box-sizing: border-box;
    padding-left: 100px; /* .center's width divided by 2 */
}

.container .sibling:last-child .content {
    text-align: right;
}

.container .sibling .center {
    height: 100%;
    width: 200px;
    background-color: lightgreen;
    transform: translateX(50%);
}

codepen: https://codepen.io/ErAz7/pen/mdeBKLG

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.