Neden CSS'de kenar boşluğu / dolgu yüzdeleri her zaman genişliğe göre hesaplanıyor?


130

CSS kutusu modeli spesifikasyonuna bakarsanız , aşağıdakileri göreceksiniz:

[Kenar boşluğu] yüzdesi, oluşturulan kutunun içeren bloğunun genişliğine göre hesaplanır . Bunun "margin-top" ve "margin-bottom" için de geçerli olduğunu unutmayın. İçeren bloğun genişliği bu elemana bağlıysa, ortaya çıkan düzen CSS 2.1'de tanımsızdır. (vurgu benim)

Bu gerçekten doğrudur. Ama neden ? Kimseyi bu şekilde tasarlamaya ne zorlar ki? İstediğiniz senaryoları düşünmek kolaydır, örneğin belirli bir şeyin her zaman sayfanın üst kısmından% 25 aşağıda olması gerekir, ancak dikey dolgunun yatay boyutuna göre olmasını isteyebileceğiniz herhangi bir neden bulmak zordur. ebeveyn.

İşte bahsettiğim fenomenin bir örneği:

<div style="border: 1px solid red; margin: 0; padding: 0; width: 200px; height: 800px;">
  This div is 200x800.
  <div style="border: 1px solid blue; margin: 10% 0 0 10%;">
    This div has top-margin of 10% and left-margin of 10% with respect to its parent.
  </div>
</div>

http://jsfiddle.net/8JDYD/


3
İlk düşüncem, margin: 25%gerçekte ne anlama geldiğine dair belirsizliğe neden olacağıydı . Kod öyle olduğunu öne sürse bile, bu eşit bir marj olmaz. Bunu destekleyecek kanıtım yok, ama mantıklı görünüyor.
Ryan Kinal

4
jsFiddle düşüncelerim . Yükseklik genişlikten çok daha değişkendir, bu nedenle içerik her değiştiğinde kenar boşluklarının tahmin edilmesi zor şekillerde kaymasına neden olur.
RichardTowers

1
@Ryan: Bu doğru, eşit bir marj olmazdı, ama yine de height: 10%; width: 10%kare bir öğe almayacağınızı söylerseniz .
mqp

4
Dev.w3.org/csswg/css3-box/#the-margin-properties'e göre, belirtiyor Note that in a horizontal flow, percentages on ‘margin-top’ and ‘margin-bottom’ are relative to the width of the containing block, not the height (and in vertical flow, ‘margin-left’ and ‘margin-right’ are relative to the height, not the width).Yani her iki yöne de gidiyor
Adam Sweeney

1
@Ryan Bence bir kazananımız var. Demo için buraya bakın - jsFiddle
RichardTowers

Yanıtlar:


60

Yorumumu bir cevaba aktarıyorum çünkü mantıklı geliyor. Ancak, lütfen bunun temelsiz bir varsayım olduğunu unutmayın. Spesifikasyonun neden bu şekilde yazıldığının gerçek nedeni teknik olarak hala bilinmemektedir.

Eleman yüksekliği, çocukların boyu ile tanımlanır. Bir öğenin üst dolgu malzemesi varsa:% 10 (üst öğenin yüksekliğine göre), bu, üst öğenin yüksekliğini etkiler. Çocuğun boyu ebeveynin boyuna bağlı olduğundan ve ebeveynin boyu çocuğun boyuna bağlı olduğundan, ya yanlış boyumuz olacak ya da sonsuz bir döngüye sahip olacağız. Elbette, bu yalnızca offset parent === parent olduğu durumu etkiler, ancak yine de. Çözmesi zor olan garip bir durum.

Güncelleme: Son birkaç cümle tamamen doğru olmayabilir. Yaprak öğesinin yüksekliği (çocuğu olmayan çocuk), üzerindeki tüm öğelerin yüksekliğini etkiler, bu nedenle bu birçok farklı durumu etkiler.


1
Bu kuralın istisnaları olduğuna dikkat edin - CSS2.1'in 10.6 bölümü, çeşitli kutu türleri için neredeyse tüm yükseklik hesaplama örneklerini kapsar. Ve aslında, ebeveyn ile çocuk arasında bir bağımlılık içeren durumlar, tanımlanmamış davranışlara yol açma eğilimindedir.
BoltClock

