只用CSS作到彻底居中

  咱们都知道 margin:0 auto; 的样式能让元素水平居中,而 margin: auto; 却不能作到垂直居中……直到如今。可是,请注意!想让元素绝对居中,只须要声明元素高度,而且附加如下样式,就能够作到:css

1
2
3
4
5
.Absolute-Center {
   margin : auto ;
   position : absolute ;
   top : 0 ; left : 0 ; bottom : 0 ; right : 0 ;
}

  我并非第一个发现这种方法的人(不过我仍是敢把它叫作“彻底居中”),它有多是种很是广泛的技巧。但大多数介绍垂直居中的文章中并无提到过这种方法。若是不是浏览这篇文章的评论,我甚至根本就不会发现这个办法。html

  上面那篇文章的评论栏中,Simon提供了一个jsFiddle的连接,其余的方法相比之下就相形见绌了。(Priit也在评论栏中提到了一样的方法)。深刻研究了一番以后,我又用某些关键词找到了记载这种方法的三个网站:站点一站点二站点三web

  之前从未用过这种方法的我想试试,看看这种”彻底居中”的方法到底有多么神奇。 好处:浏览器

  • 跨浏览器,兼容性好(无需hack,可兼顾IE8~IE10)
  • 无特殊标记,样式更精简
  • 自适应布局,可使用百分比和最大最小高宽等样式
  • 居中时不考虑元素的padding值(也不须要使用box-sizing样式)
  • 布局块能够自由调节大小
  • img的图像也可使用

  同时注意:ide

  • 必须声明元素高度
  • 推荐设置overflow:auto;样式避免元素溢出,显示不正常的问题
  • 这种方法在Windows Phone上不起做用

浏览器支持:Chrome、Firefox、Safari、Mobile Safari、IE8-10。 “彻底居中”经测试能够完美地应用在最新版本的Chrome、Firefox、Safari、Mobile Safari中,甚至也能够运行在IE8~IE10上布局

 对照表

  “彻底居中”并非本篇文章中惟一的选项。要作到垂直居中,还存在着其余方法,各有各的长处。采起什么样的方法,取决于你所支持的浏览器,以及现有标签的结构。下面这张对照表可以帮你选出最符合你须要的方法。性能

所用样式测试

支持的浏览器字体

是否 响应式flex

内容溢出后的样式

resize:both

高度可变

主要缺陷

Absolute

现代浏览器&IE8+

会致使容器溢出

是*

‘可变高度’的特性不能跨浏览器

负margin值

全部

带滚动条

大小改变后再也不居中

不具备响应式特性,margin值必须通过手工计算

Transform

现代浏览器&IE9+

会致使容器溢出

妨碍渲染

Table-Cell

现代浏览器&IE8+

撑开容器

会加上多余的标记

Inline-Block

现代浏览器&IE8+&IE7*

撑开容器

须要使用容器包裹和hack式的样式

Flexbox

现代浏览器&IE10+

会致使容器溢出

须要使用容器包裹和厂商前缀(vendor prefix)

 说明

  在研究了规范和文档后,我总结出了“彻底居中”的工做原理:

  1.在普通文档流里,margin: auto; 的意思是设置元素的margin-top和margin-bottom为0。

  W3.org If ‘margin-top’, or ‘margin-bottom’ are ‘auto’, their used value is 0.

  2. 设置了position: absolute; 的元素会变成块元素,并脱离普通文档流。而文档的其他部分照常渲染,元素像是不在原来的位置同样。 Developer.mozilla.org …an element that is positioned absolutely is taken out of the flow and thus takes up no space

  3. 设置了top: 0; left: 0; bottom: 0; right: 0; 样式的块元素会让浏览器为它包裹一层新的盒子,所以这个元素会填满它相对父元素的内部空间,这个相对父元素能够是是body标签,或者是一个设置了position: relative; 样式的容器。 Developer.mozilla.org For absolutely positioned elements, the top, right, bottom, and left properties specify offsets from the edge of the element’s containing block (what the element is positioned relative to).

  4. 给元素设置了宽高之后,浏览器会阻止元素填满全部的空间,根据margin: auto; 的要求,从新计算,并包裹一层新的盒子。 Developer.mozilla.org The margin of the [absolutely positioned] element is then positioned inside these offsets.

  5. 既然块元素是绝对定位的,又脱离了普通文档流,所以浏览器在包裹盒子以前会给margin-top和margin-bottom设置一个相等的值。 W3.org If none of the three [top, bottom, height] are ‘auto’: If both ‘margin-top’ and ‘margin-bottom’ are ‘auto’, solve the equation under the extra constraint that the two margins get equal values.?AKA: center the block vertically

  使用“彻底居中”,有意遵守了标准margin: auto; 样式渲染的规定,因此应当在与标准兼容的各类浏览器中起做用。

 对齐

  容器内对齐

  使用“彻底居中”,就能够在一个设置了position: relative的容器中作到彻底居中元素了! (居中例子,请前往英文原文查看)

