您可以在不使用表格的情况下进行HTML布局吗?


102

好的,我在一两个星期前遇到了一个简单的布局问题。即页面的各个部分需要一个标题:

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

很简单的东西。在网络世界中,表仇恨似乎已经接管了一切,当我问为什么对HTML表单而不是表使用定义列表(DL,DD,DT)标签时,让我想起了这一点 现在,前面已经讨论了表vs divs / CSS的一般主题,例如:

因此,这并不是要对CSS与布局表进行一般性讨论。这只是解决一个问题的方法。我使用CSS尝试了上述各种解决方案,包括:

  • 向右浮动按钮或包含按钮的div;
  • 按钮的相对位置;和
  • 相对位置+绝对位置。

这些解决方案均因不同原因而不能令人满意。例如,相对位置导致z-index问题,其中我的下拉菜单出现在内容下方。

所以我最后回到了:

<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>

而且效果很好。这很简单,因为它具有向后兼容性(即使在IE5上也可以使用),并且可以正常工作。不要乱搞定位或浮动。

那么,没有表的人可以做到这一点吗?

要求是:

  • 向后兼容:到FF2和IE6;
  • 合理一致:跨不同的浏览器;
  • 垂直居中:按钮和标题的高度不同;和
  • 灵活:可以对定位(填充和/或边距)和样式进行合理精确的控制。

附带说明一下,今天我碰到了几篇有趣的文章:

编辑:让我详细说明浮动问题。这类作品:

<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>

多亏了Ant P的帮助overflow: hidden(尽管还是不明白为什么)。这就是问题所在。例如,我希望标题和按钮垂直居中。这是有问题的,因为元件具有不同的高度。比较一下:

<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>

完美地运作。


11
好的,“我应该为Vim使用哪种颜色?” 被投票,我特定的CSS布局问题被投票。
cletus


在任何情况下,您都可以在没有表格的情况下做任何您想做的事情。同样为什么在地狱中@SamB碰到了这个2岁的问题呢?DOH +
动态的

3
@ yes123:好吧,语法高亮显示是错误的……
SamB 2011年

Answers:


50

使用可用的工具快速正确地完成工作没有任何问题。

在这种情况下,一张桌子工作完美。

我个人会为此使用一张桌子。

我认为应避免使用嵌套表,否则可能会造成混乱。


21
除了将表格用于表述性布局而不是表格数据时,只是因为一开始就比较容易,否则这种情况将使您走上一条黑暗而危险的道路。
一支蜡笔

9
甚至Amazon在某些情况下也会使用表。而且stackoverflow.com也这样做。当它们确实运行良好时,我全力支持CSS解决方案。
Nosredna

11
亚马逊和现在的stackoverflow都不是Web设计的顶峰。
鲍比·杰克

31
它们可能不是,但是它们正在为数以万计的用户提供服务的解决方案。

22
这种反餐桌的模因简直是愚蠢的。table是用于基于约束的灵活布局的唯一二维布局管理器;不管是一个复杂的(无数的col / rowspans)还是嵌套的,都没什么区别。但是,现实和事实似乎并不总是足够好的抵抗狂热的武器。
StaxMan,2009年

28

只需向左和向右浮动,然后设置为同时清除,就可以完成。不需要桌子。

编辑:我知道我对此有很多支持,我相信我是对的。但是在某些情况下,您只需要拥有表即可。您可以尝试使用CSS进行所有操作,并且它可以在现代浏览器中运行,但是如果您希望支持较旧的浏览器...不再赘述,这里是我博客上相关堆栈溢出线程rant

Edit2:由于旧的浏览器不再那么有趣了,因此我将Twitter引导程序用于新项目。它非常适合大多数布局需求,并且确实使用CSS。


2
不处理垂直居中,因此为-1。
SamB

1
我有一个类似的问题,左边有徽标,右边有一些文本菜单。菜单必须与徽标的基线对齐。对菜单使用float:right无效。它将它们发送到右上角,并且它们不再与徽标的基线垂直对齐。
让·弗朗索瓦·比彻姆

1
我认为您可以通过将Title的行高设置为Button的高度来解决垂直居中的问题。
igors 2013年

