display:table家族的用途

一、display:table-cell属性简述

display:table-cell属性指让标签元素以表格单元格的形式呈现,类似于td标签。目前IE8+以及其他现代浏览器都是支持此属性的,但是IE6/7只能对你说sorry了,这一事实也是大大制约了display:table-cell属性在实际项目中的应用。

我们都知道,单元格有一些比较特别的属性,例如元素的垂直居中对齐,关联伸缩等,所以display:table-cell还是有不少潜在的使用价值的,虽说IE6/7不支持此属性,但是幸运的是,IE6/7一些乱糟糟的属性与渲染,我们可以其他方法实现同样或是类似的效果。

与其他一些display属性类似,table-cell同样会被其他一些CSS属性破坏,例如float, position:absolute,所以,在使用display:table-cell与float:left或是position:absolute属性尽量不用同用。设置了display:table-cell的元素对宽度高度敏感,对margin值无反应,响应padding属性,基本上就是活脱脱的一个td标签元素了。

二、display:table-cell与大小不固定元素的垂直居中

使用display:table-cell让大小不固定元素垂直居中已经是很老的方法了,关于此应用,我已经在“大小不固定的图片、多行文字的水平垂直居中”这篇文章中有过介绍。
以前图片垂直居中之截图 张鑫旭-鑫空间-鑫生活

方便阅读,这里再次展示下代码:

