导航菜单
  • 首页
  • 首页>前端万博manbext备用网址>CSS万博manbext备用网址

    利用CSS中display:table/table-cell可以解决大部分垂直居中、多列等高、自适应布局

    尽管flex布局已经是大势所趋,但是IE11的支持都还不是很友好,在要兼容IE9的PC端,浮动、定位布局等老方法还是依然使用。特别是IE8+开始支持的display:table和display:table-cell,在一些特殊布局方面提供了很好的帮助,还是需要掌握。

    翻了很多文章,终于看到一篇介绍详细的文章,转载过来,以备后期查看。

    原文地址:css table布局大法,解决你大部分居中、多列等高、左右布局的问题

    看了这篇文章,你可以了解到以下布局方法:

  • table-cell

  • 定高水平垂直居中

  • 不定高水平垂直居中

  • 单行定高水平垂直居中

  • 单行不定高水平垂直居中

  • 多行定高水平垂直居中

  • 多行不定高水平垂直居中

  • 多列等高布局

  • 左边定宽右边自适应布局

  • 左边右边定宽中间自适应三列布局

  • 最近开发遇到一些布局上的问题,由于不确定因素比较多,比如不定宽高、单行多行的情况需要显示的样式基本相同。这样的情况会比较复杂,后来找到display:table-cell这个布局神器,这些问题也就不是问题了。比如以下这种情况:

    1.png

    基于这样的需求,我们通常都是每一种情况需要单独的写一份hack样式,这样写起来很麻烦。我们多么希望写一份样式,不管你里面的节点如何变,定不定宽高,多行与否都能表现一致。针对水平|垂直居中的情况,我找到了table-cell布局的方式,基本能解决。下面会总结一下table-cell的布局原理以及列举一些日常布局所遇到的情况。

    1、table的一些特性与表现形式

    虽然table布局因为它的一些非语义化、布局代码冗余,以及不好维护改版等缺点被赶出了布局界。但是在css不给力时期,table布局也曾风靡一时,就算现在看来table的一些布局的特性也是非常给力的,而幸好css也吸取了table布局一些好的特性为己用。让我们可以使用更少、更语义化的标签来模拟table布局,可以跳过table布局的缺点又实现我们想要的效果,所以我们首先需要了解table的一些特性以及对应的css属性。
    我们在不居中使用到的也就是table、tr、td的一些特性,所以我们只需要了解这三个标签的特性就足够了。

    table标签(display:table)

    1) table可设置宽高、margin、border、padding等属性。属性值的单位可以使用px,百分比值。

    2) table的宽度默认由内容的宽高撑开,如果table设置了宽度,宽度默认被它里面的td平均分,如果给某一个td设置宽度,那么table剩余的宽度会被其他的td平均分(有点类似flex布局)

    3) 给table设置的高度起到的作用只是min-height的作用,当内容的高度高于设置的高度时,table的高度会被撑高。

    tr标签(display:table-row)

    1) 给tr设置高度只起到min-height的作用,默认会平分table的高度。

    2) tr中的td默认高度会继承tr的高度,若给任一td设置了高度,其他td的高度也同样变高。适合多列等高布局

    3) 设置宽度、margin、都不起作用

    td标签(display:table-cell)

    1) td默认继承tr的高度,且平分table的宽度

    2) 若table(display:table)不存在,给td设置的宽高不能用百分比只能用准确的数值

    3) 给td设置vertical-align: middle; td元素里面(除float、position:absolute)所有的块级、非块级元素都会相对于td垂直居中

    4) 给td设置text-align: center; td元素里面所有非block元素(除float、position:absolute)都会相对于td水平居中,虽然block元素不居中,但其中的文字或inline元素会水平居中

    了解了table的一些属性,当我们遇到一些水平垂直居中的布局时,就会变得so easy了。

    2、图片定高|不定高水平垂直居中

    图片本身就是inline-block元素,那么我们只要给它的父级元素加个display:table-cell就好了。

    .box{    
    height: 200px;    
    width: 200px;    
    display: table-cell;    
    text-align: center;    
    border: 1px solid #ccc;    
    vertical-align: middle;
    }
    <div class="box">
        <img src="https://ss1.baidu.com/70cFfyinKgQFm2e88IuM_a/forum/pic/item/242dd42a2834349b406751a3ceea15ce36d3beb6.jpg">
    </div>

    2.png

    3、多行定高|不定高|定宽|不定宽水平垂直居中

    我们平时常见的就是单行水平垂直居中,其实就是简单的text-align:center; 然后再是line-height:xx 就搞定了。但是多行的就相对于复杂点。但是使用了table-cell之后,就变得很简单了。

    3.png

    当然,里面也可以是多个标签形成的多行,然后进行水平垂直居中。

    4.png

    其实实现的原理还是使用table-cell,先把外层box设置为table-cell,再把里面的元素设置为inline|inline-block(不定宽高|元素居中)或者block(宽度100%|文字居中)那么就可以控制里面的元素水平垂直居中了。基于这样的布局方式,你就可以把什么定高|不定高|定宽|不定宽|多行|单行的水平垂直居中都搞定了。

    4、左右浮动元素垂直居中

    由于display:table-cell对浮动元素是不起作用的,当我们需要两个元素一个左浮动一个右浮动,并且这连个元素还居中的时候。上面的方法就不起作用了。那我们可以换个法子,既然display:table-cell;的垂直居中不能直接对浮动元素起作用,那就来个间接的嘛。给两个浮动的元素外面一个display:inline-block;的元素,并且清除浮动。然后让display:table-cell的垂直居中对inline-block元素起作用就好了。

    5.png

    如果你的需求还需要在两个浮动的元素中再添加水平垂直居中的话,那么同样的道理,只需要在这两个元素中构造符合table-cell布局的结构就好了。

    5、一行多列水平垂直居中

    经常会有这样的需求,一列里面可能会有1、2、3个子元素,不管几个都是要居中的。有了table-cell就可以轻松解决了。实现原理也基本是把外层box设置为display:table-cell;然后设置居中。里面的元素item设置成inline或者line-block;就可以了,不管里面的item的个数多少,都会居中的,包括item是图片也会这样。

    6.png

    6、多列等高布局

    有这样的需求,一行有三个item,三个item的高度不定,但是这一行的三个item最终的高度以最高的那个为准。按照以前的做法要不就是砍掉需求,必须定高。实在不行就是等加载完之后用js计算三个item的高度,然后把最高的高度给其他item设置高度。这样有点恶心,并且会出现抖动。有了table-cell之后,这个就不成问题了,因为在一个tr中,里面的td必须是等高的,而不管里面内容的高度。

    7.png

    8.png

    认真看代码你会发现跟我们平时的定高布局不一样,每行外面必须得有一个ul来保证里面item的等高,并且里面还需要使用多余的li来控制间距。这样做的原因是因为tr里面的元素不会自动换行,所以必须手动换行,给外面加个ul,(说好的tr呢?)是这样的,被设置为display:table-cell的元素会跟相邻的兄弟元素共同生成一个虚拟的table、tr把自己包起来,谁叫td只能包在table里面呢。但是你直接写td标签是不会产生这样的效果的。而使用多余的li来控制间距是因为table-cell元素不认识margin,所以只能这样做了。(我的补充:虽然td不认识margin,但是可以利用table的border-collapse来实现td的间隔)在生成结构的时候就需要判断什么时候该换行了,而不是像以前一样在一个ul里面生成全部的li了。

    7、左边定宽右边自适应

    9.png

    我的补充:

    这个方法是左右两个都变成了table-cell,左边固定了宽度,右边就会占据父容器剩下的宽度。父容器必须显示为table。

    但是还有更简单的办法,那就是父容器不用display:table,左边用float:left,右边设置为display:table-cell,但是只设置为table-cell,父容器没有设置为table的时候,table-cell的元素宽度是由内容撑开的,就必须为这个table-cell设置一个很大的固定宽度,这个时候百分比也没有作用。

    .wrap{    
            width:80%;
            max-width:1000px;
            min-width: 768px;
            margin: 0 auto;
        }
        .aside{
            width:200px;
            height: 200px;
            background-color: #999;
            float: left;
        }
        .main{
            display: table-cell;
            height: 500px;
            background-color: #bbb;
            width:1000px;
        }
        
        <div class="wrap">
            <div class="aside">头像</div>
            <div class="main">个人信息</div>
        </div>

    8、左边右边定宽中间自适应三列布局

    10.png

    三列自适应宽度布局,为了中间那列能够自适应,必须父容器要display:table,这样所有的td才能占据完父容器的宽度,左右两列设置固定宽度,剩下的宽度都给了中间的td,所以达到自适应的效果。

    没有父容器为display:table的table-cell,不能设置百分比的值,只能有固定宽度值,宽度是由内容撑开。

    总结:

    使用table-cell还可以实现很多的布局,需要自己去发挥想象。总结下来也就需要记住几点,设置了display:table-cell的元素具有以下特性。

    1. text-align、vertical-align等对齐属性起作用,margin不起作用。宽高百分比值不起作用。

    2. 会生成虚拟的table、tr把自己包裹住,如果有相邻的兄弟元素也被设置了table-cell,则会跟兄弟元素一起生成虚拟的table、tr把自己包裹住,并一行等高显示

    3. 多个table-cell元素会占满被设置了display: table的元素的宽度,如果一个元素被设置了宽度,那么其他剩余的table-cell元素会占满剩下的宽度。当然,如果只有一个table-cell元素,就算设置了宽度也会占满table元素的宽度。

    4. 对设置了float、absolute的元素不起作用。且IE6、7不支持

    点赞


    2
    保存到:

    相关文章

    发表评论:

    ◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。

    Top