写点什么

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:534410

评论

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

在北京选择前端培训班学习大数据

小谷哥

尤雨溪向初学者推荐Vite 【为什么使用Vite】

flow

签约计划第三季

面试京东T5,被按在地上摩擦,鬼知道我经历了什么?

程序员啊叶

Java 编程 程序员 架构 java面试

Flink 在 讯飞 AI 营销业务的实时数据分析实践

Apache Flink

大数据 flink 编程 流计算 实时计算

iOS单元测试的那些事儿

珲少

技术分享:国民远控向日葵如何通过BBR算法提升远控体验?

贝锐

技术分享 远程控制 TCP拥塞控制 向日葵 BBR

参加前端培训班学web前端技术靠谱吗

小谷哥

目标检测网络R-CNN 系列

阿炜小菜鸡

深度学习 目标检测 7月月更

TDSQL-C Serverless:助力初创企业实现降本增效

石云升

全球架构师峰会 ArchSummit

向日葵资深产品总监技术分享:如何在AD域环境下应用

贝锐

安全 AD域 远程控制 向日葵

什么是RPC?RPC框架dubbo的核心流程

程序员啊叶

Java 编程 程序员 架构 java面试

深度学习3D人体姿态估计国内外研究现状及痛点

阿炜小菜鸡

深度学习 人体姿态估计

银行业客户体验管理现状与优化策略分析

易观分析

银行

「中高级试题」:MVCC实现原理是什么?

程序员啊叶

Java 编程 程序员 架构 java面试

web前端开发培训课程如何学习

小谷哥

浅谈低代码技术在物流运输平台中的搭建与管理

王平

公司刚来的阿里p8,看完我构建的springboot框架,甩给我一份文档

程序员啊叶

Java 编程 程序员 架构 java面试

海外APP推送(下篇):海外厂商通道集成指南

极光JIGUANG

sdk 厂商通道

行业案例|指标中台如何助力银行业普惠金融可持续发展

Kyligence

大数据 普惠金融 指标中台

百问百答第48期:极客有约——可观测体系的建设路径

博睿数据

可观测性 智能运维 博睿数据 性能监测 极客有约

干货|语义网、Web3.0、Web3、元宇宙这些概念还傻傻分不清楚?(中)

Orillusion

开源 WebGL 元宇宙 Metaverse webgpu

数据泄漏、删除事件频发,企业应如何构建安全防线?

京东科技开发者

公司管理 网络安全 安全 删库 程序员‘

一百五十个终极Java 经典面试题(你会多少题?)

程序员啊叶

Java 编程 程序员 架构 java面试

Python图像处理丨两种实现图像形态学转化运算

华为云开发者联盟

Python 人工智能 图像处理 图像

开放原子开源基金会OpenHarmony工作委员会主席侯培新寄语OpenAtom OpenHarmony分论坛

OpenHarmony开发者

OpenHarmony

向日葵远程控制为何采用BGP服务器?自动最优路线、跨运营商高速传输

贝锐

远程控制 向日葵

Redis为什么这么快?Redis的线程模型与Redis多线程

程序员啊叶

Java 编程 程序员 架构 Java 面试

敲黑板画重点:七种常见“分布式事务”详解

程序员啊叶

Java 编程 程序员 架构 java面试

大数据培训机构有哪些值得推荐?

小谷哥

程序员培训学习后好找工作吗?

小谷哥

Python爬虫,JS逆向之 webpack 打包站点原理与实战

梦想橡皮擦

Python 爬虫 7月月更

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