从IE8开始,IE浏览器支持很多的CSS display属性值,包括与表格相关的CSS属性值:display:table和display:table-row和display:table-cell,它也是最后一款支持这些属性值的主流浏览器。它标志着复杂CSS布局技术的结束,同时也给了HTML表格布局致命一击。最终,使用CSS布局来制作出类似于table布局的网格将会变得十分迅速和简单。
网页元素应用上那些与表格相关的display属性值后,能够模仿出与表格相同的特性。我将会在该文中给大家演示这种方法给CSS布局带来的巨大影响。
使用CSS表格
CSS表格能够解决所有那些我们在使用绝对定位和浮动定位进行多列布局时所遇到的问题。例如,CSS display:table;
的CSS声明能够让一个HTML元素和它的子节点像table元素一样。使用基于表格的CSS布局,使我们能够轻松定义一个单元格的边界、背景等样式,而不会产生因为使用了table那样的制表标签所导致的语义化问题。
来看个例子:
<div id="wrapper"> <div id="header"></div> <div id="main"> <div id="cell-1"> 单元格1... </div> <div id="cell-2"> 单元格2... </div> <div id="cell-3"> 单元格3... </div> </div> </div>
#main{ display:table; border-collapse:collapse; } #cell-1{ display:table-cell; width:180px; background-color:#e7dbcd; } #cell-2{ display:table-cell; width:180px; padding-left:10px; border-right:1px dotted #d7ad7b; background-color:#fde3a7; } #cell-3{ display:table-cell; width:380px; padding-left:10px; background-color:#90c695; }
上面的代码得到的结果如下:
CSS display:table属性
table
:使该元素按table样式渲染 。table-row
:使该元素按tr样式渲染。table-cell
:使该元素按td样式渲染 。table-row-group
:使该元素按tbody样式渲染。table-header-group
:使该元素按thead样式渲染。table-footer-group
:使该元素按tfoot样式渲染。table-caption
:使该元素按caption样式渲染。table-column
:使该元素按col样式渲染。table-column-group
:使该元素按colgroup样式渲染。
匿名表格元素
CSS表格除了包含table布局的普通规则之外,同时还有着CSS table布局的超强特性:缺少的表格元素会被浏览器以匿名方式创建。
CSS2.1表格模型中的元素,可能不会全部包含在除HTML之外的文档语言中。这时,那些“丢失”的元素会被模拟出来,从而使得表格模型能够正常工作。所有的表格元素将会自动在自身周围生成所需的匿名table对象,使其符合table/inline-table、table-row、table-cell的三层嵌套关系。
上面这段话的意思是,如果我们为元素使用display:table-cell;
属性,而不将其父容器设置为display:table-row;
属性,浏览器会默认创建出一个表格行,就好像文档中真的存在一个被声明的表格行一样。让我们用个简单的例子来研究下它的这一特性:以下是三栏网格布局。我们将会用三个不同的HTML例子,而它们将表现出相同的视觉效果。
来看个例子,首先,以下是能够生成三列布局样例的其中一份:
<div class="container"> <div class="row"> <div class="cell">单元格 A</div> <div class="cell">单元格 B</div> <div class="cell">单元格 C</div> </div> </div>
为上面的HTML代码添加下面的CSS样式:
.container { display: table; } .row { display: table-row; } .cell { display: table-cell; width: 100px; height: 100px; border: 2px solid #446cb3; padding: 1em; }
以上CSS给类名为container
的元素定义了display:table;
属性,类名为row的元素定义了display:table-row;
,类名为cell的元素定义了display:table-cell;
,同样还给它定义了边框、高度和宽度值。 以上HTML文档明确地为三个单元格定义了包含它的表格和表格行,使用到了所有我们创建的CSS类名。然而,我们可以减少这些标签,移除最外层的包裹容器div.container
元素试试:
<div class="row"> <div class="cell">单元格 A</div> <div class="cell">单元格 B</div> <div class="cell">单元格 C</div> </div>
得到的结果如下:
即使上面的代码遗漏了声明表格的那一行,浏览器仍将创建一个匿名的表格行。我们还可以移除更多的代码:
<div class="cell">单元格 A</div> <div class="cell">单元格 B</div> <div class="cell">单元格 C</div>
以上代码遗漏了声明表格和表格行的代码,浏览器同样会创建出这些匿名的盒对象。即使缺少这些标签元素,最终的效果仍然是一样的。
创建匿名表格元素的规则
这些匿名的盒对象不是用魔术变出来的,它们也不会自动往你的HTML源码中添加新的标签。为了完全发挥出匿名表格元素的优势,你最好能够对创建它们的规则有所了解。
如果布局中调用了匿名元素,浏览器将会根据需要创建一个匿名的盒对象并将它的CSS display
属性设置为table
、table-row
或table-cell
中的一个。
如果某个元素已经被设置为display:table-cell;
,而它的父节点(包含它的容器)没有被设置为display:table-row;
属性,那么浏览器将会创建一个被设置为display:table-row;
的匿名盒对象来嵌套它。并且与之相邻的属性为display: table-cell;
的兄弟节点也都会被这个匿名盒对象所包含,直到碰到一个没有被设置为display: table-cell;
的元素而结束这一行。
以下是相关的代码样例:
<div class="cell">单元格 A</div> <div class="cell">单元格 B</div> <div class="cell">单元格 C</div> <div>这不是一个单元格</div>
上面的三个类名为cell
的div元素均被设置为display:table-cell;
,它们将会像一个单行表格的三个单元格一样并列排布。最后一个div元素则不会被包含在这一表格行当中,因为它没有被设置成display:table-cell;
。
如果某个元素被设置为display:table-row;
,而它的父节点没有被设置为display:table;
(或者display:table-row-group;
),浏览器将会创建一个被设置为display:table;
的匿名盒对象来嵌套它,与之相邻的属性为display: table-row;
的兄弟节点也都会被包含其中。
同样,如果某个元素被设置为display:table-row;
,但它的内部却缺少display:table-cell;
的元素,那么一个匿名的table-cell
将会被创建,用来包含该table-row
中的所有元素。
请看以下代码:
<div class="row">单元行 A</div> <div class="row">单元行 B</div> <div>这不是一个单元行</div>
上面两排类名为row
的div元素被设置了display:table-row;
属性,它们将会像单列表格中的两行一样依次排列。最后一个div元素则不会包含在这个匿名的table中。
以此类推,如果某个元素的display
属性值被设置为与表格相关的值,如table-row-group
、table-header-group
、 table-footer-group
、table-column
、table-column-group
以及table-caption
,但同时又没有一个被设置为display:table;
的父元素,那么一个匿名的盒对象将会被创建用来包含该元素和它的某些兄弟节点。
其他有用的表格属性
当使用CSS表格时,因为这些元素遵从table布局的普通规则,所以你还可以给它们应用其它表格相关的CSS属性。下面是一些派得上用场的属性:
table-layout
:将table-layout
属性设置为fixed
可以让浏览器按照固定算法来渲染单元格的宽度。这在固定宽度布局中非常有用,例如我们最上面的那段布局代码。Border-collapse
:和普通的HTML表格一样,你可以使用border-collapse
属性来定义你的table布局元素之间使用何种形式的边框,是共用边框(赋值为collapse
)还是使用各自独立的边框(赋值为separate
)。Border-spacing
:如果你声明了border-collapse:separate;
,那么你就可以使用border-spacing
属性来定义相邻两个单元格边框间的距离。
制作完美的网格
制作等高网格对于传统CSS布局技术来说已经成为一个难题,然而使用合适的CSS表格则很容易实现。例如,如果我们想制作一个包含图片和标题的网格布局,使用CSS表格很快就能搞定。看个例子:
惬意的喝一杯咖啡。
今天的头条是什么呢?
今天是个重要的日子。
好久没有化妆了,画个眉毛先。
天气真好,开车去兜风!
换个造型!
<div class="grid"> <div class="row-1"> <div class="image"><img src="1.jpg" alt="" /> <p>惬意的喝一杯咖啡。</p></div> <div class="image"><img src="2.jpg" alt="" /> <p>今天的头条是什么呢?</p></div> <div class="image"><img src="5.jpg" alt="" /> <p>今天是个重要的日子。</p></div> </div> <div class="row-1"> <div class="image"><img src="3.jpg" alt="" /> <p>好久没有化妆了,画个眉毛先。</p></div> <div class="image"><img src="4.jpg" alt="" /> <p>天气真好,开车去兜风!</p></div> <div class="image"><img src="6.jpg" alt="" /> <p>换个造型!</p></div> </div> </div>
每张图片被一个img标签引用,它的标题包含在P元素中,它们均被包含在一个类名为image
的div元素中。同一行的div被一个类名为row
的div元素包含,整个影像图库被一个类名为grid
的div元素包含。 实现这个布局的CSS代码十分简单:
.grid { display: table; border-spacing: 4px; } .row { display: table-row; } .image { display: table-cell; width: 240px; background-color: #000; border: 8px solid #000; vertical-align: top; text-align: center; } .image p { color: #fff; font-size: 85%; text-align: left; padding-top: 8px; }
以上CSS代码简明易懂,可能你还注意到了我们是怎样通过border-spacing
属性来控制单元格图像之间的距离的。制作一张网格布局变得再简单不过了,同时我们还可以避免那些使用float元素实现等高布局所带来的麻烦。