面试题:水平垂直居中的17种方法

简介: CSS 方面问的最多的问题之一,我想分三种情况,水平居中、垂直居中和水平垂直居中来分析

面试的时候,绝不能只说一种,绝不能说一种解决方案,绝不能停下你吞吞吐吐的嘴

CSS 方面问的最多的问题之一,我想分三种情况,水平居中、垂直居中和水平垂直居中来分析


单单就水平垂直居中而言,大概有以下几种方案:


居中元素不定宽高


  • absolute + transform
  • flex 属性居中
  • flex + 子项 margin auto
  • grid 属性居中
  • grid + 子项 margin auto
  • grid + 子项属性居中
  • -webkit-box 属性居中
  • table-cell + text-align
  • line-height + text-align
  • writing-mode
  • table


仅居中元素定宽高适用:


  • 须知宽高 + absolute + 负 margin
  • 须知宽高 + absolute + calc
  • 须知宽高 + absolute + margin auto


局限性较大的全局居中


  • 须知宽高 + fixed + transform
  • 须知宽高 + fixed + 负 margin
  • 须知宽高 + fixed + calc
  • 须知宽高 + fixed + margin auto


水平居中



text-align:center


text-align: center;


需设置 display: inline-block 行内块元素


绝对定位 + transform 位移


position: absolute;
left: 50%;
transform: translateX(-50%);


脱离文档流


宽度+ margin: 0 auto


width: 100px;
margin: 0 auto;


这里说明下,width:100px 必须是具体的数字,且这个居中是外层居中,宽度中的内容没有居中


垂直居中



绝对定位 + transform 位移


position: absolute;
top: 50%;
transform: translateY(-50%);


与水平方向的居中一样,都是脱离文档流的做法


table-cell + vertical-align


display: table-cell;
vertical-align: middle;


display: table-cell ,让其标签元素以表格单元格的形式呈现,类似于 td 标签,

vertical-align: middle,用来指定行内元素(inline)或表格单元格(table-cell)元素的垂直居中


水平垂直居中



绝对居中 + transform 位移


<div class="father">
  <div class="son">
    123123
  </div>
</div>


.father {
  position: relative;
}
.son {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}


flex 属性居中


<div class="father">
  <div class="son">
    123123
  </div>
</div>


.father {
  display: flex;
  justify-content: center;
  align-items: center;
}


flex + margin auto


<div class="father">
  <div class="son">
    123123
  </div>
</div>


.father {
  display: flex;
}
.son {
  margin: auto;
}


grid 属性居中


<div class="father">123123</div>
// 或者
<div class="father">
  <div class="son">
    123123
  </div>
</div>


.father {
  display: grid;
  justify-content: center;
  align-items: center;
}


grid 子项属性居中


<div class="father">
  <div class="son">
    123123
  </div>
</div>


.father {
  display: grid;
}
.son {
  align-self: center;
  justify-self: center;
}


grid + margin auto


<div class="father">
  <div class="son">
    123123
  </div>
</div>


.father {
  display: grid;
}
.son {
  margin: auto;
}


grid 和 flex 很像,是 flex 的升级版,所以 grid 能做的事情更多


以上绝对定位、flex、grid 关于水平垂直居中的做法,剩下再说居中比较老的布局方法


-webkit-box 属性居中


这是一个已经过时的布局,可以看看这篇文章 CSS3 display: flex 和 display: box 有什么区别?


网友一丝说:


flex 是 2012 年的语法,是以后的标准


box 是 2009 年的语法,已经过时,需要加上对应前缀


<div class="father">
  <div class="son">
    123123
  </div>
</div>


.father {
  display: -webkit-box;
  -webkit-box-pack: center;
  -webkit-box-align: center;
}


table-cell + text-align


<div class="father">
  <div class="son">
    123123
  </div>
</div>


.father {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
}
.son {
  display: inline-block;
}


line-height + text-align


<div class="father">
  <div class="son">
    123123
  </div>
</div>