1
2
3
4
5
6
7
8
9
10
11
12
.Center-Container {
   position : relative ;
}
 
.Absolute-Center {
   width : 50% ;
   height : 50% ;
   overflow : auto ;
   margin : auto ;
   position : absolute ;
   top : 0 ; left : 0 ; bottom : 0 ; right : 0 ;
}

  接下来的示例会假设已经包含了如下样式,而且以逐步添加样式的方式提供不一样的特性。

  在可视区域内居中

  想要使内容区在可视区域内居中么?设置position: fixed样式,并设置一个较高的z-index值,就能够作到。

1
2
3
4
.Absolute-Center.is-Fixed {
   position : fixed ;
   z-index : 999 ;
}

  移动版Safari的说明:若是外面没有一层设置position: relative的容器,内容区会以整个文档的高度的中心点为基准居中,而不是以可视区域的高度中心点为基准居中。

  偏移值

  若是须要添加固定的标题,或者其余带偏移样式的元素,能够直接把相似top: 70px; 的样式写进内容区域的样式中。一旦声明了margin: auto; 的样式,内容块的top left bottom right的属性值也会同时计算进去。

  若是想让内容块在贴近侧边的过程当中保持水平居中,可使用right: 0; left: auto; 让内容贴在右侧,或者使用left: 0; right: auto; 使内容贴在左侧。

1
2
3
4
.Absolute-Center.is-Fixed {
   position : fixed ;
   z-index : 999 ;
}

  带响应式

  使用absolute的最大好处就是能够完美地使用带百分比的宽高样式!就算是min-width/max-width或者min-height/max-height也可以有如预期般的表现。

  再进一步加上padding样式的话,absolute式的彻底居中也丝绝不会破坏!

1
2
3
4
5
6
7
.Absolute-Center.is-Responsive {
   width : 60% ;
   height : 60% ;
   min-width : 200px ;
   max-width : 400px ;
   padding : 40px ;
}

  带溢出内容

  内容区高度大于可视区域或者一个position: relative的容器,其内容可能会溢出容器,或被容器截断。只要内容区域没有超出容器(没有给内容容器预留padding的话,能够设置max-height: 100%;的样式),那么容器内就会产生滚动条。

1
2
3
.Absolute-Center.is-Overflow {
   overflow : auto ;
}

  大小可调整

  使用其余样式,或者使用JavaScript调整内容区的大小,也是不用手动从新计算的!若是设置了resize的样式,甚至可让用户自行调节内容区域的大小。 “彻底居中”法,不管内容区怎么改变大小,都会保持居中。

  设置了min-/max- 开头的属性能够限制区块的大小而不用担忧撑开容器。

1
2
3
4
5
6
7
8
.Absolute-Center.is-Resizable {
   min-width : 20% ;
   max-width : 80% ;
   min-height : 20% ;
   max-height : 80% ;
   resize: both ;
   overflow : auto ;
}

  若是不设置resize: both的样式,能够设置transition样式平滑地在大小间切换。必定要记得设置overflow: auto样式,由于改变大小后的容器高宽颇有可能会小于内容的高宽。 “彻底居中”法是惟一一种能支持使用resize: both样式的方法。

  使用注意:

  • 须要设置max-width/max-height给内容区域留足够的空间,否则就有可能使容器溢出。
  • resize属性不支持移动版浏览器和IE8-10,若是用户体验很重要的话,请确保用户能够有其余替代方法来改变大小。
  • 同时使用resize样式和transition会使用户在开始改变大小时产生等于transition效果时间等长的延时。

  图像

  图像也一样有效!提供相应的class,并指定样式 height: auto; ,就获得了一张随着容器改变大小的响应式图片。

  请注意,height: auto; 样式虽然对图片有效,若是没有用到了后面介绍的‘可变高技巧’,则会致使普通内容区域伸长以适应容器长度。

  浏览器颇有多是根据渲染结果填充了图像高度值,因此在测试过的浏览器中,margin: auto; 样式就像是声明了固定的高度值通常正常工做。

  HTML:

