你的位置:首页 > 网页设计

[网页设计]CSS实现元素水平垂直居中—喜欢对称美,究竟是谁的错


在CSS中对元素进行水平居中是非常简单的:如果它是一个行内元素,就对它的父元素应用text-align:center;如果它是一个块级元素,就对它自身应用margin:auto。然而要对一个元素进行垂直居中,就有点束手无策了,本文介绍了几种常用的垂直居中方法以供参考!

一、表格布局法
二、基于行内块的解决方案(来自于第二篇参考文献)
三、基于绝对定位的解决方案
1.绝对定位+负的外边距
2.绝对定位+margin:auto
3.绝对定位+transform反向偏移
四、基于视口单位的解决方案(仅适用于基于视口的居中)
五、基于使用css3弹性布局(Flexbox)的解决方案
五、单行文本时的居中

一、表格布局法

利用表格的vertical-align属性,当然首先将显示方式设置为表格,如下:

  1. <!DOCTYPE html>
  2. <htmllang="en">
  3. <head>
  4. <metacharset="UTF-8">
  5. <title>Document</title>
  6. <styletype="text/css">
  7. .wrap{
  8. display:table;
  9. width:400px;
  10. height:200px;
  11. border:1px solid red;
  12. }
  13. .cell{
  14. display:table-cell;
  15. /*让其内容也水平居中*/
  16. text-align: center;
  17. vertical-align:middle;
  18. }
  19. .content{
  20. border:1px solid green;
  21. }
  22. </style>
  23. </head>
  24. <body>
  25. <divclass="wrap">
  26. <divclass="cell">
  27. <divclass="content">
  28. 看,我又居中没?
  29. </div>
  30. </div>
  31. </div>
  32. </body>
  33. </html>

这种方法需要在要居中的元素外层再添加一层包裹,如上面的.cell,好处是不用知道需要居中的元素是什么东西,比如上面的.content标签,在css中未对其位置进行任何设置。

二、基于行内块的解决方案(来自于第二篇参考文献)

这种方法确实讲究技巧,在实际实施中估计也不常用,但还是有必要介绍一下。具体思路是在包裹元素内设置一个“ghost”元素,使其高度为包裹元素的100%,然后同时设置“ghost”元素和居中元素vertical-align:middle.

  1. <!DOCTYPE html>
  2. <htmllang="en">
  3. <head>
  4. <metacharset="UTF-8">
  5. <title>Document</title>
  6. <styletype="text/css">
  7. .wrap{
  8. width:400px;
  9. height:200px;
  10. border:1px solid red;
  11. text-align: center;
  12. }
  13. .wrap:before{
  14. content:'';
  15. display:inline-block;
  16. height:100%;
  17. vertical-align: middle;
  18. }
  19. .content{
  20. display:inline-block;
  21. vertical-align: middle;
  22. width:150px;
  23. height:50px;
  24. border:1px solid green;
  25. }
  26. </style>
  27. </head>
  28. <body>
  29. <divclass="wrap">
  30. <divclass="content">
  31. 看,我居中没?
  32. </div>
  33. </div>
  34. </body>
  35. </html>

三、基于绝对定位的解决方案

1.绝对定位+负的外边距
  1. <!DOCTYPE html>
  2. <htmllang="en">
  3. <head>
  4. <metacharset="UTF-8">
  5. <title>Document</title>
  6. <styletype="text/css">
  7. .wrap{
  8. position: relative;
  9. width:400px;
  10. height:200px;
  11. border:1px solid red;
  12. }
  13. .content{
  14. position: absolute;
  15. top:50%;
  16. left:50%;
  17. width:100px;
  18. height:50px;
  19. margin-top:-25px;
  20. margin-left:-50px;
  21. border:1px solid green;
  22. }
  23. </style>
  24. </head>
  25. <body>
  26. <divclass="wrap">
  27. <divclass="content">
  28. 看,我居中没?
  29. </div>
  30. </div>
  31. </body>
  32. </html>

使用这种方法要求居中的元素具有固定的宽度和高度。

上面的方法本质上做了这样几件事情:先把要居中的元素的左上角放在已定位祖先元素的正中心,然后再利用负外边距把它向左、向上移动(移动距离相当于自身宽高的一半),从而把元素的正中心放置在祖先元素的正中心。借助CSS3中强大的calc()函数(当然实际实施过程中要考虑浏览器的兼容性),.content的样式还可以设置成:

  1. <styletype="text/css">
  2. .wrap{
  3. position: relative;
  4. width:400px;
  5. height:200px;
  6. border:1px solid red;
  7. }
  8. .content{
  9. position: absolute;
  10. top: calc(50%-25px);
  11. left: calc(50%-50px);
  12. width:100px;
  13. height:50px;
  14. border:1px solid green;
  15. }
  16. </style>

注意:表达式中有“+”和“-”时,其前后必须要有空格,如"widht: calc(12%+5em)"这种没有空格的写法是错误的calc函数的具体用法可以参考:
CSS3的calc()使用

2.绝对定位+margin:auto

实现原理:利用css定位规则,设置左右、上下方向定位为0,margin为auto,让css根据定位计算margin值,用hack的方式实现居中。居中块的尺寸需要固定。

