supce's blog

CSS Secret 读书笔记之水平居中&垂直居中


水平居中

行内元素

对于<span> img <input>等行内元素,只需要给父元素设置text-align: center

定宽块级元素

对于div p 等块级元素,如果是定宽,只需要给该元素设置左右marginauto

不定宽块级元素

  • 方法一:改变块级元素displayinline或者inline-block,然后设置父元素text-aligncenter

比如:

<div>
    <ul>
        <li>test one</li>
    </ul>
    <ul>
        <li>test one</li>
        <li>test two</li>
    </ul>
    <ul>
        <li>test one</li>
        <li>test two</li>
        <li>test three</li>
    </ul>
</div>

CSS:

div{
    width: 500px;
    height: 300px;
    margin: auto;
    border: 1px dashed #333;
}
ul{
    padding: 5px;
    list-style: none;
    text-align: center;
}
li{
    border:1px solid #333;
    display: inline;
}

这种方法虽然实现了居中,但是会导致块级元素功能的缺失,上面例子中已经无法给li设置宽和高(虽然可以利用margin和padding产生视觉上的宽和高)当然也可以直接设置li为inline-block

  • 方法二:通过给父元素设置float,然后父元素设置position:relative和left:50%,子元素设置position:relative和left:-50%来实现水平居中。

其基本原理如下:

1、没有浮动的div:大家都知道div是一个块元素,其默认的宽度就是100%:

2、如果div设置了浮动之后,他的内容有多宽度就会撑开有多大的容器(除了显式设置元素宽度值):

3、设置ul浮动到左侧:

4、然后设置ul的position为relative,让其在原来的位置右移50%(left:50%)

5、最后我们在li上设置position:relative,但其移动的方向和ul移动的方向刚好是反方向,而其移动的值保持一致:

保持HTML不变CSS代码如下:

div{
    width: 500px;
    height: 300px;
    margin: auto;
    border: 1px dashed #333;
}
ul{
    padding: 5px;
    float: left;
    position: relative;
    left: 50%;
    list-style: none;
    clear: both;  /*清除浮动*/
}
li{
    margin: 2px;
    position: relative;
    left: -50%;
    border:1px solid #333;
}

  • 方法三:在元素外加入table标签(包括 table、tbody、tr、td),该元素写在 td 内,然后设置左右margin的值为auto

在CSS Secret 读书笔记之结构与布局(一)中知道,如果是默认的自动表格布局算法,单元格的宽度是根据内容的宽度来进行分配的,这恰好是使用该方法的前提。

HTML:

<div>
    <table>
        <tbody>
            <tr>
                <td>
                    <ul>
                        <li>test one</li>
                        <li>test two</li>
                        <li>test three</li>
                    </ul>
                </td>
            </tr>
        </tbody>
    </table>    
</div>

CSS:

div{
        width: 500px;
        height: 300px;
        margin: auto;
        border: 1px dashed #333;
    }
    table{
        margin: auto;
    }
    ul{
        padding: 5px;
        list-style: none;
    }
    li{
        margin: 2px;
        float: left;
        border:1px solid #333;
    }


垂直居中

1、对于父元素高度不确定的文本,图片和块级元素::
设置父元素的上下内边距相同。
HTML:

<div class="parent one">
    <div class="centered">
        <h3>this is a test</h3>
        <p>this div is centered</p>
    </div>
</div>

CSS:

.parent{
    padding-top: 50px;
    padding-bottom: 50px;
    background: #ccc;
    border: 1px solid #c0c0c0;
}
.centered{
    width: 20em;
    border: #a0a0a0 solid 1px;
    background: #f5f5f5;
}

2、对于父元素高度确定的单行文本:
设置父元素的heightline-height两个属性的值相同。

line-height的值大于font-size时,会将大于的部分平均分配到文字的上下两端

HTML:

<div class="single_line">
    this is a test. 
</div>

CSS:

.single_line{
    font-size: 15px;
    height: 40px;
    line-height: 20px;
    border: 1px solid black;
}

3、对于多行文本:
设置父元素display为table,要被居中的元素display为table-cell和vertical-algin为middle
HTML:

<div class="out">
    <div class="in">
        这是一个多行文本,这是一个多行文本,这是一个多行文本
    </div>