.father {
  height: 200px;
  line-height: 200px;
  text-align: center;
}


line-heightheight ,行高和高度一样高,自然就垂直方向居中了


writing-mode


<div class="father">
  <div class="“son”">
    <div class="“sonson”">
      123123
    </div>
  </div>
</div>


.father {
  writing-mode: tb-lr;
  writing-mode: vertical-lr;
  text-align: center;
}
.father .son {
  writing-mode: lr-tb;
  writing-mode: horizontal-tb;
  text-align: center;
  width: 100%;
  display: inline-block;
}
.father9 .son .sonson {
  display: inline-block;
  text-align: initial;
}


这个很冷闷,有人介绍过这种情况


table


<table>
  <tbody>
    <tr>
      <td class="father">
        <div class="son">
          123123
        </div>
      </td>
    </tr>
  </tbody>
</table>


.father {
  text-align: center;
}


table 标签自己将它垂直居中了,text-align:center 后就是水平居中了


可以看 demo


元素有宽高的情况,又多了三种方案


须知宽高 + 绝对居中 + margin 负边距


<div class="father">
    <div class="son">
        123123
    </div>
</div>


.father {
  position: relative;
  height: 200px;
}
.son {
  width: 100px;
  height: 100px;
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -50px 0 0 -50px;
}


父元素必须要有个高度,这样才能撑开容器。子元素必须要有个宽高,才能计算出 margin 值


须知宽高 + 绝对定位 + calc


<div class="father">
  <div class="son">
    123123
  </div>
</div>


.father {
  position: relative;
  height: 200px;
}
.son {
  width: 100px;
  height: 100px;
  position: absolute;
  top: calc(50% - 50px);
  left: calc(50% - 50px);
}


与 margin 负边距一个道理,父元素需要设置一个高度。子元素必须要有高度,不用 margin,而用 CSS3 中的 calc,计算出要居中位移,兼容性需要支持 CSS3 属性


须知宽高 + 绝对居中 + margin: auto


<div class="father">
  <div class="son">
    123123
  </div>
</div>


.father {
  position: relative;
  height: 300px;
}
.son {
  width: 100px;
  height: 100px;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
}


同以上两种情况。


这三种需要定位方式来实现水平垂直居中的方法,需要设置父元素的高度(一定要有,撑开画面),子元素需要设置宽高,前两种方法是为了算出它在父元素中的相对位置,后一种方法是为了说明子元素是个容器(如果不设置宽高,就是无)


其他方法


其实,水平垂直居中方面,如果面试官硬要问还有吗?还真的有,用 fixed 定位。但这个方法有缺陷,虽然能实现水平垂直居中,但它是相对于视口(viewport),而非父元素


方法就是以上用 absolute 实现的改成 fixed 即可


  • 须知宽高 + fixed + transform
  • 须知宽高 + fixed + 负 margin
  • 须知宽高 + fixed + calc
  • 须知宽高 + fixed + margin auto


这四种方法,都需要设置子元素的宽高


这里贴一下代码


<div class="father">
  <div class="son">
    123123
  </div>
</div>


/* transform */
.son {
  width: 100px;
  height: 100px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: blue;
}
/* 负 margin */
.son {
  width: 100px;
  height: 100px;
  position: fixed;
  top: 50%;
  left: 50%;
  margin-left: -50px;
  margin-top: -50px;
  background: blue;
}
/* calc */
.son {
  width: 100px;
  height: 100px;
  position: fixed;
  top: calc(50% - 50px);
  left: calc(50% - 50px);
  background: blue;
}
/* margin: auto */
.son {
  width: 100px;
  height: 100px;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  margin: auto;
  background: blue;
}


总结



随着微软宣布放弃 IE11,现实项目中完全可以使用 flex 布局,grid 部分还不适配,但是以后肯定会取代 flex。


虽然写了很多,但是自己工作中也不会使用 table 、writing-mode、-webkit-box 等过时的布局方式,写这篇文章,纯粹是为了面试时被问到这种问题。