1
< img src = "http://placekitten.com/g/500/200" alt = "" />

  CSS:

1
2
3
4
5
6
7
8
.Absolute-Center.is-Image {
   height : auto ;
}
 
.Absolute-Center.is-Image img {
   width : 100% ;
   height : auto ;
}

  可变高度

  “彻底居中”法的确须要声明容器高度,可是高度受max-height样式的影响,也能够是百分比。这很是适合响应式的方案,只须要设置好带溢出内容就行。

  另外一种替代方案是设置display: table样式居中,,无论内容的长度。这种方法会在一些浏览器中产生问题(主要是IE和Firefox)。我在ELL Creative的朋友Kalley写了一个基于Modernizr 的测试,能够用来检查浏览器是否支持这种居中方案。如今这种方法能够作到渐进加强。

  注意要点: 这种方法会破坏浏览器兼容性,若是Modernizr测试不能知足你的需求,你可能须要考虑其余的实现方案。

  • 与大小可调整技术是不兼容的
  • Firefox/IE8中使用display: table,内容区在垂直方向靠上,水平方向仍然居中。
  • IE9/10中使用display: table,内容区会跑到左上角。
  • 移动版Safari中内容区是水平对齐的,可是若是使用了百分比的宽度,水平方向上会稍稍偏离中心。

  Javascript:

1
2
3
4
/* Modernizr Test for Variable Height Content */
Modernizr.testStyles( '#modernizr { display: table; height: 50px; width: 50px; margin: auto; position: absolute; top: 0; left: 0; bottom: 0; right: 0; }' , function(elem, rule) {
   Modernizr.addTest( 'absolutecentercontent' , Math.round(window.innerHeight / 2 - 25 ) === elem.offsetTop);
});

  CSS:

1
2
3
4
.absolutecentercontent .Absolute-Center.is-Variable {
   display : table;
   height : auto ;
}

 其余方法

  “彻底居中”法是解决居中问题的好方法,同时也有许多能够知足不一样需求的其余方法。最多见的,推荐的方法有负margin值、transform法、table-cell法、inline-block法、以及如今出现的Flexbox法,这些方法其余文章都有深刻介绍,因此这里只会稍稍说起。

  负margin值

  这或许是最经常使用的方法。若是知道了各个元素的大小,设置等于宽高一半大小的负margin值(若是没有使用box-sizing: border-box样式,还须要加上padding值),再配合top: 50%; left: 50%;样式就会使块元素居中。

  须要注意的是,这是按照预想状况也能在工做在IE6-7下的惟一方法。

1
2
3
4
5
6
7
8
9
.is-Negative {
         width : 300px ;
         height : 200px ;
         padding : 20px ;
         position : absolute ;
         top : 50% ; left : 50% ;
         margin-left : -170px ; /* (width + padding)/2 */
         margin-top : -120px ; /* (height + padding)/2 */
}

  好处:

  • 浏览器兼容性很是好,甚至支持IE6-7
  • 须要的编码量不多

  同时注意:

  • 这是个非响应式的方法,不能使用百分比的大小,也不能设置min-/max-的最大值最小值。
  • 内容可能会超出容器
  • 须要为padding预留空间,或者须要使用box-sizing: border-box样式。

  transform法

  和“彻底居中”法的好处同样,简单有效,同时支持可变高度。为内容指定带有厂商前缀的transform: translate(-50%,-50%)和top: 50%; left: 50%;样式就可让内容块居中。

1
2
3
4
5
6
7
8
9
.is-Transformed {
   width : 50% ;
   margin : auto ;
   position : absolute ;
   top : 50% ; left : 50% ;
   -webkit-transform: translate( -50% , -50% );
       -ms-transform: translate( -50% , -50% );
           transform: translate( -50% , -50% );
}

  好处:

  • 内容高度可变
  • 代码量小

  同时注意:

  • 不支持IE8
  • 须要写厂商前缀
  • 会和其余transform样式有冲突
  • 某些状况下的边缘和字体渲染会有问题

  table-cell法

  这种多是最好的方法,由于高度能够随内容改变,浏览器支持也不差。主要缺陷是会产生额外的标签,每个须要居中的元素须要三个额外的HTML标签。

  HTML:

