惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
L
LangChain Blog
WordPress大学
WordPress大学
MyScale Blog
MyScale Blog
The Cloudflare Blog
J
Java Code Geeks
Google DeepMind News
Google DeepMind News
Recent Announcements
Recent Announcements
Microsoft Azure Blog
Microsoft Azure Blog
Y
Y Combinator Blog
有赞技术团队
有赞技术团队
Last Week in AI
Last Week in AI
酷 壳 – CoolShell
酷 壳 – CoolShell
Martin Fowler
Martin Fowler
小众软件
小众软件
量子位
月光博客
月光博客
P
Proofpoint News Feed
IT之家
IT之家
腾讯CDC
博客园 - 三生石上(FineUI控件)
博客园 - 司徒正美
雷峰网
雷峰网
V
Visual Studio Blog

一颗小树

周更的第 100 篇 改变阅读方式 宝贵的人生建议 小树的工具库 2023 读《重构》有感 仅需 10 分钟,用 GPTs 实现文章总结助手 高质量的需求交付 产品始于问题,而不是解决方案 如何更好地休息 最优解人生 与体重斗,其乐无穷 结构化 prompt = 数字员工? 持续创作的法门 如何降低知识焦虑 7 月思维碎片 N 倍生产力提升:我的 AI 助理 Indie Hacker,互联网打工人的下一个出路? 如何成就伟大事业 夏日碎片 小报编辑的自我修养 一颗小树 #49 投入真实生活 一颗小树 #48 过年杂记 一颗小树 #47 我的人生信念(2023) 一颗小树 #46 回本就卖 一颗小树 #45 规划和落地 小树的 2022 年终总结 一颗小树 #44 构建高质量信源 一颗小树 #43 我的 2022 书单 一颗小树 #42 阳了怎么办 一颗小树 #41 一人企业
把简单做好也不简单-css水平垂直居中
也树 · 2016-12-15 · via 一颗小树

44 年前我们把人送上月球,但在 CSS 中我们仍然不能很好实现水平垂直居中。

作者:Icarus 原文链接:把简单做好也不简单-css 水平垂直居中

水平垂直居中有相同点也有不同点,接下来讨论常见的方式。

如无特殊说明,以下示例 html 均为:

<div class="md-warp">
	<span class="md-main"></span>
</div>

基础样式为:

.md-warp{
	width: 400px;
	height: 300px;
	max-width: 100%;
	border: 1px solid #000;
}
.md-main{
	display: block;
	width: 100px;
	height: 100px;
	background: #f00;
}

水平居中

margin 法

需要满足三个条件:

  • 元素定宽
  • 元素为块级元素或行内元素设置display:block
  • 元素的margin-leftmargin-right都必须设置为 auto 三个条件缺一不可。

demo:

.md-main{
	margin: 0 auto;
}

定位法

需要满足三个条件:

  • 元素定宽
  • 元素绝对定位,并设置left:50%
  • 元素负左边距margin-left为宽度的一半

demo1:

.md-warp{
	position: relative;
}
.md-main{
	position: absolute;
	left: 50%;
	margin-left: -50px;
}

有些时候我们的元素宽度可能不是固定的,不用担心,我们依然可以使用定位法实现水平居中,此时需要用到 css3 中的transform属性中的translate,可以使元素移动时相对于自身的宽度和高度。 需要注意,这种方法需要 IE9+才可以实现。

demo2

.md-warp{
	position: relative;
}
// 注意此时md-main不设置width为100px
.md-main{
	position: absolute;
	left: 50%;
	-webkit-transform: translate(-50%,0);
	-ms-transform: translate(-50%,0);
	-o-transform: translate(-50%,0);
	transform: translate(-50%,0);
}

不定宽

文字水平居中

对于单行文字来说,直接使用text-align: center即可。 多行文字可以看作一个块级元素参考 margin 法和定位法。

垂直居中

定位法

和水平居中类似,只是把left:50%换成了top:50%,负边距和transform属性进行对应更改即可。

优点:能在各浏览器下工作,结构简单明了,不需增加额外的标签。

demo1:

.md-warp{
	position: relative;
}
.md-main{
	position: absolute;
	/* 核心 */
	top: 50%;
	margin-top: -50px;
}

运用 css3 中的 clac()属性能简化部分代码:

.md-warp{
	position: relative;
}
.md-main{
	position: absolute;
	/* 核心 */
	top: calc(50% - 50px);
}

demo2

.md-warp{
	position: relative;
}
.md-main{
	position: absolute;
	top: 50%;
	// 注意此时md-main不设置height为100px
	-webkit-transform: translate(0,-50%);
	-ms-transform: translate(0,-50%);
	-o-transform: translate(0,-50%);
	transform: translate(0,-50%);
}

