Bu HTML düzenini tablo kullanmadan yapabilir misiniz?


102

Tamam, bir veya iki hafta önce basit bir düzen problemim vardı. Yani bir sayfanın bölümleri bir başlığa ihtiyaç duyuyordu:

+---------------------------------------------------------+
| Title                                            Button |
+---------------------------------------------------------+

Oldukça basit şeyler. Web dünyasında tablo nefretinin hakim olduğu bir şey var, HTML formları için neden tablolar yerine tanım listeleri (DL, DD, DT) etiketleri kullanmalıyım? Şimdi tablolar ile divs / CSS arasındaki genel konu daha önce tartışılmıştı, örneğin:

Yani bu, CSS ile mizanpaj tabloları hakkında genel bir tartışma değildir. Bu basitçe tek bir sorunun çözümü. Aşağıdakileri içeren CSS kullanarak yukarıdakilere çeşitli çözümler denedim:

  • Düğme veya düğmeyi içeren bir div için sağa kayın;
  • Düğmeye göre konum; ve
  • Göreceli + mutlak konum.

Bu çözümlerin hiçbiri farklı nedenlerden dolayı tatmin edici değildi. Örneğin, göreli konumlandırma, açılır menümün içeriğin altında göründüğü bir z-endeksi sorunuyla sonuçlandı.

Böylece şuna geri döndüm:

<style type="text/css">
.group-header { background-color: yellow; width: 100%; }
.group-header td { padding: 8px; }
.group-title { text-align: left; font-weight: bold; }
.group-buttons { text-align: right; }
</style>
<table class="group-header">
<tr>
  <td class="group-title">Title</td>
  <td class="group-buttons"><input type="button" name="Button"></td>
</tr>
</table>

