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

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
WordPress大学
WordPress大学
博客园 - 【当耐特】
Engineering at Meta
Engineering at Meta
IT之家
IT之家
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
美团技术团队
S
SegmentFault 最新的问题
The GitHub Blog
The GitHub Blog
Martin Fowler
Martin Fowler
Recorded Future
Recorded Future
H
Help Net Security
aimingoo的专栏
aimingoo的专栏
Y
Y Combinator Blog
博客园_首页
A
About on SuperTechFans
MongoDB | Blog
MongoDB | Blog
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
D
DataBreaches.Net
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
B
Blog
The Register - Security
The Register - Security
I
InfoQ
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
雷峰网
雷峰网
Last Week in AI
Last Week in AI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
Blog — PlanetScale
Blog — PlanetScale
N
Netflix TechBlog - Medium
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
有赞技术团队
有赞技术团队
Stack Overflow Blog
Stack Overflow Blog
Jina AI
Jina AI
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News - Newest:
Hacker News - Newest: "LLM"
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
W
WeLiveSecurity
Latest news
Latest news
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 叶小钗
L
Lohrmann on Cybersecurity
博客园 - Franky
Recent Commits to openclaw:main
Recent Commits to openclaw:main
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO

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 的前端性能优化实践 - Keenwon's Blog Fresh 快速入门 - Keenwon's Blog Islands Architecture - Keenwon's Blog Awesome Command-line Utilities - Keenwon's Blog
CSS 奇技淫巧 —— 绝对居中布局 - Keenwon's Blog
semanwmj@gma · 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:如果你有其他更好的方案,欢迎评论区留言讨论!