display:inline-block

声明display:inline-block将其变成行内块级元素,那么可用text-align和line-height声明水平垂直居中了,但是行内块级元素与匿名行内盒的基线对齐存在很大差异,所以需声明vertical-align:middle将其调整到垂直居中的位置,不过这也是近似垂直居中,父节点最后还需声明font-size:0消除该差异

  1. .center-layout {
  2. line-height: 400px;
  3. text-align: center;
  4. font-size: 0;
  5. div {
  6. display: inline-block;
  7. vertical-align: middle;
  8. }
  9. }

display:table-cell

父节点声明display:table-cell模拟表格布局的垂直居中;子节点声明margin:0 auto使其水平居中

  1. .center-layout {
  2. display: table-cell;
  3. vertical-align: middle;
  4. div {
  5. margin: 0 auto;
  6. }
  7. }

position

该方式也是最传统最稳定的水平垂直居中布局了,唯二的缺点就是声明属性稍多和必须已知宽高。要点是使用margin负值将节点拉回最中间,所以必须已知宽高才能计算margin负值,通常是margin-left和margin-top,可连写成margin:-(height/2) 0 0 -(width/2)

  1. .center-layout {
  2. position: relative;
  3. div {
  4. position: absolute;
  5. left: 50%;
  6. top: 50%;
  7. margin: -50px 0 0 -50px;
  8. }
  9. }

自从CSS3的transform普及后,声明transform:translate(-50%,-50%)可代替margin负值了,这样就无需声明宽高和计算宽高的二分之一是多少,真正做到自适应水平垂直居中。
但是存在一个缺陷,若节点需额外使用transform,那么就比较麻烦了。将额外的transform合并到水平垂直居中的transform:translate(-50%,-50%)里,就会存在有一个比较棘手的变换顺序问题,在第12章变换与动画中会详细讲解。解决方式就是在节点外部套上一层

,把transform:translate(-50%,-50%)转嫁到
上,那么节点就能自由使用transform了

  1. .center-layout {
  2. position: relative;
  3. div {
  4. position: absolute;
  5. left: 50%;
  6. top: 50%;
  7. transform: translate(-50%, -50%);
  8. }
  9. }

flex

  1. .center-layout {
  2. display: flex;
  3. justify-content: center;
  4. align-items: center;
  5. }

当然还有一个隐藏的终极方式,也是史上最简方式。只需声明两个重要属性

  1. .center-layout {
  2. display: flex;
  3. div {
  4. margin: auto;
  5. }
  6. }