写点什么

Threads 横空出世,通过解析 App,我发现了这些 CSS 小秘密

作者 | Ahmad, Digital

  • 2023-08-11
    北京
  • 本文字数:2563 字

    阅读完需:约 8 分钟

Threads 横空出世,通过解析App,我发现了这些CSS小秘密

每当遇上一款新产品,我首先想到的就是研究研究他们是怎么实现 CSS 的。Meta 新近推出的 Threads 当然也不例外,我快速体验了这款移动应用,发现它的主要功能就是展示网络上的公共发帖。

 

浏览过程中我也有了其他深入发现,本文将具体为大家一一介绍。

 

闲言少叙,咱们马上开始!

 

在帖子布局中使用 CSS 网格

 

Threads 当中的 CSS 网格,可以算是我在生产级应用中见到的最值得一聊的案例。Meta 在这里选择用 CSS 网格构建帖子布局。

 


咱们简单看看:

 

:root {  --barcelona-threadline-column-width: 48px;}.post {  display: grid;  grid-template-columns:    var(--barcelona-threadline-column-width)    minmax(0, 1fr);  grid-template-rows: 21px 19px max-content max-content;}
复制代码

 

有趣发现:第一个网格列被命名为--barcelona。我很好奇他们为什么要选这个名字。

帖子布局由 2 列 x 4 行网格组成。这里没有主容器,帖中的每个条目封镜 使用 grid-column 和 grid-row 属性进行手动放置。

 

再来看用户头像:

 

.post-avatar {  padding-top: 4px;  grid-row: 1 / span 2;  grid-column: 1;}
复制代码

 

头像位于第一列并跨越前两行。这里的 padding-top 尤其值得注意。虽然我在生产代码中没找到确切用途,但猜测它可能是在微调 UI 对齐。

 

下图所示,是经过/未经 padding-top 处理的头像部分前后对比:



在这里采用 padding-top 的另一个理由,可能是要把头像下推以对齐第二行的下沿。



在网格行数中使用奇数值

 

为什么行值选择的是 21px 和 19px?经过进一步检查,这似乎也是对 UI 的微调措施。行高之和为 40px,即头像高度再加上 padding-top(36 像素+4 像素)。



大家可能会好奇,为什么不对这些值做标准化设置?毕竟在系统设计中存在这样一条“铁律”:设计师必须始终遵循 UI 元素的预定义规则。

 

但从 Threads 来看,手动调整具体值也是可接受的。在某些情况下,甚至不妨先把严格的指导方针放下。

 

使用固定的行大小限制

 

由于行大小是固定的,因此无法为其添加填充。但只要意识到存在这个限制,我们也可以借用边距来绕过这一约束。

 

请看以下示例: 



由于行大小是固定的,所以添加顶部和底部填充不会影响到帖子标题。

 

各布局列之间的列距显得有点凌乱

 

布局列之间的当前列距为零。相反,图像大小为 36 x 36 像素,而其容器宽度则为 48 像素。



这就用模拟的方式呈现出了列距的效果。我不知道开发团队为什么不直接设置列距,我个人是比较倾向这种作法。

 

为什么不用命名 CSS 网格区域?

 

根据我迄今为止观察到的情况,网格布局当中存在三种变体,而且使用命名网格区域后这三种变体都能获得效果提升。


我试着复制了这套网格并根据命名区域进行了构建,新的结果比直接为列和行指定值更加顺畅易读。

为了演示差别,我们先为布局中的各个条目分配一个 grid-area:

 

.AvatarContainer {  grid-area: avatar;}.HeaderContainer {  grid-area: header;}.BodyContainer {  grid-area: body;}.ThreadlineContainer {  grid-area: line;}.FooterContainer {  grid-area: footer;}
复制代码

 

变体 1:使用默认值

 

之后,我们再来研究变体。以下为默认布局的效果:



.post {  display: grid;  grid-template-columns:    var(--barcelona-threadline-column-width)    minmax(0, 1fr);  grid-template-rows: 21px 19px max-content max-content;  grid-template-areas:    "avatar header"    "avatar body"    ". body"    ". footer";}
复制代码

 

请注意,这里使用 . 来表示空白区域。

 

变体 2:回复

 

这个变体代表某人回复另一用户时的情况。



.post--reply {  grid-template-rows: 36px 0 max-content max-content;  grid-template-areas:    "avatar header"    "body body"    "body body"    "footer footer";}
复制代码

 

变体 3:默认值加 Thread Line



.post--withLine {  grid-template-areas:    "avatar header"    "avatar body"    "line body"    "footer footer";}
复制代码

 

在这里使用命名网格区域,即可通过编辑一处来变更整个布局。

 

Thread Lines 中的 SVG

 

老实说,Threads 应用中最先引起我注意的就是这条螺旋线。从几周前第一次看到以来,我一直想搞清楚它是怎么实现的。

 

先来看以下截屏:



Threads Line 这条螺旋线把我的头像和 Zuck 的头像连接了起来,而这其实是条 SVG 路径,具体由三部分组成。



第一部分的长度用 JavaScript 代码计算得出。

 

CSS 网格的内联 CSS 变量

 