1
@sanjaypoyzer En basit durumda, tarayıcıların blok genişliklerini dışarıdan (kökten uçlara) hesapladığını ve daha sonra yüksekliklerini belirlemek için içeriği bu bloklara akıttığını tahmin ediyorum (köke ipuçları).
sam

9
W3C bunu neden sürekli yapıyor? Görünüşe göre W3C için 'anlamsal', mantıklı düşünemeyen insanlara hitap etmek zorunda olmakla eşdeğerdir, ki bu hiç mantıklı değil. Bu, dünyadaki insanların ne kadar kafa karıştırıcı ve aptal olduklarından şikayet etmek ve ardından daha fazla kafa karışıklığı ve aptallık yaymak gibidir. Sağladığınız mantık mantıklı değil: aynı argüman genişlikler için de geçerli, ancak bu gayet iyi çalışıyor. Gerekli olan tek şey, ebeveynin yüksekliği piksel olarak veya değişmez bir şey olarak ayarlanmadıkça, yüksekliklerin belirleneceği bir bağlam ve yön ayarlamaktır, o zaman çok fazla sorun olmaz.
u353

3
Bu bağımlılık bir çözümü vardır ve olacak bir cebirsel formül değil bu saygı duymayan bir şekilde bunu çözmek için tercih sürece sonsuz döngüye neden olur. Ebeveyn boyunun olduğunu söyle h_p. Üst% 10'luk bir dolgu üst kısmı, çocuğun boyunu h_c = h_ci + 0.1h_p, yani çocuğun h_ciiç boyunu ve ebeveyn boyuna bağlı olmadığını gösterir. Bir çocuk için ebeveyn yüksekliğini h_p = h_ci + 0.1h_p=> denkleminden bulmanız yeterlidir h_p = h_ci / 0.9. Farklı dolgu malzemeleri için bile, kaç çocuğunuz olursa olsun bunu her zaman yapabilirsiniz. Sadece bir bilinmeyen ( h_p) ve bir denklem.
jeteon

2
Sonsuz hesaplamanın sebebi olduğunu sanmıyorum. Bunun basit bir nedeni şudur: widthSonuçları aynı problemde yatay olarak kullanmak.
Joy

30

"N%" kenar (ve dolgu) olması için, aynı kenar üstü / kar sağ / kar-alt / kar sol için, dört aynı baza göre olması. Üst / alt, sol / sağ'dan farklı bir taban kullanıyorsa, "n%" kenar boşluğu (ve dolgu) dört kenarda da aynı anlama gelmez.

(Ayrıca, genişliğe göre üst / alt kenar boşluğuna sahip olmanın , kutu yeniden ölçeklendirilse bile, değişmeyen bir en boy oranına sahip bir kutu belirlemenize olanak tanıyan garip bir CSS hackine olanak tanıdığını unutmayın.)


... şaşırtıcı derecede basit bir cevap. Yukarıdaki tüm varsayımlar haklı olsa da, bu oldukça iyi bir noktadır. Muhtemelen birden fazla çözümün doğru olacağı bir durum gibi görünüyor, bu yüzden en olası olanı seçtiler .... belki?
dudewad