1
2
3
4
5
6
7
<div class= "Center-Container is-Table" >
   <div class= "Table-Cell" >
     <div class= "Center-Block" >
     <!-- CONTENT -->
     </div>
   </div>
</div>

  CSS:

1
2
3
4
5
6
7
8
9
.Center-Container.is-Table { display : table; }
.is-Table .Table-Cell {
   display : table-cell ;
   vertical-align : middle ;
}
.is-Table .Center-Block {
   width : 50% ;
   margin : 0 auto ;
}

  好处:

  • 内容高度可变
  • 内容溢出则能自动撑开父元素高度
  • 浏览器兼容性好

  同时注意:

  • 须要额外的HTML标签

  inline-block法

  迫切须要的方法:inline-block法居中。基本方法是使用 display: inline-blockvertical-align: middle样式和伪元素让内容块在容器中居中。个人实现用到了几个在其余地方见不到的新技巧解决了一些问题。

  内容区声明的宽度不能大于容器的100% 减去0.25em的宽度。就像一段带有长文本的区域。否则,内容区域会被推到顶端,这就是使用:after伪类的缘由。使用:before伪类则会让元素有100%的大小!

  若是内容块须要尽量大地占用水平空间,能够为大容器加上max-width: 99%;样式,或者考虑浏览器和容器宽度的状况下使用max-width: calc(100% – 0.25em) 样式。

  这种方法和table-cell的大多数好处相同,不过最初我放弃了这个方法,由于它更像是hack。无论这一点的话,浏览器支持很不错,并且也被证明是很流行的方法。

  HTML:

1
2
3
4
5
< div class = "Center-Container is-Inline" >
   < div class = "Center-Block" >
     <!-- CONTENT -->
   </ div >
</ div >

  CSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.Center-Container.is-Inline {
   text-align : center ;
   overflow : auto ;
}
 
.Center-Container.is-Inline:after,
.is-Inline .Center-Block {
   display : inline- block ;
   vertical-align : middle ;
}
 
.Center-Container.is-Inline:after {
   content : '' ;
   height : 100% ;
   margin-left : -0.25em ; /* To offset spacing. May vary by font */
}
 
.is-Inline .Center-Block {
   max-width : 99% ; /* Prevents issues with long content causes the content block to be pushed to the top */
   /* max-width: calc(100% - 0.25em) /* Only for IE9+ */
}

  好处:

  • 内容高度可变
  • 内容溢出则能自动撑开父元素高度
  • 浏览器兼容性好,甚至能够调整支持IE7

  同时注意:

  • 须要额外容器
  • 依赖于margin-left: -0.25em的样式,作到水平居中,须要为不一样的字体大小做调整
  • 内容区声明的宽度不能大于容器的100% 减去0.25em的宽度

  Flexbox法

  CSS将来发展的方向就是采用Flexbox这种设计,解决像垂直居中这种共同的问题。请注意,Flexbox有不止一种办法居中,他也能够用来分栏,并解决奇奇怪怪的布局问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.Center-Container.is-Flexbox {
   display : -webkit-box;
   display : -moz-box;
   display : -ms-flexbox;
   display : -webkit-flex;
   display : flex;
   -webkit-box-align: center ;
      -moz-box-align: center ;
      -ms-flex-align: center ;
   -webkit-align-items: center ;
           align-items: center ;
   -webkit-box-pack: center ;
      -moz-box-pack: center ;
      -ms-flex-pack: center ;
   -webkit-justify- content : center ;
           justify- content : center ;
}

  好处:

  • 内容能够是任意高宽,溢出也能表现良好
  • 能够用于各类高级布局技巧

  同时注意: 不支持IE8-9

  • 须要在body上写样式,或者须要额外容器
  • 须要各类厂商前缀兼容现代浏览器
  • 可能有潜在的性能问题

 最后的建议

  各项技术都有各自的好处,采起什么样的方法,取决于你所支持的浏览器,以及现有标签的结构。请使用上面提供对照表帮你选出最符合你须要的方法。

  “彻底居中”法简单方便,迅速及时。之前使用负Margin值的地方,均可以使用Absolute居中。无需繁琐的数学计算,无需额外标签,并且能够随时改变大小。

  若是网站须要可变高度的内容,并且同时照顾到浏览器兼容性的话,能够尝试table-cell和inline-block技术,若是想尝试新鲜事物的话,可使用Flexbox,并享受这种高级技术带来的好处。

  原文连接: codepen.io   翻译: 伯乐在线 埃姆杰

相关文章
相关标签/搜索