收获是 absolute 的居中要父子同心(父元素设置高度,子元素设置宽高),fixed 的居中只需要设置子元素的宽高。


线上 demo 查看


参考资料



  • 如何居中一个元素(终结版)


  • 给你一份详细的 CSS 布局指南,请查收


  • CSS 实现水平垂直居中的 1010 种方式(史上最全)



相关文章
|
2月前
|
缓存 算法 Java
Java面试题:深入探究Java内存模型与垃圾回收机制,Java中的引用类型在内存管理和垃圾回收中的作用,Java中的finalize方法及其在垃圾回收中的作用,哪种策略能够提高垃圾回收的效率
Java面试题:深入探究Java内存模型与垃圾回收机制,Java中的引用类型在内存管理和垃圾回收中的作用,Java中的finalize方法及其在垃圾回收中的作用,哪种策略能够提高垃圾回收的效率
28 1
|
23天前
|
Java
【Java基础面试二十】、介绍一下Object类中的方法
这篇文章介绍了Java中Object类的常用方法,包括`getClass()`、`equals()`、`hashCode()`、`toString()`、`wait()`、`notify()`、`notifyAll()`和`clone()`,并提到了不推荐使用的`finalize()`方法。
【Java基础面试二十】、介绍一下Object类中的方法
|
23天前
|
Java API 索引
【Java基础面试二十四】、String类有哪些方法?
这篇文章列举了Java中String类的常用方法,如`charAt()`、`substring()`、`split()`、`trim()`、`indexOf()`、`lastIndexOf()`、`startsWith()`、`endsWith()`、`toUpperCase()`、`toLowerCase()`、`replaceFirst()`和`replaceAll()`,并建议面试时展示对这些方法的熟悉度,同时深入理解部分方法的源码实现。
【Java基础面试二十四】、String类有哪些方法?
|
22天前
|
Java
【Java集合类面试三十】、BlockingQueue中有哪些方法,为什么这样设计?
BlockingQueue设计了四组不同行为方式的方法用于插入、移除和检查元素,以适应不同的业务场景,包括抛异常、返回特定值、阻塞等待和超时等待,以实现高效的线程间通信。
|
1月前
|
SQL 安全 测试技术
[go 面试] 接口测试的方法与技巧
[go 面试] 接口测试的方法与技巧
|
1月前
|
机器学习/深度学习 算法 Python
【机器学习】面试问答:决策树如何进行剪枝?剪枝的方法有哪些?
文章讨论了决策树的剪枝技术,包括预剪枝和后剪枝的概念、方法以及各自的优缺点。
40 2
|
1月前
|
机器学习/深度学习
【机器学习】面试题:LSTM长短期记忆网络的理解?LSTM是怎么解决梯度消失的问题的?还有哪些其它的解决梯度消失或梯度爆炸的方法?
长短时记忆网络(LSTM)的基本概念、解决梯度消失问题的机制,以及介绍了包括梯度裁剪、改变激活函数、残差结构和Batch Normalization在内的其他方法来解决梯度消失或梯度爆炸问题。
42 2
|
1月前
|
存储 机器学习/深度学习 缓存
【数据挖掘】XGBoost面试题:与GBDT的区别?为什么使用泰勒二阶展开?为什么可以并行训练?为什么快?防止过拟合的方法?如何处理缺失值?
XGBoost与GBDT的区别、XGBoost使用泰勒二阶展开的原因、并行训练的原理、速度优势、防止过拟合的策略以及处理缺失值的方法,突出了XGBoost在提升模型性能和训练效率方面的一系列优化。
31 1
|
1月前
|
机器学习/深度学习
【多线程面试题 二】、 说说Thread类的常用方法
Thread类的常用方法包括构造方法(如Thread()、Thread(Runnable target)等)、静态方法(如currentThread()、sleep(long millis)、yield()等)和实例方法(如getId()、getName()、interrupt()、join()等),用于线程的创建、控制和管理。