【问题标题】:Can you do this HTML layout without using tables?您可以在不使用表格的情况下进行这种 HTML 布局吗?
【发布时间】:2010-10-06 02:15:41
【问题描述】:

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

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

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

效果很好。

【问题讨论】:

  • 好吧,这是有道理的“我应该为 vim 使用什么颜色?”被赞成,我的特定 CSS 布局问题被反对。
  • 在任何情况下,您都可以在没有桌子的情况下为所欲为。还有,到底为什么@SamB 碰到了这个 2 岁的问题?卫生部+
  • @yes123:嗯,语法高亮是错误的……

标签: html css layout


【解决方案1】:

使用可用的工具快速正确地完成工作并没有错。

在这种情况下,一张桌子工作得很好。

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

我认为应该避免嵌套表,事情会变得一团糟。

【讨论】:

  • 除非您使用表格而不是表格数据进行演示布局,因为它一开始更容易苍白,在这种情况下,您将走上一条黑暗而危险的道路。
  • 甚至亚马逊在某些情况下也使用表格。 stackoverflow.com 也是如此。当它们实际上运行良好时,我完全支持 css 解决方案。
  • 亚马逊和现在的 stackoverflow 都不是网页设计的巅峰之作。
  • 他们可能不是,但他们正在为成千上万的用户提供服务。
  • 这个反桌子的表情包简直是老傻了。灵活的基于约束的布局的唯一二维布局管理器是表格;以及它是否只是一个复杂的(有无数的 col/rowspans),或者嵌套的没有什么区别。但事实和事实似乎并不总是足以对抗狂热的武器。
【解决方案2】:

只需左右浮动并设置为清除两者,就完成了。不需要表格。

编辑:我知道我为此得到了很多支持,我相信我是对的。但在某些情况下,您只需要有表。你可以尝试用 CSS 做所有事情,它可以在现代浏览器中工作,但如果你想支持旧的浏览器......不要重复我自己,这里是 related stack overflow threadrant on my blog

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

【讨论】:

  • 不处理垂直居中,所以-1。
  • 我遇到了类似的问题,左侧有徽标,右侧有一些文本菜单。菜单必须与徽标的基线对齐。对菜单使用 float:right 不起作用。它将它们发送到右上角,它们不再与徽标的基线垂直对齐。
  • 我认为你可以通过将 Title 的 line-height 设置为 Button 的高度来解决垂直居中问题。
  • @igors,+1,你是对的。请注意,这个问题来自 2009 年。;)
【解决方案3】:

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

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

【讨论】:

  • +1 哇,溢出隐藏是怎么回事?它的确有所作为。不知道为什么。
  • 说实话,我也不明白,在规范中也找不到任何提及。有人告诉我这是“正确”的方式,但在我回答了另一个问题后,建议他们使用清除的元素来做到这一点。对我来说似乎是个好主意。
  • 浮动元素仍然需要清除,以使它们后面的内容正常流动。溢出:隐藏;只处理容器的高度。
  • "overflow: hidden" 是一种实现高度“扩展”和清除的技巧。以下元素将清除该框(至少在正确实现该规范部分的浏览器中)。
  • -1 表示不处理垂直居中,但 +2 表示overflow:hidden
【解决方案4】:

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

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

我想郑重声明,是的,在 CSS 中垂直居中是很困难的。当人们发帖时,在 SO 上似乎没完没了,“你能在 CSS 中做 X”吗?答案几乎总是“是”,他们的抱怨似乎没有道理。在这种情况下,是的,那一件事很难。

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

【讨论】:

  • 这是我对“table haters”论点的一个问题:CSS 可以做所有表格可以做的事情……除了一些非常简单、常见和合理的情况(比如垂直居中)。 CSS 看起来就像一个选举承诺变质了。
  • 我的观点是,垂直居中是唯一真正困难的事情。
  • CSS 并不是要替换表格;它只是为了让您在没有表格的情况下解决大多数常见的布局问题。如果桌子能用,就用桌子,就像用钢笔而不是大锤画画一样。
【解决方案5】:

在纯 CSS 中,有朝一日可以使用"display:table-cell"。不幸的是,这不适用于当前的 A 级浏览器,因此,无论如何,如果您只想获得相同的结果,不妨使用表格。至少你会确信它在过去足够远。

老实说,如果更容易的话,就用一张桌子。不会疼的。

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

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

我认为这需要 XHTML 1.1 之外的特殊 DTD,这只会激起整个 text/htmlapplication/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 将块对齐到组头元素的文本基线。每个块的不同高度将保持垂直居中并推出其容器的高度。需要计算元素的宽度以适应宽度。在这里,它们是 400 和 100,减去它们的水平填充。

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

【讨论】:

  • 嗯显示:table-X标签似乎有使用表格进行布局的目的,只是不使用表格标签?
【解决方案6】:

我建议不要在这种情况下使用表格,因为那不是表格数据;将按钮放在最右边纯粹是为了展示。这就是我要复制您的表结构的方法(更改为不同的 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 将其撞到它们上方.

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

【讨论】:

  • 由于 :after 伪类,您的解决方案无法在 IE6 上运行。
  • 它确实在 IE 6 中工作,这要归功于 .group-header 中的 zoom: 1,它触发 hasLayout 并导致 IE 6 的行为与激活 :after 元素一样。
【解决方案7】:

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

【讨论】:

  • 我有一个垂直居中的要求(和一点额外的填充)。我想我在你发帖后澄清了这一点。
【解决方案8】:
<div class="group-header">
    <input type="button" name="Button" value="Button" style="float:right" />
    <span>Title</span>
</div>

【讨论】:

    【解决方案9】:

    我选择使用 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
    }
    

    See Demo

    【讨论】:

      【解决方案10】:

      我同意应该只将表格用于表格数据,原因很简单,表格在加载完成之前不会显示(无论速度有多快;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>
      

      按钮功能和任何额外的细节都可以通过这个基本形式来设计。为错误的标签道歉。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-05
        • 1970-01-01
        • 2022-11-14
        • 2013-11-14
        • 2012-03-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多