Ve mükemmel çalışıyor. Geriye dönük uyumluluğa sahip olabildiği kadar basit (muhtemelen IE5'te bile çalışacak) ve işe yarıyor. Konumlandırma veya şamandıralarla uğraşmak yok.

Öyleyse herhangi biri masasız eşdeğerini yapabilir mi?

Gereksinimler şunlardır:

  • Geriye doğru uyumlu: FF2 ve IE6'ya;
  • Makul ölçüde tutarlı: farklı tarayıcılarda;
  • Dikey olarak ortalanmış: düğme ve başlık farklı yüksekliktedir; ve
  • Esnek: konumlandırma (dolgu ve / veya kenar boşluğu) ve stil üzerinde makul ölçüde hassas kontrole izin verin.

Bir yan not olarak, bugün birkaç ilginç makaleye rastladım:

DÜZENLEME: Float konusunu detaylandırmama izin verin. Bu tür işler:

<html>
  <head>
    <title>Layout</title>
    <style type="text/css">
      .group-header, .group-content { width: 500px; margin: 0 auto; }
      .group-header { border: 1px solid red; background: yellow; overflow: hidden; }
      .group-content { border: 1px solid black; background: #DDD; }
      .group-title { float: left; padding: 8px; }
      .group-buttons { float: right; padding: 8px; }
    </style>
  </head>
  <body>
    <div class="group-header">
      <div class="group-title">This is my title</div>
      <div class="group-buttons"><input type="button" value="Collapse"></div>
    </div>
    <div class="group-content">
      <p>And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.</p>
      <p>So can anyone do the equivalent without tables that is backwards compatible to at least FF2 and IE6?</p>
      <p>On a side note, I came across a couple of interesting articles today:</p>
    </div>
  </body>
</html>

Sayesinde Ant P için overflow: hiddenparçanın (neden olsa hala alamadım). Sorun burada devreye girer. Başlığın ve düğmenin dikey olarak ortalanmasını istediğimi varsayalım. Bu sorunludur çünkü elemanlar farklı yüksekliktedir. Bunu şununla karşılaştırın:

<html>
  <head>
    <title>Layout</title>
    <style type="text/css">
      .group-header, .group-content { width: 500px; margin: 0 auto; }
      .group-header { border: 1px solid red; background: yellow; overflow: hidden; }
      .group-content { border: 1px solid black; background: #DDD; }
      .group-header td { vertical-align: middle; }
      .group-title { padding: 8px; }
      .group-buttons { text-align: right; }
    </style>
  </head>
  <body>
    <table class="group-header">
    <tr>
      <td class="group-title">This is my title</td>
      <td class="group-buttons"><input type="button" value="Collapse"></td>
    </tr>
    </table>
    <div class="group-content">
      <p>And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.</p>
      <p>So can anyone do the equivalent without tables that is backwards compatible to at least FF2 and IE6?</p>
      <p>On a side note, I came across a couple of interesting articles today:</p>
    </div>
  </body>
</html>

hangi mükemmel çalışıyor.


11
Tamam bu mantıklı "Vim için hangi rengi kullanmalıyım?" olumlu oy alırsa, benim özel CSS düzeni sorunum olumsuz oylanır.
cletus


her durumda masa olmadan istediğinizi yapabilirsiniz. Ayrıca neden @SamB bu 2 yıllık soruyu çarptı? DOH +
dinamik

3
@ yes123: pekala, sözdizimi vurgulama yanlıştı ...
SamB

Yanıtlar:


50

İşi hızlı ve doğru bir şekilde yapmak için size sunulan araçları kullanmakta yanlış bir şey yoktur.

Bu durumda bir masa mükemmel çalıştı.

Şahsen bunun için bir masa kullanırdım.

İç içe geçmiş tablolardan kaçınılması gerektiğini düşünüyorum, işler karışabilir.


21
Tablodaki veriler yerine sunum düzeni için bir tablo kullandığınız zamanlar hariç, çünkü başlangıçta daha kolay soluktur, bu durumda karanlık ve tehlikeli bir yola girersiniz.
One Crayon

9
Amazon bile belirli durumlarda tablolar kullanır. Stackoverflow.com da öyle. Gerçekten iyi çalıştıklarında css çözümlerinden yanayım.
Nosredna

11
Artık ne amazon, ne de stackoverflow web tasarımının zirveleri değil.
Bobby Jack

31
Olmayabilirler, ancak on binlerce kullanıcıya hizmet veren çalışan çözümler.
17 26

22
Bu anti-masa memesi tamamen eski bir aptal. Esnek kısıtlamalara dayalı laout için tek 2 boyutlu düzen yöneticisi tablodur; ve sadece karmaşık bir tane (sayısız sütun / satır aralığı ile) veya iç içe geçmiş olanlar çok az fark yaratır. Ancak gerçeklik ve gerçekler her zaman bağnazlığa karşı yeterince iyi değil gibi görünüyor.
StaxMan

28

Sadece sola ve sağa süzülün ve ikisini de temizlemeye ayarlayın ve bitirdiniz. Masaya gerek yok.

Düzenleme: Bunun için çok fazla olumlu oy aldığımı biliyorum ve haklı olduğuma inandım. Ancak, sadece tablolara sahip olmanız gereken durumlar vardır. Her şeyi CSS ile yapmayı deneyebilirsiniz ve modern tarayıcılarda çalışacaktır, ancak daha eski olanları desteklemek istiyorsanız ... Kendimi tekrarlamak istemiyorum, burada ilgili yığın taşması dizisi ve blogumda rant .

Düzenleme2: Eski tarayıcılar artık o kadar ilginç olmadığından, yeni projeler için Twitter önyükleme kullanıyorum. Çoğu düzen ihtiyacı için harika ve CSS kullanıyor.


2
Dikey merkezlemeyi işlemez, yani -1.
SamB

1
Solda bir logo ve sağda bazı metin menülerim olduğunda benzer bir sorunla karşılaştım. Menülerin logonun taban çizgisine hizalanması gerekiyordu. Float kullanma: menüler için doğru çalışmadı. Onları sağ üst köşeye gönderdi ve artık logonun taban çizgisine dikey olarak hizalanmadılar.
Jean-François Beauchamp

1
Dikey merkezlemeyi, Başlığın satır yüksekliğini Düğmenin yüksekliğiyle aynı olacak şekilde ayarlayarak çözebileceğinizi düşünüyorum.
igors

1
@igors, +1, haklısın. Bu sorunun 2009 yılına ait olduğunu unutmayın.;)
Milan Babuškov

17

Bu biraz hileli bir soru: Siz gelene kadar çok basit görünüyor

Başlığın ve düğmenin dikey olarak ortalanmasını istediğimi varsayalım.

Evet, CSS'de dikey merkezlemenin zor olduğunu belirtmek isterim. İnsanlar gönderi yayınladığında ve SO'da sonsuz göründüğünde, "CSS'de X yapabilir misin" cevabı neredeyse her zaman "evet" olur ve mızmızlanmaları haksız görünür. Bu durumda, evet, bu belirli bir şey zor.

Birisi tüm soruyu "CSS'de dikey merkezleme sorunlu mu?" Şeklinde düzenlemelidir.


11
"Masadan nefret edenler" argümanıyla ilgili sorunum bu: CSS tabloların yapabileceği her şeyi yapabilir ... oldukça basit, yaygın ve makul durumlar dışında (dikey merkezleme gibi). CSS, kötü giden bir seçim vaadi gibi görünüyor.
cletus

4
Demek istediğim, dikey merkezlemenin gerçekten zor olan TEK şey olduğuydu.
AmbroseChapel

3
CSS, tabloların yerini alma amacını taşımaz; sadece genel yerleşim problemlerinin çoğunu tablolar olmadan çözmenize izin vermek içindir. Bir masa çalışıyorsa, tıpkı bir balyoz yerine kalemle çizdiğiniz gibi bir masa kullanın.
Aaron Digulla

16

Float title left, float button right ve (yakın zamana kadar bilmediğim kısım budur) - ikisini de kapsayıcı yapın {overflow:hidden}.

Z-endeksi sorunundan kaçınılmalıdır. İşe yaramazsa ve gerçekten IE5 desteğine ihtiyacınız varsa , devam edin ve masayı kullanın.


+1 Whoa, gizli taşma ne durumda? Bir fark yaratır. Neden olduğuna dair hiçbir fikrim yok.
cletus

Dürüst olmak gerekirse, ben de anlamıyorum ve şartnamede ondan hiç bahsedemiyorum. Birisi bana bunun "doğru" yol olduğunu söyledi, başka bir soruyu cevaplamak için açık bir öğe kullandıklarını önerdikten sonra. Bana iyi bir fikir gibi görünüyor.

Yüzen öğelerin, onları izleyen içeriğin düzgün şekilde akması için yine de temizlenmesi gerekir. taşma: gizli; yalnızca kabın yüksekliğini ele alır.
Zack The Human

2
"overflow: hidden", HER İKİ yükseklik 'genişletme' ve temizlemeyi başarmak için bir hack'tir. Aşağıdaki öğeler bu kutuyu temizleyecektir (en azından spesifikasyonun bu bölümünü doğru şekilde uygulayan tarayıcılarda).
Bobby Jack

1
Dikey merkezleme için -1 değil, +2 için overflow:hidden.
SamB

7

Saf CSS'de, işe yarayan bir cevap bir gün sadece kullanmak olacaktır "display:table-cell". Maalesef bu, mevcut A sınıfı tarayıcılarda işe yaramıyor, bu nedenle yine de aynı sonucu elde etmek istiyorsanız, bir tablo kullanabilirsiniz. En azından geçmişte yeterince işe yaradığından emin olacaksınız.

Dürüst olmak gerekirse, daha kolaysa bir masa kullanın. Acıtmaz.

Tablo öğesinin anlamsallığı ve erişilebilirliği sizin için gerçekten önemliyse, tablonuzu anlamsal olmayan yapmak için bir çalışma taslağı vardır:

http://www.w3.org/TR/wai-aria/#presentation

Bütün bu sadece kışkırtmak olur XHTML 1.1 ötesinde özel bir DTD gerektirir düşünüyorum text/htmlvs application/xmlo yüzden oraya girmeyelim, tartışma.

Öyleyse, çözülmemiş CSS sorununuz üzerine ...

İki öğeyi merkezlerinde dikey olarak hizalamak için: Birkaç farklı yolla yapılabilir, bazı kapsamlı CSS korsanlığı.

Aşağıdaki kısıtlamalara uyabilirseniz, nispeten basit bir yol vardır:

  • İki elemanın yüksekliği sabittir.
  • Konteynerin yüksekliği sabittir.
  • Öğeler örtüşmeyecek kadar dar olacaktır (veya sabit bir genişliğe ayarlanabilir).

Ardından, negatif kenar boşluklarıyla mutlak konumlandırmayı kullanabilirsiniz:

.group-header { height: 50px; position: relative; }
.group-title, .group-buttons { position: absolute; top: 50%; }
# Assuming the height of .group-title is a known 34px
.group-title { left: 0; margin-top: -17px; }
# Assuming the height of .group-buttons is a known 38px
.group-buttons { right: 0; margin-top: -19px; }

Ancak bu çoğu durumda anlamsızdır ... Elemanların yüksekliğini zaten biliyorsanız, o zaman yüzerleri kullanabilir ve bunları gerektiği gibi konumlandırmak için yeterli marj ekleyebilirsiniz.

İşte iki sütunu satır içi bloklar olarak dikey olarak hizalamak için metin taban çizgisini kullanan başka bir yöntem. Buradaki dezavantaj, sütunların genişliği sol kenardan doldurması için sabit genişlikler ayarlamanız gerekmesidir. Öğeleri bir metin taban çizgisine kilitlememiz gerektiğinden, ikinci sütun için sadece float: sağ kullanamayız. (Bunun yerine, ilk sütunu onu itecek kadar geniş yapmalıyız.)

<html>
  <head>
    <title>Layout</title>
    <style type="text/css">
      .group-header, .group-content { width: 500px; margin: 0 auto; }
      .group-header { border: 1px solid red; background: yellow; }
      .valign { display: inline-block; vertical-align: middle; }
      .group-content { border: 1px solid black; background: #DDD; }
      .group-title { padding: 8px; width: 384px; }
      .group-buttons { padding: 8px; width: 84px; text-align: right; }
    </style>
    <!--[if lt IE 8]>
    <style type="text/css">
      .valign { display: inline; margin-top: -2px; padding-top: 1px; }
    </style>
    <![endif]-->
  </head>
  <body>
    <div class="group-header">
      <div class="valign">
        <div class="group-title">This is my title.</div>
      </div><!-- avoid whitespace between these! --><div class="valign">
        <div class="group-buttons"><input type="button" value="Collapse"></div>
      </div>
    </div>
    <div class="group-content">
      <p>And it works perfectly, but mind the hacks.</p>
    </div>
  </body>
</html>

HTML: Her sütunun etrafına .valign sarmalayıcılar ekleriz. (Sizi daha mutlu edecekse onlara daha "anlamsal" bir ad verin.) Bunların arasında boşluk bırakmadan tutulması gerekir, aksi takdirde metin boşlukları onları ayırır. (Bunun berbat olduğunu biliyorum, ancak işaretlemeyle "saf" olduğunuz ve onu sunum katmanından ayırdığınız için elde ettiğiniz şey budur ... Ha!)

CSS: Biz kullanmak vertical-align:middlegrup başlık öğesinin metni başlangıca blokları sıraya. Her bloğun farklı yükseklikleri dikey olarak ortalanmış olarak kalacak ve konteynerlerinin yüksekliğini dışarı çıkaracaktır. Elemanların genişlikleri, genişliğe uyacak şekilde hesaplanmalıdır. Burada, yatay dolguları hariç 400 ve 100'dürler.

IE düzeltmeleri: Internet Explorer yalnızca yerel olarak satır içi öğeler için satır içi bloğu görüntüler (örneğin, div değil, span). Ancak div hasLayout'u verirsek ve sonra onu satır içi olarak görüntülersek, aynı satır içi blok gibi davranacaktır. Kenar boşluğu ayarı, üstte 1 piksellik bir boşluğu düzeltmektir (görmek için .group-başlığına arka plan renkleri eklemeyi deneyin).


1
Hmm ekran: table-X etiketlerinin amacı tabloları kullanarak, yalnızca tablo etiketleri kullanmadan mizanpaj yapmak gibi görünüyor?
Danubian Sailor

3

Bu örnekte tablo kullanmamanızı tavsiye ederim, çünkü bu tablo verileri değildir; en sağda bulunan düğmenin olması tamamen sunum amaçlıdır. Tablo yapınızı çoğaltmak için bunu yapacağım (sitenizin hiyerarşisinde bulunduğunuz yere uyması için farklı bir H # ile değiştirin):

<style>
  .group-header { background: yellow; zoom: 1; padding: 8px; }
  .group-header:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
  /* set width appropriately to allow room for button */
  .group-header h3 { float: left; width: 300px; }
  /* set line-height or margins to align with h3 baseline or middle */
  .group-header input { float: right; }
</style>

<div class="group-header">
  <h3>This is my title</h3>
  <input type="button" value="Collapse"/>
</div>

Ortada gerçek dikey hizalama istiyorsanız (yani, metin düğmeyi kaydırıyorsa, her iki metin satırına göre hala ortada hizalıysa), o zaman ya bir tablo yapmanız ya da position: absolutekenar boşlukları ile bir şeyler çalışmanız gerekir . Ekleyebilirsinposition: relative o noktaya gelirse, Z-endeksine sahip üstlerindeki bunu çarpmak için izin düğmeleri ile aynı sipariş seviyesine çekmek için sırayla açılır menüden (veya daha büyük olasılıkla kendi üst) için.

Div'e ihtiyacınız olmadığına width: 100%dikkat edin, çünkü bu blok düzeyinde bir öğe ve zoom: 1div'in IE'de bir açık düzeltme varmış gibi davranmasına neden olur (diğer tarayıcılar gerçek temizliği alır). Ayrıca, bir şeyleri biraz daha spesifik olarak hedefliyorsanız, tüm bu yabancı sınıflara ihtiyacınız yoktur, ancak konumlandırmayı kolaylaştırmak için düğmede bir sarmalayıcı div veya span'a ihtiyacınız olabilir.


Çözümünüz IE6'da çalışmıyor çünkü: after sözde sınıf.
Sebastian Hoitz

1
IE 6'da, hasLayout'u tetikleyen ve IE 6'nın: after öğesi etkinmiş gibi davranmasına neden olan zoom: 1in sayesinde çalışır .group-header.
One Crayon

2

Bir div içinde double float yapın ve clearfix'i kullanın. http://www.webtoolkit.info/css-clearfix.html Herhangi bir dolgu / kenar boşluğu kısıtlamanız var mı?

<div class="clearfix">
   <div style="float:left">Title</div>
   <input type="button" value="Button" style="float:right" />
</div>

Dikey bir merkezleme ihtiyacım var (ve biraz fazladan dolgu). Sanırım bunu siz yayınladıktan sonra açıklığa kavuşturdum.
cletus

2
<div class="group-header">
    <input type="button" name="Button" value="Button" style="float:right" />
    <span>Title</span>
</div>

1

Flexbox'ı kullanmayı seçtim çünkü işleri çok daha kolay hale getirdi.

Temel olarak hizalamak ve eklemek istediğiniz çocukların ebeveynine gitmeniz gerekir display:box(elbette önekli). Onları yanlara oturtmak için, içeriği kullan . Bu durumda olduğu gibi, sonuna hizalanması gereken öğeleriniz olduğunda, aradaki boşluk doğru şeydir (bağlantıya bakın) ...

Sonra dikey hizalama sorunu. İki elemanın üstünü yaptığım için, bir Flexbox'ı hizalamak istiyorsunuz. Şimdi kullanmak çok kolayalign-items: center .

Sonra daha önce istediğiniz stilleri ekledim, başlıktaki kayan noktayı ve başlıktaki düğmeyi kaldırdım ve bir dolgu ekledim:

.group-header, .group-content {
    width: 500px;
    margin: 0 auto;
}
.group-header{
    border: 1px solid red;
    background: yellow;
    overflow: hidden;
    display: -webkit-box;
    display: -moz-box;
    display: box;
    display: -webkit-flex;
    display: -moz-flex;
    display: -ms-flexbox;
    display: flex;
    -webkit-justify-content: space-between;
    -moz-justify-content: space-between;
    -ms-justify-content: space-between;
    -o-justify-content: space-between;
    justify-content: space-between;
    webkit-align-items: center;
    -moz-align-items: center;
    -ms-align-items: center;
    -o-align-items: center;
    align-items: center;
    padding: 8px 0;
}
.group-content{
    border: 1px solid black;
    background: #DDD;
}
.group-title {
    padding-left: 8px;
}
.group-buttons {
    padding-right: 8px
}

Demoyu Gör


1

Tabloların yüklenmesi bitene kadar gösterilmemesi gibi basit bir nedenden dolayı (bu ne kadar hızlı olursa olsun; CSS yönteminden daha yavaştır) gerçekten yalnızca tablo verileri için tabloların kullanılması gerektiğini kabul ediyorum. Bununla birlikte, bunun en basit ve en zarif çözüm olduğunu düşünüyorum:

<html>
    <head>
        <title>stack header</title>
        <style type="text/css">
            #stackheader {
                background-color: #666;
                color: #FFF;
                width: 410px;
                height: 50px;
            }
            #title {
                color: #FFF;
                float: left;
                padding: 15px 0 0 15px;
            }
            #button {
                color: #FFF;
                float: right;
                padding: 15px 15px 0 0;
            }
        </style>
    </head>

    <body>
        <div id="stackheader">
        <div id="title">Title</div>
        <div id="button">Button</div>
        </div>
    </body>
</html>

Düğme işlevi ve herhangi bir ekstra ayrıntı bu temel formdan şekillendirilebilir. Kötü etiketler için özür dilerim.

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.