diff --git a/03-CSS进阶/04-如何让一个元素水平垂直居中?.md b/03-CSS进阶/04-如何让一个元素水平垂直居中?.md new file mode 100644 index 0000000..f3d1dc3 --- /dev/null +++ b/03-CSS进阶/04-如何让一个元素水平垂直居中?.md @@ -0,0 +1,363 @@ + +## 前言 + +如何让一个子元素在父容器里**水平垂直居中**?这个问题必考,在实战开发中,也应用得非常多。 + +你也许能顺手写出好几种实现方法。但大部分人的写法不够规范,经不起千锤百炼。 + +这篇文章中,我们来列出几种常见的写法,最终你会明白,哪种写法是最优雅的。 + + +## 如何让一个行内元素(文字、图片等)水平垂直居中 + +> 行内元素的居中问题比较简单。 + +### 行内元素水平居中 + +给父容器设置: + +``` + text-align: center; + +``` + +### 行内元素垂直居中 + +让**文字的行高** 等于 **盒子的高度**,可以让单行文本垂直居中。比如: + +```css + .father { + height: 20px; + line-height: 20px; + } +``` + +## 如何让一个块级元素水平垂直居中 + +> 这一段是本文的核心。如何让一个块级的子元素在父容器里水平垂直居中?有好几种写法。我们一起来看看。 + +### margin: auto 的问题 + +在 CSS 中对元素进行水平居中是非常简单的:如果它是一个行内元素,就对它的父容器应用 `text-align: center`;如果它是一个块级元素,就对它自身应用 `margin: auto`或者 `margin: 0 auto`。 + +我们都知道,`margin: auto`相当于`margin: auto auto auto auto`。`margin: 0 auto`相当于`margin: 0 auto 0 auto`,四个值分别对应上右下左。其计算值取决于**剩余空间**。(参考链接:) + +但是,如果要对一个元素垂直居中,`margin: auto`就行不通了。 + +比如下面这段代码: + +```html + + + + + + Document + + + +
+
+
+ + + + +``` + + +上面的代码中,父元素和子元素都是定宽高的,即便在这种情况下,我给子元素设置 `margin: auto`,子元素依然没有垂直居中。 + +那还有没有比较好的通用的做法呢? + +### 方式一:绝对定位 + margin(需要指定子元素的宽高,不推荐) + +```html + + + + + + Document + + + +
+
子元素的内容
+
+ + + + +``` + + +**代码解释**:我们先让子元素的左上角居中,然后向上移动宽度的一半(50px),就达到了垂直居中的效果;水平居中的原理类似。 + +**不足之处**:要求指定子元素的宽高,才能写出 `margin-left`和 `margin-right`的属性值。 + +但是,在通常情况下,对那些需要居中的元素来说,其宽高往往是由其内容来决定的,不建议固定宽高。 + + +### 方式二:绝对定位 + translate(无需指定子元素的宽高,推荐) + +```html + + + + + + Document + + + +
+
子元素的内容
+
+ + + +``` + +这种写法,在没有指定子元素宽高的情况下,也能让其在父容器中垂直居中。因为 translate() 函数中使用百分比值时,是以这个元素自身的宽度和高度为基准进行换算和移动的(**动态计算宽高**)。 + + +### 方式3:flex 布局(待改进) + +将父容器设置为 Flex 布局,再给父容器加个属性`justify-content: center`,这样的话,子元素就能水平居中了;再给父容器加个属性 `align-items: center`,这样的话,子元素就能垂直居中了。 + +代码举例: + +```html + + + + + + Document + + + +
+
子元素的内容
+
+ + + + +``` + +上面这种写法的,不足之处在于:给父容器设置属性`justify-content: center`和`align-items: center`之后,导致父容器里的所有子元素们都垂直居中了(如果父容器里有多个子元素的话)。可我明明只向让指定的**某个子元素**居中,要怎么改进呢? + +### 方式4: flex 布局 + margin: auto(推荐) + +我们只需写两行声明即可:先给父容器设置 `display: flex`,再给指定的子元素设置我们再熟悉不过的 `margin: auto`,即可让这个指定的子元素在**剩余空间**里,水平垂直居中。大功告成。 + +代码举例: + +```html + + + + + + Document + + + +
+
子元素的内容,想水平垂直居中
+
这个元素不想水平垂直居中
+
+ + + +``` + +请注意,当我们给父容器使用 Flex 布局 时,子元素的`margin: auto`不仅让其在水平方向上居中,**垂直方向上也是居中的**。 + +参考文章:[探秘 flex 上下文中神奇的自动 margin](https://www.cnblogs.com/coco1s/p/10910588.html) + + +## 垂直居中的典型应用场景:红包幕帘/弹窗 + +### 问题引入 + +就拿“弹窗”这一点来说,现在大家的弹窗都是各种样式、各种布局满天飞。不过进公司后,大家在第一次写弹窗之前,都会问一个问题:“弹窗这么通用的东西,没有一个规范吗?”说完之后,又默默写自己的有个性的弹窗去了。 + +建议大家在写弹窗的时候,无论如何,一定要**严格采用**水平居中、垂直居中的写法。 + +千万不要用 `margin-top` 这种举例屏幕顶部的距离来计算弹窗的位置,太搓了。不要让领导觉得:“你们写了这么久的前端代码,连个弹窗都搞不定?” + +### 移动端,红包幕帘/弹窗 居中的规范写法(非常标准) + +移动端场景,这里提供一个 红包幕帘/弹窗 的居中写法。注意,是严格居中,非常标准。为什么是移动端?你有见过PC网页端给你送红包的么? + +在实战开发中,下面的这段代码,可以直接拿去用。注释详细,贴心无比。 + +```html + + + + + + Document + + + +
默认文档流中的页面主体
+ +
+ + +
+ + + +``` + +实现效果: + +![](http://img.smyhvae.com/20191010_1510.png) + + +**补充**: + +1、如果你的页面中,有很多弹窗,建议将弹窗封装成一个抽象组件。 + +2、任何弹窗,都需要解决“滚动穿透”的问题,本文篇幅有限,请自行查阅。 + + +## 参考链接 + +- [七种方式实现垂直居中](https://jscode.me/t/topic/1936) + +- [margin:auto实现绝对定位元素的水平垂直居中](http://www.zhangxinxu.com/wordpress/2013/11/margin-auto-absolute-%E7%BB%9D%E5%AF%B9%E5%AE%9A%E4%BD%8D-%E6%B0%B4%E5%B9%B3%E5%9E%82%E7%9B%B4%E5%B1%85%E4%B8%AD/) + diff --git a/03-CSS进阶/如何居中.md b/03-CSS进阶/如何居中.md deleted file mode 100644 index 1992cee..0000000 --- a/03-CSS进阶/如何居中.md +++ /dev/null @@ -1,196 +0,0 @@ - -## 如何居中(必考) - -### 水平居中 - -1、**行内元素:**(文字、图片等水平居中) - -给父亲设置: - -``` - text-align: center; - -``` - -另外,**让文字的行高 等于 盒子的高度**,可以让单行文本垂直居中。 - - -2、**块级元素:**(让标准流中的盒子水平居中) - -给元素设置:(让当前元素在父亲里剧中) - -``` - //方式一 - margin: auto; - - 方式二 - margin: 0 auto; -``` - -上面的代码, `margin: auto`相当于`margin: auto auto auto auto`。`margin: 0 auto`相当于`margin: 0 auto 0 auto`,四个值分别对应上右下左。 - -- 垂直方向:根据规范,margin-top: auto 和 margin-bottom: auto,其计算值为0。 - -- 水平方向:水平方向的 auto,其计算值取决于可用空间(**剩余空间**)。 - -参考链接: - -### 垂直居中/水平居中(元素的高度已知) - -方法:绝对定位 + margin-top - -如果盒子是绝对定位的,此时已经脱标了,`margin:auto`无效。如果还想让其居中(位于父亲的正中间),可以这样做: - -```html - - - - - Title - - - - - -
-
- 一串文字一串文字一串文字一串文字一串文字一串文字一串文字一串文字一串文字一串文字 -
-
- - - -``` - -如上方代码所示,我们先让这个高度为100px的盒子,上边线居中,然后向上移动宽度的一半(50px),就达到了垂直居中的效果。水平居中的原理类似。 - -效果: - -![](http://img.smyhvae.com/20180322_1843.png) - -### 垂直居中/水平居中(元素的高度未知) - -**方法1:**模拟表格法 - -将父元素设置为display:table,然后将子元素也(就是要垂直居中显示的元素)设置为display:table-cell,然后加上vertical-align:middle来实现。 - -html代码: - -```html - - - - - Title - - - - - -
-
-
-