/*这里的大小是根据高宽上限128像素图片设置的*/
div{display:table-cell; width:1em; height:1em; border:1px solid #beceeb; font-size:144px; text-align:center; vertical-align:middle;} 
div img{vertical-align:middle;}

结果如下图:
table-cell和文字大小实现的图片垂直居中显示

这里有个demo地址,里面有display:table-cell实现大小不固定图片垂直居中的效果展示,您可以狠狠地点击这里

二、display:table-cell与两栏自适应布局

就在前不久,看facebook好友动态列表页面前端代码的时候才发现原来display:table-cell可以用在两栏的自适应布局上。
facebook的table-cell自适应方法 张鑫旭-鑫空间-鑫生活

虽然IE6/7不认识display:table-cell,但是亏了其一向自以为是的渲染与解析,我们可以很幸运的使用其他属性实现几乎一致的效果。
display:table-cell下的两栏自适应效果截图 张鑫旭-鑫空间-鑫生活

您可以狠狠地点击这里:display:table-cell下两栏自适应布局demo

代码展示:
本例中,左侧为头像,右侧内容自适应。其中头像部分使用了float属性,左浮动,IE8+以及Firefox、Chrome、Opera等现代浏览器右侧使用了display:table-cell属性,结果就自适应了,很简单的代码,很神奇的效果。
display:table-cell自适应布局代码展示 张鑫旭-鑫空间-鑫生活

OK,对于不认识display:table-cell属性的IE6/7呢?哦呵呵,很简单,使用display:inline-block属性代替display:table-cell就完全ok的啦!

原因在于:IE6/7下block属性的元素对inline-block属性是有反应,但是却不是纯洁的反应,而是怪蜀黍看到粉嫩小萝莉的一点邪念,就是让元素有个怪异的haslayout属性。//zxx:大家似乎都喜欢用haslayout解析一些老IE下的一些怪异现象,但我自己打心底里是不认同这个概念。

如果IE6/7是很标准的纯洁的解释inline-block属性的话,是无法实现自适应的,右侧的文字描述内容会跑到头像的下面,哦呵呵~~有点负负得正,以毒攻毒的意味。代码如下:

display:table-cell; *display:inline-block;

就万事大吉,收工回家了。

在本例demo中,右侧内容足够多,所以宽度完整的撑开了,如果内容有限,则宽度就是内容的宽度,此时想要让某个元素(例如关闭按钮)右侧定位就会有问题,解决方法就是定义一个非常宽的宽度,就像上面facebook截图中的CSS属性一样,所以,考虑到各种情况,更健壮耐用的CSS代码应如下:

display:table-cell; *display:inline-block; width:2000px; *width:auto;

或者使用:

display:table-cell;  width:2000px; *width:auto; *zoom:1;

这种两栏的自适应布局,不仅不要分别丈量与计算两列的宽度,连“页面重构鑫三无准则 之无宽度准则”中absolute自适应布局的头像宽度都不需要亮了,可以说是更加懒惰,更加直接的好方法。

三、display:table-cell下的等高布局

table表格中的单元格最大的特点之一就是同一行列表元素都等高。所以,很多时候,我们需要等高布局的时候,就可以借助display:table-cell属性。说到table-cell的布局,不得不说一下“匿名表格元素创建规则”:

CSS2.1表格模型中的元素,可能不会全部包含在除HTML之外的文档语言中。这时,那些“丢失”的元素会被模拟出来,从而使得表格模型能够正常工作。所有的表格元素将会自动在自身周围生成所需的匿名table对象,使其符合table/inline-table、table-row、table- cell的三层嵌套关系。

举个例子吧,如果我们为元素使用“display:table-cell;”属性,而不将其父容器设置为“display:table-row;”属性,浏览器会默认创建出一个表格行,就好像文档中真的存在一个被声明的表格行一样。如果您还不是很理解,可见参见支付宝UED的“基于display:table的CSS布局”一文。//zxx:支付宝今年的招牌广告做得很赞的~~

实现等高布局,毫无疑问,display:table-cell是首选,这就好比鼹鼠,生下来就是为了打洞用的。考虑到匿名创建表格元素的问题,所有table-cell元素外一定要留有一个用来包裹的标签。于是,我们有类似下面的CSS代码:

.list_row{display:table-row;}
.list_cell{display:table-cell; width:30%; padding:1.6%; background-color:#f5f5f5;}
/*中间一个元素背景淡蓝,有别于两边的淡灰色*/
.list_center{background-color:#f0f3f9;}

结果在现代浏览器下(如下Firefox3.6下截图):
table-cell下的等高布局 张鑫旭-鑫空间-鑫生活

您可以狠狠地点击这里:table-cell等高布局demo

对于不支持display:table-cell属性的IE6/7浏览器,又当如何解决呢?
我们可以使用“补差等高法”,就是一个一个很大的margin-bottom负值配上一个同样大小的padding-bottom值,本例中为了实例需要,margin-bottom值就百来像素。显然,由于两者原理不同,难免需要用到hack,所以demo完整CSS代码如下:

.list_row{display:table-row; overflow:hidden;}
.list_cell{display:table-cell; width:30%; margin-bottom:-100px; padding:1.6%; *padding-bottom:110px; background-color:#f5f5f5; *float:left;}
.list_center{background-color:#f0f3f9;}

认识display:table-cell属性的元素对margin属性不敏感,所以上面margin-bottom属性前没有加*号。HTML结构代码如下:

<div class="list_row">
    <div class="list_cell">你一定也有过这种感觉的。...罗兰《寂寞的感觉》</div>
    <div class="list_cell list_center">作为一个被基阿异捅过...水,四积阴功五读书。</div>
    <div class="list_cell">奔波了一...永远幸福快乐!</div>
</div>

//zxx:“补差等高法”虽然有效,也有兼容性,但是会带来一些潜在的问题,不宜多用。

四、display:table-cell下的列表布局

这里的列表布局专指横向repeat的布局,就像下图所示的:
列表布局示意  张鑫旭-鑫空间-鑫生活

一般这类布局都是使用浮动的。但是浮动布局的不足在于:一是需要清除浮动造成影响;二是不支持不定高列表的浮动。替代浮动布局的方法是有的,如果深究细节以及一些思想,方法还不少。其中有一个方法就是使用display:table-cell。

当然,说句心里话,将display:table-cell属性用在列表元素布局上,有点类似于张飞绣衣服,大马拉小车,优势并没有多大发挥,但是,毕竟也算浮动布局的一个备用替换方案。我的下一篇文章将会详细讲解浮动布局的替换方案,其中table-cell方法可以说是里面最不好的一个方法,本着过渡和热身的目的,这里只简单讲过。

首先是效果:
您可以狠狠地点击这里:display:table-cell下的列表布局

可以看到即使模块高度不一致,也不会产生浮动布局可能产生的错位。
由于table-cell需要每行包裹一个独立的标签,所以,在后台repeat输出的时候,需要两次循环,而是列数是限死的(与浮动布局一样)。对于简单的列表,使用display:table-cell是很难看到什么优势的,但是,如果列表复杂,数据多,内容细,display:table-cell可能会像大S订婚的传闻那样让人震惊。


现在已经很少有人会使用table来设计网页的布局,但是table真的过时了吗?不然!例如,在很常见的一个2列的布局中,左边我们想放一个导航菜单,右边放置正文内容,然后顶上放置一个header,页面最下方放置一个footer,这应该是一个很常见的页面布局方式。

这个时候,我们希望中间的siderbar跟正文内容都有相同的高度,顶着上面的header与下面的footer,该怎么办呢?

带着这个疑问,我将介绍css中的display属性table,table-cell,table-row,table-row-group,table-header-group,table-footer-group,table-caption,table-column,table-column-group。我想大家肯定对display:block,display:inline相当熟悉了,但是在这儿我还是想啰嗦一下对display熟悉的理解。

display属性会定义标签的盒子模型,每一个标签都有自己的默认盒子模型,例如div得默认盒子模型为block,span的默认盒子模型为inline,li的默认盒子模型为list-item。每一种盒子模型都有一些默认特征,例如block模型会默认独占父元素的宽度,当然,我们也可以设置它的宽度。但是inline模型则跟它相比有很大区别,inline元素会根据其内容自动调整宽高,因为就算我们显式设置其宽高也没用,正因为如此,inline元素一般不会独占父元素的宽度。

那么回到主题,当display属性为table,或table-*时,对应的元素会有什么样的特征呢?我们都知道table标签,它可以设置背景,边框,可以定义里面每行的高度,可以定义每列的宽度。可以直观理解当一个标签的display属性设置为table后,它就具有table标签的一些默认特征。那我们会问:这样的话跟直接使用table标签有什么区别呢?这就涉及到一个样式与数据分离的原则了,在HTML中我们应该尽量不要包含样式的信息,它只是用来定义网页的基本结构,元素之间的逻辑位置关系,以及所包含的信息,所以后来都推荐使用XHTML,也许有这方面的考虑吧。而CSS样式则用来告诉浏览器应该怎样展示HTML。如果直接用table,table定义的是一个语义结构,它除了会把数据用表格显示,并且指示这个地方就是一个表格,可能会在可访问性上造成歧义。

另外如果想调整布局也比较困难。另外,难道说我们就要彻底摒弃table标签吗?当然也不是!例如我们要呈现一些数据表,那还是用table非常合适的。

下面是一个用display=table布局的范例:


  1. <nav>  
  2.     <section class="command-list">  
  3.     <section class="command-item"><span>Home</span></section>  
  4.     <section class="command-item"><span>Archive</span></section>  
  5.     <section class="command-item"><span>Download</span></section>  
  6.     <section class="command-item"><span>Leisure</span></section>  
  7.     </section>  
  8. </nav>  
  1. .command-list {  
  2.    display: table;  
  3.    border-spacing10px;  
  4.    table-layoutfixed;  
  5. }  
  6. .command-item {  
  7.    displaytable-cell;  
  8.    border-radius: 10px;  
  9.    background-color#a9ed8c;  
  10.    text-aligncenter;  
  11.    width200px;  
  12.    line-height2em;  
  13.    vertical-alignmiddle;  
  14. }  

我们知道table, head, tr, td, footer都有严格的层次关系,那么使用display属性时会不会有这方面的限制呢?没有。原因是浏览器会自动创建匿名元素。例如在上面的例子中我们直接让子元素的display属性值为table-cell,这个时候,浏览器在呈现时会自动把这些拥有table-cell属性值的子元素依次添加到一个匿名的元素中,该元素的display属性值为table-row。

如果有如下的示例代码,那浏览器会怎么显示呢?
  1. <div class="cell">cell1</div>  
  2. <div class="cell">cell2</div>  
  3. <div class="cell">cell3</div>  
  4. <div>cell4</div>  
这个时候,会创建两个有父子关系的匿名元素,子元素有table-row属性值,父元素有table属性值.注意,cell4因为没有table-cell属性值,所以它不会被包含在匿名的table-row元素中。
另外,还有些相关的CSS属性:
table-layout 定义table layout算法
  • auto - 列宽由cell中不可断开(unbreakable)的内容的最大宽度觉得; 缺点是比较慢,因为它要读取table中所有的内容才能确定列宽

  • fixed - 水平宽度只由table的宽度和列宽决定,而不是cell中的内容; 性能比较好, 浏览器只要碰到第一行就能决定table怎么显示了
  • inherit - 属性值继承至父元素

border-collapse:定义table的边框是否折叠成一个边框
  • collapse - 边框尽量折叠,border-spacing和empty-cells属性值被忽略
  • separate - 边框分开,border-spacing和empty-cells属性值不被忽略
  • inherit - 属性值继承至父元素
在本人最开头提的那个问题怎么解决呢?如下是利用css table的解决办法:


  1.             <section class="content-container-sample">  
  2.                <section class="left-sidebar">  
  3.                    <ul>  
  4.                        <li>Message In Site</li>  
  5.                        <li>Forum</li>  
  6.                        <li>Blog</li>  
  7.                        <li>Ask Question</li>  
  8.                    </ul>  
  9.                </section>  
  10.                <section class="right-content">  
  11.                   <blockquote >  
  12.                      <p>Perhaps you’re feeling slightly uncomfortable about the example we’ve just seen—after all, haven’t web standards advocates like myself been insisting for years that you shouldn’t be using tables for layout?</p>  
  13.                   </blockquote>  
  14.                    <q>  
  15.                            Perhaps you’re feeling slightly uncomfortable about the example we’ve just seen—after all, haven’t web standards advocates like myself been insisting for years that you shouldn’t be using tables for layout?  
  16.                   </q>  
  17.                </section>  
  18.             </section>  
  1. .content-container-sample {  
  2.    display: table;  
  3.    border-collapsecollapse;  
  4.    width80%;  
  5.    margin:0 auto;  
  6. }  
  7. .left-sidebar {  
  8.    displaytable-cell;  
  9.    width25%;  
  10.    background-color#e0e0e0;  
  11. }  
  12. .left-sidebar > ul {  
  13.     list-style-type:none;     
  14. }  
  15. .left-sidebar > ul > li {  
  16.     margin-bottom:15px;  
  17. }  
  18. .right-content {  
  19.    displaytable-cell;  
  20.    width75%;  
  21.    height500px;  
  22.    background: -moz-linear-gradient(45deg, #ab9898#f3abab);  



我的一个布局应用实例:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<style type="text/css">
    #div_table{
    width: 960px;
    height: 480px;
    display: table;
    position: absolute;
    top: 20px;
    left: 100px;
        }
    #div1{
    border: 1px solid #0F0;
    display: table-cell;
    height: 480px;
    width: 200px;
    left: 0px;
    top: 0px;
    position: absolute;
        }    
    #div2{
    display: table-cell;
    position: absolute;
    height: 480px;
    width: 460px;
    border: 1px solid #F00;
    left: 200px;
    top: 0px;
        }    
    #div3{
    display: table-cell;
    position: absolute;
    height: 480px;
    width: 300px;
    left: 660px;
    top: 0px;
    border: 1px solid #000;
        }    
</style>
</head>

<body>
<div id="div_table">
        <div id="div1">
        </div>
        <div id="div2"></div>
        <div id="div3"></div>
    </div>
</body>
</html>





五、结语

对于display:table-cell,我自己其实用的并不多,毕竟其特殊之处就在于垂直居中,等高,水平级联,匿名创建等特性,其他种种属性可以使用其他更好的display属性代替的。但是话说回来,不太使用display:table-cell属性的真正的原因可能是对该属性的了解的还不够深入,可能该属性本身是存在很多非常实用的应用,但是自己由于掌握不够而不知道。所以,要是哪位同行知道display:table-cell其他一些不错的应用的话,欢迎大力补充,不甚感谢!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值