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

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

Keenwon's Blog

Mac 安装 Ollama 和 Open WebUI 快速排序第 N 趟的可能结果 - Keenwon's Blog PVE 动态分配虚拟机的内存 - Keenwon's Blog ubuntu crontab 定时执行 node 程序 Node.js SEA - Keenwon's Blog 基于 Web Vitals 的前端性能优化实践 Fresh 快速入门 - Keenwon's Blog Islands Architecture - Keenwon's Blog Awesome Command-line Utilities
CSS 奇技淫巧 —— 绝对居中布局 - Keenwon's Blog
semanwmj@gmail.com (keenwon) · 2023-07-10 · via Keenwon's Blog

本文来聊一个 flex 布局的小技巧 —— 绝对居中布局。这名字是我瞎起的,可能不是特别恰当,不过我讲完背景,大家就应该都清楚了。

背景#

APP 顶部由上到下,一般是「状态栏」和「导航栏」。状态栏通常就是系统默认的样式,最多根据底色的深浅,把文字和图标切换为反色,保证用户可以清晰地看到时间等信息。但是导航栏,经常需要适配页面的视觉风格,特别是在一些「全屏 H5」中。比如下面这张图片:

前端在实现这个组件的时候,考虑到要兼容各种场景,通常会分为三个部分:

  • 左边:返回按钮,可能要适配 Android 和 iOS 的不同风格,看 APP 的精细程度
  • 中间:内容区。可以是文字,也可以是组件,比如上图的 <Tab />
  • 右边:自定义区域。常见的内容有「确认」,「搜索」,「帮助」等等...

那么问题来了,当左边和右边都是正常按钮时,两边宽度是一致的,中间文字默认居中即可。

但是,当右边的自定义内容,宽度与左边不同,或者干脆没有右边自定义区域。这种情况下,中间文字就不居中了:

那么,如何让中间的文字部分,相对于整个导航栏绝对居中呢?

绝对居中布局#

可能很多人首先想到的是,让左右两部分绝对定位在两侧。但是这样布局的问题是,中间区域是无法「感知」到左右两部分的宽度,很容易出现内容覆盖的情况:

所以,绝对定位的方案,样式上不够「安全」。而使用 JS 的话,由于设备和字体的差异,需要在运行时计算宽度,非常不利于 SSR 和 SSG 直接输出顶部内容。最好方案还是能继续使用 flex 三列布局,中间部分自动撑满余下全部区域,不产生重叠。

但是,使用 flex 布局要解决一个问题,由于左右两部分,存在不等宽的可能。那么在不等宽的情况下,如何保证中间区域仍然居中呢?

从问题到结论的过程中,经过了大量尝试和思考,这部分比较难用文字记录下来。此处直接说结论,中间区域居中的核心,是要保证左右两部分始终等宽。而让左右两部分始终等宽的方式,就是左右两边同时渲染左右两个组件,通过 overflow: hidden 裁掉多余的部分。看个示意图就一目了然了:

因为导航栏的高度,在一台设备上通常是固定的。所以左右两个组件,左边按照「左上右下」,右边按照「右上左下」的布局排列好,外部容器裁掉高出的部分,即可保证左右等宽。

HTML 代码:

<div class="container">
  <div class="left-wrapper">
    <div class="back">后退</div>
    <div class="report">反馈问题</div>
  </div>
  <div class="center">这里是绝对居中的标题</div>
  <div class="right-wrapper">
    <div class="report">反馈问题</div>
    <div class="back">后退</div>
  </div>
</div>

CSS 代码:

.container {
  width: 100%;
  height: 60px;
  line-height: 60px;
  display: flex;
  background-color: #ddd;
  border: 2px solid #000;
}

.left-wrapper,
.right-wrapper {
  width: auto;
  height: 60px;
  background-color: #d6e8d5;
  flex-direction: column;
}

.back {
  width: 60px;
  height: 60px;
  text-align: center;
  background-color: #ccc;
}

.report {
  width: 100px;
  height: 60px;
  text-align: center;
  background-color: #999999;
}

.center {
  flex: 1;
  text-align: center;
  background-color: #fff2cc;
}

这个方案比较 hack,最初这么做的原因是不想使用 JS 计算,纯 CSS 的方案性能更好,也比较适配我们的 SSR、SSG 架构。但毕竟会重复渲染两次,所以如果有一些特别复杂的组件,最好能在外层包一个定宽的容器,动态讲复杂组件渲染到容器内。

除了重复渲染的问题,此方案还存在一些其他的短板,比如加了 overflow: hidden 后,右边如果有下拉菜单的话,可能要特殊处理下。但总的来说,还是比较稳的,在线上使用很久了,没发现什么明显的问题。

PS:如果你有其他更好的方案,欢迎评论区留言讨论!