测试垂直居中效果测试垂直居中效果测试垂直居中效果测试垂直居中效果

-
-
-
- - - - -``` - -效果: - -![](http://img.smyhvae.com/20180322_1833.png) - - - -**方式二:**绝对定位 + `margin:auto` - -```css -.element { - position: absolute; - left: 0; top: 0; right: 0; bottom: 0; - margin: auto; /* 有了这个就自动居中了 */ -} -``` - -代码两个关键点: - -- 上下左右均0位置定位; - -- margin: auto - -**方式三:**用绝对定位 + translate 位移来做 - -```css - div { - background-color: red; - position: absolute; 绝对定位的盒子 - top: 50%; 首先,让上边线居中 - transform: translateY(-50%); 然后,利用translate,往上走自己宽度的一半【推荐写法】 - } -``` - -**方式四:**flex 布局 - -```css - .parent{ - display: flex;/*Flex布局*/ - display: -webkit-flex; /* Safari */ - align-items: center;/*设置子元素在侧轴方向上的布局*/ - } -``` - -参考链接: - -- [七种方式实现垂直居中](https://jscode.me/t/topic/1936) - -- [margin:auto实现绝对定位元素的水平垂直居中](http://www.zhangxinxu.com/wordpress/2013/11/margin-auto-absolute-%E7%BB%9D%E5%AF%B9%E5%AE%9A%E4%BD%8D-%E6%B0%B4%E5%B9%B3%E5%9E%82%E7%9B%B4%E5%B1%85%E4%B8%AD/) -