renjie-run / blog

Personal Blog
2 stars 0 forks source link

常用的控制元素水平垂直解决方案 - 已知宽高 #11

Open renjie-run opened 4 years ago

renjie-run commented 4 years ago

处理元素水平垂直居中的场景最为常见,方法也数不胜举,或简单粗暴直接,或为奇伎淫巧,不能评判某些实现方式的好坏,但总有一个会是最为适合你的业务需求,这里整理了一些常用的处理方案(仅通过 CSS 实现)。

前期准备

HTML

<div class="father">
    <div class="child"></div>
</div>

CSS

.father {
  width: 300px;
  height: 300px;
  border: 1px solid red;
}

.child {
  width: 100px;
  height: 100px;
  background-color: skyblue;
}

1. 绝对定位 + margin

.father {
  position: relative;
}

.child {
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -50px;
  margin-left: -50px;
}

这里相对于父元素分别向下、向右偏移了50%的距离,这里偏移距离是以子元素的左上角为基准的,所以偏移的距离会多出元素自身大小的 1/2,所以需要配合margin来矫正一下。

2. 绝对定位 + calc

.father {
  position: relative;
}

.child {
  position: absolute;
  top: calc(50% - 50px);
  left: calc(50% - 50px);
}

calc在某些场景下使用起来非常方便,这里的实现思路跟第一种方案的思路基本一致,只不过这里设置偏移的距离的时候直接通过calc来计算出来了。

3. 绝对定位 + transform

.father {
  position: relative;
}

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

实现思路同第一种方案,这里矫正偏移距离的方式是通过 transform: translate(x, y) 来处理的,translate是参考自己的位置来平移的,这里就不展开讲这个属性了。

4. 绝对定位 + margin: auto

.father {
  position: relative;
}

.child {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
}

这里主要是设置marginauto时,四个方向的margin会平分剩余空间,从而让子元素能够在父盒子内水平垂直居中。

5. line-height + text-align

.father {
  line-height: 300px;
  font-size: 0;
  text-align: center;
}

.child {
  font-size: 16px;
  line-height: initial;
  text-align: left;
  vertical-align: middle;
  display: inline-block;
}

首先要将子盒子设置为行内块级元素,然后通过将父盒子的line-height设置为自身的高度使子盒子在垂直方向居中,再通过将text-align设置为center使子盒子在水平方向居中。

这里要注意的是父盒子将font-size设置为 0,是为了消除行内块级元素会产生空格的问题,同时子盒子也要设置相应的样式来消除这些继承过来的样式所产生的影响。

6. table-cell

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

.child {
  display: inline-block;
}

父盒子通过将display设置为 table-cell,然后使用 text-align: center使子元素在水平方向居中,使用vertical-align: middle使子元素在垂直方向居中。这里需要注意的是,子元素需要是行内元素或行内块级元素。

7. flex

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

8. grid

.father {
  display: grid;
}

.child {
  align-self: center;
  justify-self: center;
}

9. writing-mode

.father {
  writing-mode: vertical-lr;
  text-align: center;
}

.child {
  display: inline-block;
  writing-mode: horizontal-tb;
  margin: 0 calc(50% - 50px);
}

writing-mode: vertical-lr效果为垂直方向内内容从上到下,水平方向从左到右,通过对父元素设置该样式改变了子盒子在父盒子内排列方向,再结合text-align: center样式使子盒子能够在垂直方向居中,子盒子通过margin: 0 calc(50% - 50px)样式使子盒子能够在水平方向居中。

10. flex + margin

.father {
  display: flex;
}

.child {
  margin: auto;
}

/* 子盒子也可以使用如下样式 */
.child {
  align-self: center;
  margin: 0 auto;
}

11. grid + margin

.father {
  display: grid;
}

.child {
  margin: auto;
}

利用伪元素来实现居中,但感觉用的场景应该不多,这里就不列举了,有兴趣的话可以网上专门查阅。

能够实现水平垂直居中的方法还有很多,期待更好的发现吧!

最终都是要实现这么个效果(就是大小为 100 100 的子盒子,水平垂直居中于大小为 300 300 的盒子中): 水平垂直居中效果图