首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CSS上下左右居中

CSS上下左右居中

作者头像
ayqy贾杰
发布2019-06-12 12:33:24
3.2K0
发布2019-06-12 12:33:24
举报
文章被收录于专栏:黯羽轻扬黯羽轻扬

写在前面

有了transformflex后,水平竖直居中已经很容易了,比如万能的:

position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
/* 1.内容左上角居中 */
top: 50%; left: 50%;
/* 2.负半宽高把内容挪回来 */
-webkit-transform: translate(-50%, -50%);

关键是利用transform百分比相对自身宽高计算的特性,如果环境不支持transform的话,就需要用一些比较老,但很精妙的技巧了

margin居中

一个特征明显的方法:

position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
/* 1.要求自身内容相对包含块居中 */
margin: auto;
/* 2.给出自身宽高计算方式 */
width: 100px; height: 100px;

原理

关键是利用margin的计算规则:

'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = 包含块的宽度'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = 包含块的高度

(摘自10.3.7 绝对定位的不可替换元素、10.6.4 绝对定位的不可替换元素)

margin居中,就是要给上面的方程加上限制条件:

margin-top === margin-bottom && margin-left === margin-right

这是用margin实现居中的核心

CSS里2个步骤实际意义如下:

  1. 指定margin计算方式,其它必要值可计算的话,auto要求margin平分剩余空间
  2. 指定必要值计算方式

这里的“必要值”要分开看,水平方向是left, right, width,因为有如下规则:

如果’left’,’width’和’right’全都是’auto’…… 如果这3个值都不是’auto’…… 否则,把值为’auto’的’margin-left’和’margin-right’设置为0,再在下面6条规则中挑1条合适的应用 5.如果’width’是’auto’,’left’和’right’都不是’auto’,则求出’width’

也就是说,如果

left: 0;
right: 0;
width: auto;

那么

margin-left: auto;
margin-right: auto;

的实际效果是

left: 0;
right: 0;
margin-left: 0;
margin-right: 0;
width: auto;

margin auto失效(被抹掉变成0了),所以width是必要值,必须给出其计算方式,比如数值、百分比,或者限制条件,比如max-width

竖直方向是top, bottom, height,对应的规则与水平方向类似:

5.如果’height’是’auto’,’top’和’bottom’都不是’auto’,则把值为’auto’的’margin-top’和’margin-bottom’设置为0,再求出’height’

所以height也是必要值

这样看来,最显眼的t: 0, b: 0, l: 0, r: 0不是重点,与wdith, height一样,只是让margin auto可计算的必要值而已,所以应该这样排列:

position: absolute;
/* 1.要求自身内容相对包含块居中 */
margin: auto;
/* 2.给出margin auto计算所需的必要值 */
top: 0; bottom: 0; left: 0; right: 0;
width: 100px; height: 100px;

而且,tblr全0显然不必要:

top: 30px; bottom: 30px; left: 50px; right: 50px;

也是可以的,更进一步,甚至可以用tblr来抵消上下(左右)padding, border-width的差值

优缺点

缺点:

  • 无法应对内容不定高度的场景(height必须auto的场景)
  • WP下无效(假设可以忽略)

优点:

  • 兼容[IE8+]
  • 支持resize(用户拖动内容右下角时仍然居中)

inline居中

相当巧妙的方式:

.center-inline-container {
   /* 1.内容水平居中 */
   text-align: center;
}
.center-inline-container:before {
   /* 0宽空格 */
   content: '\200B';
   display: inline-block;
   /* 2.把内容高度撑起来 */
   height: 100%;
   vertical-align: middle;
}
.center-inline-content {
   display: inline-block;
   /* 3.竖直居中 */
   vertical-align: middle;
}

原理

关键是利用vertical-align: middle;实现竖直居中:

把该盒的竖直中点和父级盒的基线加上父级的半x-height对齐

也就是说:

内容的纵向中点位置 = 父级盒的基线位置 + 父级的半x-height高度

首先确定父级盒的基线位置:

‘inline-block’(盒)的基线是它的最后一个常规流中的行盒的基线,除非它没有流内行盒或者它的’overflow’属性的计算值不为’visible’,此时基线是bottom margin边

需要接着找“最后一个常规流中的行盒的基线”:

包含来自同一行的盒的矩形区域叫做行盒 CSS 2.1没有定义行盒基线的位置

遇到问题了,规范没说行盒的基线在哪个位置,但给了限制条件:

内联级盒是根据其’vertical-align’属性竖直对齐的。如果它们是’top’或者’bottom’对齐,它们必须对齐得让行盒高度最小化

满足这些非直接限制后,再确定行盒的基线位置,那么行盒基线位置的影响因素有:

  • 行盒里的内联级盒的vertical-alignheightline-height
  • 行盒所在容器的line-height
  • 其它(可能还有别的)

不同case下行盒基线位置可能不一样,但很容易把最终基线的位置标出来:

Just add a character at the beginning of the line in questions

一般添个小写字母x,紧贴着x底部的位置就是基线

接下来确定“父级的半x-height高度”,这个相对容易:

ex:相关字体的’x-height’ ‘ex’单位是根据元素的第一个可用字体定义的。一种异常情况是当’ex’出现在’font-size’属性的值中,此时参考父元素的’ex’ 之所以叫’x-height’,是因为通常等于小写”x”的高度。然而,不含”x”的字体中也定义了’ex’ 字体的x-height可以通过几种不同的方式得到。有些字体包含关于x-height的可靠规格。如果可靠的字体规格无法获得,UA可以根据一个小写字形的高度确定x-height。一个可能的启发是看小写”o”的字形延伸到基线下方多远,并减去其边界框的top值。如果有时确定x-height是不可能或者不现实的,就应该用0.5em

也就是说:

x-height = 当前字体的x-height || 根据一个小写字形的高度确定x-height || 0.5em

那么“半x-height高度”(0.5ex)大约是0.25em

再看CSS里的3个步骤:

  1. 水平居中不是问题
  2. 伪元素把行盒高度撑满容器,配合vertical-align: middle;把行盒基线位置拉到容器中心附近
  3. 内容中心点与行盒基线上方0.5ex位置对齐

看到这里很明确了,竖直方向根本没居中

  • 行盒基线不等于容器中心
  • 行盒基线上方0.5ex处也不等于容器中心

最终两个中心是对不上的,所以这种方式实现的居中有瑕疵,存在像素级的差异,如下图:

css-center-inline

可以尝试用margin-top来修补,但因为行盒基线没有确定的计算方法,做不到完美修复,从Demo来看,0.25ex似乎最合适,实际应用中可能需要微调(如果在意像素级瑕疵的话)

优缺点

缺点:

  • 存在像素级瑕疵无法解决,不是完美竖直居中
  • 存在HTML空白字符占空间的问题(压缩HTML,或者容器font-size: 0,内容重置font-size),影响水平居中
  • 需要额外元素/伪元素

优点:

  • 兼容[IE8+]
  • 支持不定高度内容

在线Demo

Demo地址:http://ayqy.net/temp/css-center.html

P.S.样式、结构及注意事项都在源码里

参考资料

  • Absolute Horizontal And Vertical Centering In CSS
  • Centering in the Unknown
  • Vertical-Align: All You Need To Know:结合CSS规范梳理line box, inline box, baseline等等,待翻译
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-07-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端向后 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • margin居中
    • 原理
      • 优缺点
      • inline居中
        • 原理
          • 优缺点
          • 在线Demo
            • 参考资料
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档