你能在不使用表格的情况下做这个 HTML 布局吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/522928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can you do this HTML layout without using tables?
提问by cletus
Ok, I had a simple layout problem a week or two ago. Namely sections of a page needed a header:
好的,一两周前我遇到了一个简单的布局问题。即页面的部分需要标题:
+---------------------------------------------------------+
| Title Button |
+---------------------------------------------------------+
Pretty simple stuff. Thing is table hatred seems to have taken over in the Web world, which I was reminded of when I asked Why use definition lists (DL,DD,DT) tags for HTML forms instead of tables?Now the general topic of tables vs divs/CSS has previously been discussed, for example:
很简单的东西。事情是表格仇恨似乎已经在 Web 世界中占据了上风,当我问为什么对 HTML 表单使用定义列表(DL、DD、DT)标签而不是表格时,我想起了这一点?现在之前已经讨论过表格 vs divs/CSS 的一般主题,例如:
So this isn't intended to be a general discussion about CSS vs tables for layout. This is simply the solution to one problem. I tried various solutions to the above using CSS including:
所以这不是关于布局的 CSS 与表格的一般性讨论。这只是一个问题的解决方案。我使用 CSS 尝试了各种解决方案,包括:
- Float right for the button or a div containing the button;
- Position relative for the button; and
- Position relative+absolute.
- 按钮或包含按钮的 div 向右浮动;
- 按钮的相对位置;和
- 位置相对+绝对。
None of these solutions were satisfactory for different reasons. For example the relative positioning resulted in a z-index issue where my dropdown menu appeared under the content.
由于不同的原因,这些解决方案都不能令人满意。例如,相对定位导致我的下拉菜单出现在内容下方的 z-index 问题。
So I ended up going back to:
所以我最终回到了:
<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>
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.
它完美地工作。它很简单,尽可能向后兼容(即使在 IE5 上也可能工作),而且它只是工作。没有搞乱定位或浮动。
So can anyone do the equivalent without tables?
那么任何人都可以在没有桌子的情况下做等效的事情吗?
The requirements are:
要求是:
- Backwards compatible:to FF2 and IE6;
- Reasonably consistent:across different browsers;
- Vertically centered:the button and title are of different heights; and
- Flexible:allow reasonably precise control over positioning (padding and/or margin) and styling.
- 向后兼容:到FF2和IE6;
- 合理一致:跨不同浏览器;
- 垂直居中:按钮和标题的高度不同;和
- 灵活:允许对定位(填充和/或边距)和样式进行合理精确的控制。
On a side note, I came across a couple of interesting articles today:
顺便说一句,我今天看到了几篇有趣的文章:
EDIT:Let me elaborate on the float issue. This sort of works:
编辑:让我详细说明浮动问题。这类作品:
<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>
Thanks to Ant Pfor the overflow: hidden
part (still don't get why though). Here's where the problem comes in. Say I want the title and button to be vertically centered. This is problematic because the elements are of different height. Compare this to:
感谢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>
which works perfectly.
这完美地工作。
采纳答案by Gregor Brandt
There is nothing wrong with using the tools that are available to you to do the job quickly and correctly.
使用您可以使用的工具快速正确地完成工作并没有错。
In this case a table worked perfectly.
在这种情况下,一张桌子工作得很好。
I personally would have used a table for this.
我个人会为此使用一张桌子。
I think nested tables should be avoided, things can get messy.
我认为应该避免嵌套表,事情会变得混乱。
回答by Milan Babu?kov
Just float left and right and set to clear both and you're done. No need for tables.
只需向左和向右浮动并设置为清除两者即可完成。不需要桌子。
Edit:I know that I got a lot of upvotes for this, and I believed I was right. But there are cases where you simply need to have tables. You can try doing everything with CSS and it will work in modern browsers, but if you wish to support older ones... Not to repeat myself, here the related stack overflow threadand rant on my blog.
编辑:我知道我为此获得了很多赞成票,我相信我是对的。但在某些情况下,您只需要拥有表格。你可以尝试用 CSS 做所有事情,它可以在现代浏览器中工作,但如果你希望支持旧浏览器......不要重复我自己,这里是我博客上相关的堆栈溢出线程和咆哮。
Edit2:Since older browsers are not that interesting anymore, I'm using Twitter bootstrap for new projects. It's great for most layout needs and does using CSS.
Edit2:由于旧的浏览器不再那么有趣,我将 Twitter 引导程序用于新项目。它非常适合大多数布局需求,并且确实使用 CSS。
回答by AmbroseChapel
This is kind of a trick question: it looks terribly simple until you get to
这是一个棘手的问题:它看起来非常简单,直到你知道
Say I want the title and button to be vertically centered.
假设我希望标题和按钮垂直居中。
I want to state for the record that yes, vertical centring is difficult in CSS. When people post, and it seems endless on SO, "can you do X in CSS" the answer is almost always "yes" and their whinging seems unjustified. In this case, yes, that one particular thing is hard.
我想声明一下,是的,在 CSS 中垂直居中是很困难的。当人们发帖时,“你能在 CSS 中做 X”吗?答案几乎总是“是”,他们的抱怨似乎没有道理。在这种情况下,是的,一件特别的事情很难。
Someone should just edit the entire question down to "is vertical centring problematic in CSS?".
有人应该将整个问题编辑为“CSS 中的垂直居中是否有问题?”。
回答by AmbroseChapel
Float title left, float button right, and (here's the part I never knew until recently) - make the container of them both {overflow:hidden}
.
向左浮动标题,向右浮动按钮,以及(这是我直到最近才知道的部分) - 将它们都放在容器中{overflow:hidden}
。
That should avoid the z-index problem, anyway. If it doesn't work, and you reallyneed the IE5 support, go ahead and use the table.
无论如何,这应该可以避免 z-index 问题。如果它不起作用,并且您确实需要 IE5 支持,请继续使用该表。
回答by Andrew Vit
In pure CSS, a working answer will one day be to just use "display:table-cell"
. Unfortunately that doesn't work across current A-grade browsers, so for all that you might as well use a table if you just want to achieve the same result anyway. At least you'll be sure it works far enough into the past.
在纯 CSS 中,有朝一日一个可行的答案是只使用"display:table-cell"
. 不幸的是,这不适用于当前的 A 级浏览器,因此对于所有这些,如果您只想获得相同的结果,则最好使用表格。至少你会确定它在过去足够远。
Honestly, just use a table if it's easier. It won't hurt.
老实说,如果更容易,就使用桌子。不会痛的。
If the semantics and accessibility of the table element really matter to you, there is a working draft for making your table non-semantic:
如果 table 元素的语义和可访问性对您来说真的很重要,那么有一个工作草案可以使您的 table 非语义:
http://www.w3.org/TR/wai-aria/#presentation
http://www.w3.org/TR/wai-aria/#presentation
I think this requires a special DTD beyond XHTML 1.1, which would just stir up the whole text/html
vs application/xml
debate, so let's not go there.
我认为这需要 XHTML 1.1 之外的特殊 DTD,这只会激起整个text/html
vsapplication/xml
争论,所以我们不要去那里。
So, on to your unresolved CSS problem...
所以,继续你未解决的 CSS 问题......
To vertically align two elements on their center: it can be done a few different ways, with some obtuse CSS hackery.
垂直对齐两个元素在它们的中心:它可以通过几种不同的方式完成,使用一些钝的 CSS 技巧。
If you can fit within the following constraints, then there is a relatively simple way:
如果你能满足以下约束,那么有一个相对简单的方法:
- The height of the two elements is fixed.
- The height of the container is fixed.
- The elements will be narrow enough not to overlap (or can be set to a fixed width).
- 两个元素的高度是固定的。
- 容器的高度是固定的。
- 元素将足够窄而不会重叠(或可以设置为固定宽度)。
Then you can use absolute positioning with negative margins:
然后你可以使用负边距的绝对定位:
.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; }
But this is pointless in most situations... If you already know the height of the elements, then you can just use floats and add enough margin to position them as needed.
但这在大多数情况下毫无意义......如果您已经知道元素的高度,那么您可以使用浮动并添加足够的边距来根据需要定位它们。
Here is another method which uses the text baseline to vertically align the two columns as inline blocks. The drawback here is that you need to set fixed widths for the columns to fill out the width from the left edge. Because we need to keep the elements locked to a text baseline, we can't just use float:right for the second column. (Instead, we have to make the first column wide enough to push it over.)
这是另一种方法,它使用文本基线将两列作为内联块垂直对齐。这里的缺点是您需要为列设置固定宽度以填充左边缘的宽度。因为我们需要将元素锁定在文本基线上,所以我们不能只对第二列使用 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>
The HTML:We add .valign wrappers around each column. (Give them a more "semantic" name if it makes you happier.) These need to be kept without whitespace in between or else text spaces will push them apart. (I know it sucks, but that's what you get for being "pure" with the markup and separating it from the presentation layer... Ha!)
HTML:我们在每列周围添加 .valign 包装器。(如果它能让你更快乐,给它们一个更“语义”的名字。)它们之间需要保持没有空格,否则文本空间会将它们分开。(我知道这很糟糕,但这就是使用标记“纯粹”并将其与表示层分离的结果......哈!)
The CSS:We use vertical-align:middle
to line up the blocks to the text baseline of the group-header element. The different heights of each block will stay vertically centered and push out the height of their container. The widths of the elements need to be calculated to fit the width. Here, they are 400 and 100, minus their horizontal padding.
CSS:我们用来vertical-align:middle
将块与 group-header 元素的文本基线对齐。每个块的不同高度将保持垂直居中并推出其容器的高度。需要计算元素的宽度以适应宽度。在这里,它们是 400 和 100,减去它们的水平填充。
The IE fixes:Internet Explorer only displays inline-block for natively-inline elements (e.g. span, not div). But, if we give the div hasLayout and then display it inline, it will behave just like inline-block. The margin adjustment is to fix a 1px gap at the top (try adding background colors to the .group-title to see).
IE 修复:Internet Explorer 仅显示本机内联元素的内联块(例如跨度,而不是 div)。但是,如果我们给 div hasLayout 然后将它内联显示,它的行为就像 inline-block。边距调整是修复顶部1px的间隙(尝试在.group-title中添加背景颜色以查看)。
回答by One Crayon
I would recommend not using a table in this instance, because that is not tabular data; it's purely presentational to have the button located at the far right. This is what I'd do to duplicate your table structure (change to a different H# to suit where you are in your site's hierarchy):
我建议不要在这种情况下使用表格,因为那不是表格数据;将按钮置于最右侧纯粹是为了展示。这就是我要复制您的表结构(更改为不同的 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>
If you want true vertical alignment in the middle (ie, if the text wraps the button is still middle-aligned with respect to both lines of text), then you either need to do a table or work something with position: absolute
and margins. You can add position: relative
to your drop-down menu (or more likely its parent) in order to pull it into the same ordering level as the buttons, allowing you to bump it above them with z-index, if it comes to that.
如果你想要在中间真正的垂直对齐(即,如果文本环绕按钮仍然相对于两行文本居中对齐),那么你要么需要做一个表格,要么使用position: absolute
边距做一些事情。您可以添加position: relative
到您的下拉菜单(或者更有可能是它的父级),以便将其拉入与按钮相同的排序级别,允许您使用 z-index 将其置于按钮上方,如果涉及到的话。
Note that you don't need width: 100%
on the div because it's a block-level element, and zoom: 1
makes the div behave like it has a clearfix in IE (other browsers pick up the actual clearfix). You also don't need all those extraneous classes if you're targeting things a bit more specifically, although you might need a wrapper div or span on the button to make positioning easier.
请注意,您不需要width: 100%
在 div 上,因为它是一个块级元素,zoom: 1
并使 div 的行为就像它在 IE 中具有 clearfix 一样(其他浏览器选择实际的 clearfix)。如果您更具体地定位事物,您也不需要所有这些无关的类,尽管您可能需要在按钮上使用包装器 div 或 span 以使定位更容易。
回答by bendewey
Do a double float in a div and use the clearfix. http://www.webtoolkit.info/css-clearfix.htmlDo you have any padding/margin restrictions?
在 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>
回答by Omer Bokhari
<div class="group-header">
<input type="button" name="Button" value="Button" style="float:right" />
<span>Title</span>
</div>
回答by Galen777
I agree that one should really only use tables for tabular data, for the simple reason that tables don't show until they're finished loading (no matter how fast that is; it's slower that the CSS method). I do, however, feel that this is the simplest and most elegant solution:
我同意人们真的应该只将表格用于表格数据,原因很简单,表格在加载完成之前不会显示(无论加载速度有多快;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>
The button function and any extra detail can be styled from this basic form. Apologies for the bad tags.
按钮功能和任何额外的细节都可以从这个基本形式来设计。为不好的标签道歉。
回答by user3522940
I've chose to use Flexbox, because it made things so much easier.
我选择使用 Flexbox,因为它让事情变得如此简单。
You basically need to go to the parent of the children you want to align and add display:box
(prefixed of course). To make them sit in the sides, use justify-content. Space between is the right thing when you have elements which need to be aligned to the end, like in this case (see link)...
您基本上需要转到要对齐和添加的子项的父项display:box
(当然是前缀)。要使它们坐在两侧,请使用justify-content。当您有元素需要对齐到末尾时,之间的空间是正确的,就像在这种情况下一样(见链接)...
Then the vertical align issue. Because I made the parent of the two elements, you want to align a Flexbox. It's easy now to use align-items: center
.
然后是垂直对齐问题。因为我创建了两个元素的父元素,所以你想要对齐一个 Flexbox。现在很容易使用align-items: center
。
Then I added the styles you wanted before, removed the float from the title and button in the header and added a padding:
然后我添加了你之前想要的样式,从标题中的标题和按钮中删除浮动并添加了一个填充:
.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
}