这是个令人振奋的发现:我和其他很多从业者所提倡的设计,终于开始在 Threads 这类大型应用中得到体现。

 

在用户个人资料部分,选项卡的网格布局是由包含选项卡计数的内联 CSS 变量构建而成。



这种设计非常精妙。随着选项卡数量的增加,我们只需要调整 CSS 变量的值即可。多么简洁、多么方便!

 

Overflow Wrapping

 

我注意到,Threads 在帖子本体中用到了 overflow-wrap: anywhere。有一说一,我之前从来没用过、甚至没听说过这个关键字,我一直用的都是 break-word。

 

根据 MDN 的介绍,它跟 break-word 的作用相同,只有一点区别:在计算最小内容的实际大小时,它会考虑由单词截断造成的软换行情况。

 

我还是没发现 break-word 跟 anywhere 到底有什么区别。如果有 Threads 团队的同学正好看到这篇文章,还望不吝赐教。

 

使用动态视口单元

 

我很喜欢用动态视口单元 dvh 作为启动画面。



感兴趣的朋友也可以参考我之前写的关于新视口单元的文章:

 

https://ishadeed.com/article/new-viewport-units/

 

几项防御式 CSS 策略

 

为了确保 Flexbox 的布局不会因最小内容长度而中断,可以使用 min-width: 0 来重置该行为。



我在讨论 Flexbox 中最小内容大小的防御式 CSS 文章中,具体介绍了相关问题。

 

https://defensivecss.dev/tip/flexbox-min-content-size/

 

总结

 

文章就是这些。我很喜欢研究 CSS,以此为切入点思考 Threads 团队是如何设计和构建这款产品的。相信还有很多细节逃过了我的双眼,毕竟目前能接触到的只是 Web 上的预览版本。随着后续研究的深入,我也期待给大家带来更多有趣的发现。

 

原文链接:


https://ishadeed.com/article/threads-app-css/

 

相关阅读:


5 天内用户数破亿、增速碾压 ChatGPT,Twitter 劲敌 Threads 是如何构建的?

nodejs 中使用 worker_threads 来创建新的线程

48 小时注册用户达 7000 万,马斯克:Threads 是 Twitter 前员工做出来的!

我眼中的 CSS 革命:新特性潜力无限

2023-08-11 16:534396

评论

发布
暂无评论
发现更多内容

前端代码重复度检测

南城FE

JavaScript 前端 代码

披荆斩棘的芒果 TV:基于 StarRocks 的云原生湖仓架构升级

StarRocks

简单聊聊低代码

互联网工科生

低代码 数字化

基于Vue构建的快速开发框架

树上有只程序猿

Vue 低代码

云桌面如何部署?云桌面系统方案部署详细教程

青椒云云电脑

云桌面 云桌面系统

ETL数据转换方式有哪些?

RestCloud

数据同步 ETL

数字货币双仓合约交易所系统开发搭建

V\TG【ch3nguang】

WorkPlus安全专属的企业IM助力政企高效协作

BeeWorks

SQL和Python,哪个更容易自学?哪个更适合数据工作的编程新手?

高端章鱼哥

Python sql

深入浅出了解华为云API网关的Gzip功能

华为云PaaS服务小智

云计算 软件开发 API 华为云

回归营销初心,2023金投赏鲸鸿动能专场聚焦品牌重塑

最新动态

邀你见证一本思维小册子的诞生:《豆哥宝典:思维模型》

豆哥

AI 思维模型 GPT 宝典

算启新程 智享未来,英特尔携中国移动为行业数字化转型提供新动能

E科讯

​左手 Serverless,右手 AI,7 年躬身的古籍修复之路

阿里巴巴云原生

阿里云 Serverless 云原生

2023年10款好用的AI生成PPT软件盘点,干货建议收藏!

彭宏豪95

效率 软件 职场 PPT AIGC

低代码平台技术分享官丨工作流应用场景之任务交接

inBuilder低代码平台

工作流 低代码

语音识别技术:现状、挑战与未来发展

来自四九城儿

体育赛事直播平台源码解决方案,开发搭建系统架构的重要组成部分

软件开发-梦幻运营部

持续测试新范式:拨压测一体化

阿里巴巴云原生

阿里云 云原生 压测 拨测

Python 实训教学,更便捷的学生邀请及内容分发|ModelWhale 版本更新

ModelWhale

人工智能 数据分析 在线编程 高等教育 云课堂

SRM供应商招采系统(源码)

金陵老街

基于 ACK Fluid 的混合云优化数据访问(四):将第三方存储目录挂载到 Kubernetes,提升效率和标准化

阿里巴巴云原生

阿里云 Kubernetes 容器 云原生 ACK

“鲸鸿动能·品牌共创计划”发布,多项权益助力品牌激发无限潜能

最新动态

什么是多云? 为什么我们需要多云可观测性 (Observability)?

NineData

多云服务 多云架构 多云管理 多云 多云多源

Native SQLite Manager for mac(SQLite数据库管理器) 1.26.1全新激活版

mac

苹果mac Windows软件 Native SQLite Manager SQLite 数据库的工具

Threads 横空出世,通过解析App,我发现了这些CSS小秘密_大前端_InfoQ精选文章