寸需要可控

  1. <!DOCTYPE html>
  2. <htmllang="en">
  3. <head>
  4. <metacharset="UTF-8">
  5. <title>Document</title>
  6. <styletype="text/css">
  7. .wrap{
  8. position: relative;
  9. width:400px;
  10. height:200px;
  11. border:1px solid red;
  12. }
  13. .content{
  14. position: absolute;
  15. width:150px;
  16. height:50px;
  17. margin:auto;
  18. top:0;left:0;bottom:0;right:0;
  19. border:1px solid green;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <divclass="wrap">
  25. <divclass="content">
  26. 看,我居中没?
  27. </div>
  28. </div>
  29. </body>
  30. </html>


上面提到的两种绝对定位的方案最大的局限就是它要求元素的宽度和高度固定。下面介绍的第三种基于绝对定位的方案则不会出现这个问题,对于需要居中的元素宽高是否固定没有硬性要求,这样居中元素的尺寸就由其内容确定了。

3.绝对定位+transform反向偏移

还是上面的例子将内部元素的设置负的外边距的那两句改成

  1. <styletype="text/css">
  2. .wrap{
  3. position: relative;
  4. width:400px;
  5. height:200px;
  6. border:1px solid red;
  7. }
  8. .content{
  9. position: absolute;
  10. top:50%;
  11. left:50%;
  12. border:1px solid green;
  13. transform: translate(-50%,-50%);
  14. }
  15. </style>

使用这种方法对于居中元素宽高没有要求的原因是在translate()变形函数中使用百分比时,是以这个元素本身的宽度和高度为基准进行换算和移动的。

当然了,使用基于绝对定位的方法一定要先知道你要居中的对象是哪一个,这样才能对其设置绝对定位,这是与表格布局法明显不同的地方。

四、基于视口单位的解决方案(仅适用于基于视口的居中)

假如不想使用绝对定位,仍然可以采用translate()技巧来让元素以其自身宽高一半进行偏移,但是如果使用绝对定位,也就无法使用left和top使元素左上角位于容器正中心。
我们的第一反应很可能是用margin属性的百分比来实现。

  1. <!DOCTYPE html>
  2. <htmllang="en">
  3. <head>
  4. <metacharset="UTF-8">
  5. <title>Document</title>
  6. <styletype="text/css">
  7. .content{
  8. border:1px solid green;
  9. margin:50%auto0;
  10. transform: translateY(-50%);
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <divclass="content">
  16. 看,我居中没?
  17. </div>
  18. </body>
  19. </html>


实际上的结果却如上图所示,元素到了视口的下方。原因在于margin的百分比是以父元素的宽度作为基准的。在《CSS揭秘》这本大作中提到了一种方法可以正确使元素基于视口居中,该方法采用视口单位vh作为长度单位。1vh表示视口单位的1%。

  1. <!DOCTYPE html>
  2. <htmllang="en">
  3. <head>
  4. <metacharset="UTF-8">
  5. <title>Document</title>
  6. <styletype="text/css">
  7. .content{
  8. border:1px solid green;
  9. width:150px;
  10. margin:50vhauto0;
  11. transform: translateY(-50%);
  12. }
  13. </style>
  14. </head>
  15. <body>
  16. <divclass="content">
  17. 看,我居中没?
  18. </div>
  19. </body>
  20. </html>

五、基于使用css3弹性布局(Flexbox)的解决方案

css3的伸缩盒布局简直是一切布局的救星,遗憾的是,很多老浏览器不支持,哎哎哎哎!

  1. <!DOCTYPE html>
  2. <htmllang="en">
  3. <head>
  4. <metacharset="UTF-8">
  5. <title>Document</title>
  6. <styletype="text/css">
  7. .wrap{
  8. display: flex;
  9. width:400px;
  10. height:200px;
  11. border:1px solid red;
  12. }
  13. .content{
  14. margin:auto;
  15. border:1px solid green;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <divclass="wrap">
  21. <divclass="content">
  22. 看,我居中没?
  23. </div>
  24. </div>
  25. </body>
  26. </html>

想让.content居中就是这么简单,使包裹元素display: flex;要居中的元素margin: auto;这样水平和垂直方向都居中了,而且对于居中元素的宽高也没有要求。

Flexbox还有另一个好处在于,它可以在不知道需要居中的元素是什么的情况下使居中元素居中,就像方法一的效果一样,具体实现是借助:align-items和justify-content仍然用上面的例子.

  1. <styletype="text/css">
  2. .wrap{
  3. display: flex;
  4. align-items: center;
  5. justify-content: center;
  6. width:400px;
  7. height:200px;
  8. border:1px solid red;
  9. }
  10. .content{
  11. border:1px solid green;
  12. }
  13. </style>

实现效果相同。

五、单行文本时的居中

可以利用line-height属性与元素高度相同

  1. <!DOCTYPE html>
  2. <htmllang="en">
  3. <head>
  4. <metacharset="UTF-8">
  5. <title>Document</title>
  6. <styletype="text/css">
  7. .content{
  8. width:150px;
  9. height:100px;
  10. line-height:100px;
  11. text-align: center;
  12. border:1px solid green;
  13. }
  14. </style>
  15. </head>
  16. <body>
  17. <divclass="content">
  18. 看,我居中没?
  19. </div>
  20. </body>
  21. </html>


参考:
CSS揭秘(英文原版:CSS Secrets)
Centering in the Unknown



来自为知笔记(Wiz)