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

时间:2009-02-07 01:44:02

标签: html css layout

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

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

非常简单的东西。事情似乎已经在网络世界中占据了一席之地,当我问Why use definition lists (DL,DD,DT) tags for HTML forms instead of tables?时我被提醒了。现在已经讨论过表格与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>

感谢overflow: hidden部分的Ant P(但仍然不明白为什么)。这就是问题所在。说我希望标题和按钮垂直居中。这是有问题的,因为元素具有不同的高度。将其与:

进行比较
<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>

完美无缺。

10 个答案:

答案 0 :(得分:49)

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

在这种情况下,表格完美无缺。

我个人本来会用这个表。

我认为应该避免使用嵌套表,事情会变得混乱。

答案 1 :(得分:27)

只需向左和向右浮动并设置清除两者即可。不需要桌子。

编辑:我知道我得到了很多赞成票,我相信我是对的。但有些情况下你只需要有桌子。您可以尝试使用CSS完成所有操作,它可以在现代浏览器中使用,但如果您希望支持较旧的浏览器...不要重复自己,related stack overflow threadrant on my blog

Edit2:由于旧浏览器不再那么有趣,我正在使用Twitter引导程序来处理新项目。它适用于大多数布局需求,并使用CSS。

答案 2 :(得分:17)

这是一个棘手的问题:在你到达之前,它看起来非常简单

  

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

我想说明是的,CSS的垂直居中很困难。当人们发帖,并且在SO上似乎无穷无尽时,“你能用CSS做X”,答案几乎总是“是”,他们的唠叨似乎是不合理的。在这种情况下,是的,一件特别的事情很难。

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

答案 3 :(得分:16)

左边浮动标题,右边浮动按钮,(这是我最近才知道的部分) - 使它们的容器{overflow:hidden}

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

答案 4 :(得分:7)

在纯CSS中,有一天工作答案只能使用"display:table-cell"。不幸的是,这在当前的A级浏览器中不起作用,所以对于所有这些,如果您只是想要获得相同的结果,也可以使用表。至少你会确定它在过去的工作中已经足够了。

老实说,如果更容易,只需使用一张桌子。它不会受到伤害。

如果表元素的语义和可访问性对您来说真的很重要,那么有一个工作草案可以使您的表非语义化:

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

我认为这需要一个超越XHTML 1.1的特殊DTD,这只会激起整个text/html vs application/xml辩论,所以我们不要去那里。

那么,关于你未解决的CSS问题......

要在它们的中心垂直对齐两个元素:它可以用几种不同的方式完成,有一些钝的CSS hackery。

如果符合以下约束条件,则有一种相对简单的方法:

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

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

.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然后将其显示为内联,它的行为就像内联块一样。边距调整是在顶部修复1px间隙(尝试将背景颜色添加到.group-title中以查看)。

答案 5 :(得分: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>

如果你想在中间进行真正的垂直对齐(即,如果文本包裹按钮仍然是相对于两行文本的中间对齐),那么你需要做一个表或者用{{1和边距。您可以将position: absolute添加到下拉菜单(或者更可能是其父级),以便将其拉到与按钮相同的排序级别,允许您使用z-index将其添加到它们上方(如果有的话)那个。

请注意,div上不需要position: relative,因为它是一个块级元素,而width: 100%使得div的行为就像它在IE中有一个clearfix(其他浏览器选择实际的clearfix)。如果你的目标更具针对性,你也不需要所有那些无关的类,尽管你可能需要在按钮上使用包装div或span来使定位更容易。

答案 6 :(得分:2)

在div中执行双浮点并使用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>

答案 7 :(得分:2)

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

答案 8 :(得分: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>

按钮功能和任何额外的细节都可以从这个基本形式设置样式。 为坏标签道歉。

答案 9 :(得分:1)

我选择使用弹性盒子,因为它使事情变得如此简单 您基本上需要转到要对齐的子项的父项,并添加display:box(当然是前缀)。使他们坐在两侧使用justify-content。当你有需要与末尾对齐的元素时,间距是正确的,就像在这种情况下一样(见链接)...
然后是真正的对齐问题。因为我想要对齐一个弹性框的两个元素的父级,现在很容易使用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
    }

<强> See Demo