</div>

CSS:

.out{
    margin: 20px;
    height: 250px;
    background: #ccc;
    border: 1px solid #c0c0c0;
    display: table;
}
.in{
    width: 200px;
    display: table-cell;
    vertical-align: middle;
}

4、inline-block方法:
设置元素display:inline-block; vertical-align:middle,为父元素设置after伪元素,将伪元素的display和vertical属性分别设置为inline-block和middle,最后设置伪元素高度与父元素高度相同(height:100%)

由于行内框的高度是由最高的行内框决定的,设置伪元素高度与父元素高度一致,然后利用vertical-algin即可

HTML:

<div class="container one">
    <div class="centered-one centered">
        <h1>this is a test</h1>
        <p>this div is centered</p>
    </div>
</div>

CSS:

.container{
    margin: 20px;
    height: 250px;
    background: #ccc;
    border: 1px solid #c0c0c0;
}
.centered{
    width: 20em;
    border: #a0a0a0 solid 1px;
    background: #f5f5f5;
}
.centered-one,.one:after{
    display: inline-block;
    vertical-align: middle;
}
.one:after{
    content: '';
    height: 100%;
}

5、对于宽高确定的元素:

方法一:利用绝对定位
设置父元素的position为relative,设置要垂直居中的元素position为absolute,top和bottom为0,上下外边距为auto。

元素在过度受限情况下,将margin设置为auto,浏览器会重算margin的值,过度受限指的是同时设置top/bottom与height或者left/right与width

计算公式为:

‘top’ + ‘margin-top’ + ‘border-top-width’ + ‘padding-top’ + ‘height’ + ‘padding-bottom’ + ‘border-bottom-width’ + ‘margin-bottom’ + ‘bottom’ = 包含块的高度,在其他值不是auto的时候,margin-top和margin-bottom是可以根据上式算出的

HTML:

<div class="container two">
    <div class="centered-two centered">
        <h1>this is a test</h1>
        <p>this div is centered</p>
    </div>
</div>

CSS:

.container{
    margin: 20px;
    height: 250px;
    background: #ccc;
    border: 1px solid #c0c0c0;
}
.centered{
    width: 20em;
    border: #a0a0a0 solid 1px;
    background: #f5f5f5;
}
.two{
    position: relative;
}
.centered-two{
    position: absolute;
    width: 300px;
    height: 150px;
    top:0; bottom:0;
    margin:auto 0;
}

方法二:利用负边距
设置父元素的position为relative,设置要垂直居中的元素position为absolute,top为50%,margin-top为高度的一般。

通过设置top为50%,将元素的左上角放在父元素的垂直中心,在利用margin-top为高度的一半,将元素的垂直中心与父元素的垂直中心重合

HTML:

<div class="container three">
    <div class="centered-three centered">
        <h1>this is a test</h1>
        <p>this div is centered</p>
    </div>
</div>

CSS:

.container{
    margin: 20px;
    height: 250px;
    background: #ccc;
    border: 1px solid #c0c0c0;
}
.centered{
    width: 20em;
    border: #a0a0a0 solid 1px;
    background: #f5f5f5;
}
.three{
    position: relative;
}
.centered-three{
    position: absolute;
    top: 50%;
    width: 300px;
    height: 150px;
    margin-top: -75px;
}

如果想要水平也居中,可以同时设置left为50%,margin-left为负的宽度的一半。

如果支持CSS3的话,为了增强自适应性,可以使用translateY()变形函数,这个函数支持百分比。
修改CSS代码如下:

.centered-three{
    position: absolute;
    top: 50%;
    /*width: 300px;
    height: 150px;
    margin-top: -75px;*/
    width: 20em;
    height: 10em;
    transform: translateY(-50%);
}

想要水平垂直居中,可以同时设置left:50%,transform:transform(-50%,-50%)

6、Flex布局
这个比较简单
HTML:

<div class="container four">
    <div class="centered-four centered">
        <h1>this is a test</h1>
        <p>this div is centered</p>
    </div>
</div>

CSS:

.four{
    display: flex;
    align-items: center;
}

如果想要水平垂直居中,只需修改CSS代码如下:

.four{
    display: flex;
    /*align-items: center;*/
}
.centered-four{
    margin: auto;
}