1
Söyleyebilmeniz için sözdiziminde fazladan bir öğenin olması güzel olurdu padding: n [type]. Böylece , geriye dönük uyumluluk için ikinci parametrenin varsayılan olarak "genişlik" olarak ayarlanması padding: 5% logicalyerine (OP'nin önerdiği) sahip olursunuz padding: 5% width.
jeteon

5
"n% marj (ve doldurma) dört tarafta da aynı anlama gelmez" - Ama bu neden bir sorun olur?
Herbertusz

4

Bununla oynadıktan sonra @ChuckKollars gelen cevap için ben oy JSFiddle (Krom 46.0.2490.86 üzerine) ve atıfta bu yazı (Çince yazılmış).


Sonsuz hesaplama varsayımına karşı önemli bir neden şudur: kullanmak widthaynı sonsuz hesaplama problemiyle karşı karşıyadır .

Bu JSFiddle'a bir bakın , parentekran, inline-blocküzerinde marj / padding tanımlamaya uygun. childKenar değerine sahiptir 20%. Sonsuz hesaplama varsayımını izlersek :

  1. Genişliği childşunlara bağlıdır:parent
  2. Genişliği parentşunlara bağlıdır:child

Ancak sonuç olarak, Chrome hesaplamayı bir yerde durdurur ve sonuçta:

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

JSFiddle üzerinde "sonuç" panelini yatay olarak genişletmeye çalışırsanız, genişliğinin değişmeyeceğini göreceksiniz. Lütfen içindeki içeriğin iki satırachild bölündüğünü unutmayın (tek satır değil), neden? Sanırım Chrome bir yere sabit kodluyor. Eğer düzenlerseniz daha (yapmak içeriği JSFiddle ), sürece fazladan bir boşluk yatay olarak orada olduğunu göreceksiniz, Chrome içerik iki satır tutar.child

Böylece şunu görebiliriz: sonsuz hesaplamayı engellemenin bir yolu var .


Şu varsayıma katılıyorum: Bu tasarım sadece aynı ölçüye dayalı dört kenar boşluğu / dolgu değerini korumak içindir.

Bu gönderi (Çince yazılmıştır) ayrıca başka bir neden önermektedir: okuma / dizginin yönünden kaynaklanmaktadır. Yukarıdan aşağıya, sabit genişlik ve sonsuz yükseklik (sanal olarak) ile okuyoruz.


Bunun nedeni, web sayfalarının genellikle sonsuz bir yönde dikey olarak kaydırılmasıdır; böylece genişlik tarayıcı penceresinin genişliğinden hesaplanabilir. Öğelerin ekrandan daha geniş olmasının tek yolu, genişliklerini daha büyük olarak belirlemenizdir. Tipik blok elemanlar% 100 genişliktedir ve otomatik olarak dikey yönde genişler (bilinmeyen). Bu yüzden genişlikte aynı sorun yok.
Lucent Fox

3

OP'nin neden üst / alt marj yüzdelerini genişliğin yüzdesi olarak tanımladığını (ve varsayılacağı gibi yükseklik değil) sorduğunu anlıyorum, ancak potansiyel bir çözüm yayınlamanın da yararlı olabileceğini düşündüm.

Çoğu modern tarayıcı artık vw ve vh'yi destekliyor ve bu da, görünüm alanı genişliğine ve görünüm alanı yüksekliğine göre kenar boşluğu sayıları belirlemenize izin veriyor.

Kaydırma çubuğu yoksa 100vw / 100vh% 100 genişlik /% 100 yüksekliğe (sırasıyla) eşittir; bir kaydırma çubuğu varsa, görüntü alanı numaraları bunu hesaba katmaz (% sayıları hesaba katarken). Neyse ki, neredeyse tüm tarayıcılar 17px kaydırma çubuğu boyutlarını kullanır ( buraya bakın ), bu nedenle bunu hesaba katmak için css calc işlevini kullanabilirsiniz. Bir kaydırma çubuğunun görünüp görünmeyeceğini bilmiyorsanız, bu çözüm işe yaramayacaktır.

Örneğin: Yatay kaydırma çubuğu olmadığı varsayıldığında, yüksekliğin% 50'si olan bir üst kenar boşluğu "margin-top: 50vh;" olarak tanımlanabilir. Yatay kaydırma çubuğu ile bu, "margin-top: calc (0.5 * (100vh - 17px));" olarak tanımlanabilir. (calc'deki eksi ve artı operatörlerinin her iki tarafta da boşluklar gerektirdiğini unutmayın!).


1
Bu, çoğu durumda yararlı bir çözümdür, ancak işe yaramadığı pek çok örnek vardır (örneğin, içeriği, kullanılabilir alanı doldurmak için büyüyen bir flexbox konteynerin boyutuna orantılı olarak sığdırmaya çalışıyorsanız, başka bir kutu varken değişken içerik).
Jules
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.