不定高

单行文本垂直居中

需要满足两个条件:

  • 元素内容是单行,并且其高度是固定不变的。
  • 将其line-height设置成和height的值一样
<div><span>这是一段文字</span></div>
div{
	width: 400px;
	height: 300px;
	border: 1px solid #000;
}
span{
	line-height: 300px;
}

这是一段文字

以上是一些常规办法,接下来是利用 CSS3 新特性实现的示例。

视窗单位的解决办法(垂直居中)

如果想避免使用绝对定位,我们仍然可以利用translate()方法,其值刚好是元宽度和高度的一半。但是,我们如何不使用 top 和 left 将元素从 top 和 left 移动 50%的偏移量呢?

首先想到的是给 margin 属性一个百分数,像这样:

.md-main{
	margin: 50% auto 0;
	transform: translateY(-50%);
}

效果如下所示:

我们发现并没有出现预想的结果,这是因为margin的百分比计算是相对于父容器的width来计算的,甚至包括margin-topmargin-bottom

我们如果仍然想让元素在视窗中居中,还是有救的。CSS3 定义了一种新的单位,称为相对视窗长度单位。

以下摘自 w3cplus vw是相对于视窗的宽度。与你预期刚好相反,1vw相当于视窗宽度的1%,而不是100%vw相似的是,1vh相当于视窗高度的1% 如果视窗的宽度小于高度,1vmin等于1vw,反之,如果视窗宽度大于高度,1vmin等于1vh 如果视窗的宽度大于高度,1vmax等于1vw,反之,如果视窗宽度小于高度,1vmax等于1vh

在上个示例的基础上,我们需要给margin设置vh单位:

.md-warp{
	position: relative;
}
.md-main{
	position: absolute;
	margin: 50vh auto 0;
	transform: translateY(-50%);
}

注意:这种方法最大的局限是只能适用于元素在视窗中垂直居中,如果是在局部的某个地方就无能为力了。

Flexbox 的解决方案

如果不考虑浏览器的兼容性,Flexbox 无疑是最好的解决方案,因为它的出现就是为了解决这样的问题。

完成这项工作只需要两个样式,在需要水平垂直居中的父元素上设置display:flex和在水平垂直居中的元素上设置margin:auto

.md-warp{
	display:flex;
}
.md-main{
	margin: auto;
}

Flexbox 的实现文本的水平垂直居中同样很简单。

.md-warp{
	display:flex;
}
.md-main{
	display: flex;
  align-items: center;
  justify-content: center;
	margin: auto;
}

我是字啊

补充:

inline-block 配合伪类的解决方案

.md-warp{
  font-size: 0;
}
.md-warp:before{
  content:'';
  display:inline-block;
  width: 0;
  height:100%;
  vertical-align:middle;
}
.md-main{
  display:inline-block;
  vertical-align:middle;
  font-size: 14px;
}

引自https://demo.doyoe.com/css/alignment/ 首先要了解垂直方向的对齐排版需使用 vertical-align ,并且只应用于 inline level, inline-block level 及 table-cells 元素上;其次 vertical-align 的对齐就基于每个 line box(行框) 的,简单的说,inline level 元素按照 Normal flow 水平排版出一行就会形成一个 line box,其高度由内容形成,如果换行,则又是另一个 line box,所有一段文本可能会分布在多个 line box 里,这些不重叠的 line box 被称作为 a vertical stack of line boxes(一个垂直堆叠的线框集合)这些。 换句话说,我们的垂直居中是要在每个 line box 中进行处理。而上例中我们想让一行文本在名叫 demo 的高 100px 的容器里垂直居中,这时有个问题就是 demo 容器并非该行文本的 line box,所以就算定义 vertical-laign 为 middle 也无法让该行文本在 demo 容器中垂直居中。我们知道 line box 的高度是由内容形成的,这时我们可以额外创建一个与该行文本处于同一 line box 的元素,同时将新增元素的高度定义为与 demo 容器相同,此时 line box 的高度将与 demo 一致,文本将会在 line box 内垂直居中,即同样实现了在 demo 容器中垂直居中。

绝对垂直居中

.md-warp{
  position: relative;
}
.md-main{
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
}

常用在弹出层的定位中。

结语

  • 绝对定位通常不是一个很好的选择,因为它对整体的布局影响相当的大。
  • 在一些浏览器中,可能会导致元素出现略微的模糊,那是因为元素有可能被放置在半个像素位置上。我们可以通过transform-style:preserve-3d来解决,但这是一个 Hack 手段,不能保证它不会过时。

以上各种方法稍加组合即可同时实现水平和垂直居中,这些就是平时用到较多的一些居中的方法,希望大家看完之后有收获:)