1
@ igors,+ 1,您是对的。请注意,这个问题来自2009年。;)
米兰·巴布斯科夫(MilanBabuškov

17

这是一个技巧问题:看起来非常简单,直到您了解

假设我希望标题和按钮垂直居中。

我想记录一下,是的,在CSS中垂直居中很难。当人们发表文章时,SO似乎无穷无尽,“你能在CSS中做X吗?”答案几乎总是“是”,他们的抱怨似乎是没有道理的。在这种情况下,是的,一件事情很难。

有人应该将整个问题编辑为“ CSS的垂直居中是否有问题?”。


11
“ table haters”参数是我的问题:CSS可以完成表可以做的所有事情……除了一些非常简单,常见和合理的情况(例如垂直居中)。CSS看起来像选举承诺变糟了。
cletus

4
我的观点是,垂直居中仅是真正困难的事情。
AmbroseChapel,2009年

3
CSS并不是要替换表。这只是为了让您无需使用表即可解决大多数常见的布局问题。如果可以使用桌子,请使用桌子,就像用钢笔代替大锤一样画。
亚伦·迪古拉

16

向左浮动标题,向右浮动按钮,以及(这是我直到最近才知道的部分)-分别将它们都作为容器{overflow:hidden}

无论如何,那应该避免z-index问题。如果它不起作用,并且您确实需要IE5支持,请继续使用该表。


+1哇,隐藏的溢出是什么?它的确有所作为。不知道为什么。
cletus

老实说,我也没有得到它,并且在规范中找不到任何提及。有人告诉我,这是“正确”的方式,在我回答了另一个问题,暗示他们使用清除的元素来做到这一点之后。对我来说似乎是个好主意。

仍需要清除浮动元素,以便其后的内容正确流动。溢出:隐藏 仅说明容器的高度。
Zack The Human

2
“溢出:隐藏”是实现高度“扩展”和清除的一种手段。以下元素将清除该框(至少在正确实现规范那部分的浏览器中)。
鲍比·杰克2009年

1
-1表示不处理垂直居中,而+2表示overflow:hidden
SamB 2011年

7

在纯CSS中,有一天将是一个有效的答案"display:table-cell"。不幸的是,这不适用于当前的A级浏览器,因此,如果您只想获得相同的结果,那么最好还是使用表。至少您可以确定它在过去已经足够有效了。

老实说,只要使用表格即可。不会疼的

如果table元素的语义和可访问性对您而言确实很重要,那么有一个工作表可以使您的表变为非语义:

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

我认为这需要XHTML 1.1以外的特殊DTD,这只会激起整个text/htmlvs的application/xml争论,所以让我们不要去那里。

因此,关于您未解决的CSS问题...

要使两个元素在它们的中心垂直对齐:可以用几种不同的方法来完成,同时要使用一些钝的CSS骇客工具。

如果您可以满足以下约束,那么有一种相对简单的方法:

  • 这两个元素的高度是固定的。
  • 容器的高度是固定的。
  • 元素将足够窄而不会重叠(或可以设置为固定宽度)。

然后,您可以使用带有负边距的绝对定位:

.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; }

但这在大多数情况下是没有意义的...如果您已经知道元素的高度,则可以使用浮点数并添加足够的边距以根据需要定位它们。

这是另一种使用文本基线将两列作为内联块垂直对齐的方法。此处的缺点是您需要为列设置固定宽度以从左侧边缘填充宽度。因为我们需要将元素锁定在文本基线上,所以我们不能仅在第二列中使用float:right。(相反,我们必须使第一列足够宽以将其推入。)

<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:我们在每列周围添加.valign包装器。(给它们一个更“语义”的名称,如果它使您更快乐。)这些名称必须保持中间没有空格,否则文本空间会将它们分开。(我知道它很烂,但这就是您将标记“纯净”并将其与表示层分离的结果……哈!)

CSS:我们用于vertical-align:middle将块排列到group-header元素的文本基线。每个块的不同高度将保持垂直居中并推出其容器的高度。需要计算元素的宽度以适合宽度。在这里,它们是400和100,减去其水平填充。

IE修复: Internet Explorer仅显示本机内联元素的内联块(例如,span,而不是div)。但是,如果我们给div hasLayout然后内联显示,它的行为就像inline-block一样。边距调整是为了在顶部固定一个1px的间隙(请尝试向.group-title添加背景色以进行查看)。


1
嗯,显示:table-X标记似乎旨在使用表格进行布局,而仅不使用表格标记?
Danubian Sailor 2013年

3

我建议在这种情况下不要使用表,因为那不是表格数据。将按钮放在最右边纯粹是演示性的。这就是我要复制您的表结构的方法(更改为其他H#以适合您在网站层次结构中的位置):

<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>

如果要在中间进行真正的垂直对齐(即,如果文本自动换行,则按钮仍相对于两行文本都在中间对齐),则您需要制作表格或使用position: absolute和边距进行处理。您可以添加position: relative到下拉菜单(或更可能是其父菜单)中,以将其拉入与按钮相同的排序级别,并允许您使用z-index将其突出到按钮上方。

请注意,您不需要width: 100%div,因为它是一个块级元素,并且zoom: 1使div的行为就像它在IE中具有clearfix(其他浏览器会选择实际的clearfix)一样。如果您要更具体地定位目标,那么您也不需要所有这些无关的类,尽管您可能需要在按钮上使用包装div或span来简化定位。


由于:after伪类,您的解决方案在IE6上不起作用。
塞巴斯蒂安·霍伊茨

1
由于zoom: 1in .group-header,它确实可以在IE 6中工作,这会触发hasLayout并使IE 6的行为与激活:after元素相同。
一支蜡笔

2

在div中使用double浮动,然后使用clearfix。http://www.webtoolkit.info/css-clearfix.html 您是否有填充/边距限制?

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

我有一个垂直居中的要求(和一些额外的填充)。我想我澄清了,不过在您发布之后。
cletus


1

我选择使用Flexbox,因为它使事情变得如此简单。

基本上,您需要转到要对齐并添加的孩子的父母display:box(当然是前缀)。为了使它们坐在侧面,请使用justify-content。当您的元素需要与末端对齐时,正确的选择是正确的,例如在这种情况下(请参阅链接)...

然后是垂直对齐问题。因为我是这两个元素的父对象,所以您想对齐一个Flexbox。现在很容易使用align-items: center

然后,我添加了您之前想要的样式,从标题中的标题和按钮中删除了浮动元素,并添加了填充:

.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
}

观看演示


1

我同意,实际上应该只将表格用于表格数据,原因很简单,即表格要在完成加载后才显示(无论速度有多快; CSS方法的速度都较慢)。但是,我确实认为这是最简单,最优雅的解决方案:

<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>

可以从此基本表单设置按钮功能和任何其他详细信息的样式。不好的标签表示歉意。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.