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

推荐订阅源

Vercel News
Vercel News
O
OpenAI News
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
GbyAI
GbyAI
T
The Blog of Author Tim Ferriss
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
云风的 BLOG
云风的 BLOG
罗磊的独立博客
S
SegmentFault 最新的问题
The Register - Security
The Register - Security
Hugging Face - Blog
Hugging Face - Blog
D
DataBreaches.Net
U
Unit 42
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog
阮一峰的网络日志
阮一峰的网络日志
P
Proofpoint News Feed
雷峰网
雷峰网
V
Visual Studio Blog
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
N
Netflix TechBlog - Medium
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Y
Y Combinator Blog
博客园 - 【当耐特】
G
Google Developers Blog
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
I
InfoQ
Martin Fowler
Martin Fowler
F
Fortinet All Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Cloudflare Blog
AI
AI
Google Online Security Blog
Google Online Security Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - Franky
Blog — PlanetScale
Blog — PlanetScale
Webroot Blog
Webroot Blog
PCI Perspectives
PCI Perspectives
爱范儿
爱范儿
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org

Ahmad Shadeed

Better fluid sizing with round() Use Cases for Field Sizing The Basics of Anchor Positioning Item Flow CSS Relative Colors Balancing Text In CSS Should masonry be part of CSS grid? CSS display contents CSS Grid Areas CSS Cap Unit An Interactive Guide to CSS Container Queries CSS :has() Interactive Guide CSS Nesting UX in DevTools CSS Nesting Future CSS: State Container Queries Rebuilding a comment component with modern CSS Conditional CSS with :has and :nth-last-child CSS Text balancing with text-wrap:balance CSS Masking Do we need CSS flex-wrap detection? My CSS Wishlist Conditional CSS CSS Style Queries Inside the mind of a frontend developer: Article layout Inside the mind of a frontend developer: Hero section CSS container queries are finally here The CSS behind Figma First Look At The CSS object-view-box Property Learn CSS Subgrid CSS :has Parent Selector Aligning Content In Different Wrappers Flexbox Dynamic Line Separator Hello, CSS Cascade Layers Building UI Components With SVG and CSS A Deep CSS Dive Into Radial And Conic Gradients Defensive CSS Building Real-life Components: Facebook Messenger Conditional Border Radius In CSS CSS Container Query Units Aligning a Button Label Vertically Comparing Design Mockups To Code Result Using HSL Colors In CSS Custom Scrollbars In CSS Let CSS Container Queries For Designers The State of CSS Cross-Browser Development Overflow Issues In CSS Inspect Element As A Way To Increase Your Curiosity Handling Text Over Images in CSS Digging Into CSS Logical Properties Clipping Scrollable Areas On The inline-start Side Understanding Clip Path in CSS The Art of Building Real-life Components Handling Short And Long Content In CSS CSS Scroll Snap A Deep Dive Into CSS Grid minmax() CSS Variables 101 Finding The Root Cause of a CSS Bug Learn CSS centering How to detect browser support for Flexbox Gap CSS Mistakes While On Autopilot Digging Into the Flex Property Understanding CSS Multiple Backgrounds Aligning Logo Images in CSS Grid for layout, Flexbox for components Colors in CSS Thinking About The In-between Design Cases min(), max(), and clamp() CSS Functions Image Techniques On The Web Everything About Auto in CSS Learn Box Alignment Let Learn CSS Positioning Intrinsic Sizing In CSS CSS Grid Template Areas In Action Hiding Elements On The Web Creating a Variable Color Font From Scratch Building a Football Ticket With CSS and SVG Blending Modes in CSS CSS Variables With Inline Styles Implementing Dark Mode For My Website Rebuilding Apple Music Header in HTML & CSS Accessible Checkbox Layout Flickering On Browser Resize Enhancing The Clickable Area Size Custom Underlines with SVG Part 3: The Process of Implementing A UI Design From Scratch Part 2: The Process of Implementing A UI Design From Scratch Building An Old Nav Design CSS Flexbox: 5 Real World Use Cases I Used CSS Inline Flex For The First Time The Process of Implementing A UI Design From Scratch Common CSS Issues For Front-End Projects Handling Long and Unexpected Content in CSS How to Build Web Form Layouts With CSS Grid Grid Layout Ah-ha Moment Enhancing Our Components with CSS :empty Building Resizeable Components with Relative CSS Units CSS Writing Mode The Journey of Learning Front End Web Development on a Daily Basis
CSS Findings From The Threads App
Ahmad Shadeed · 2023-07-13 · via Ahmad Shadeed

The Layout Maestro

I spent years teaching CSS layout on this blog. I put everything I know into The Layout Maestro course: 70+ lessons and 150+ interactive examples that teach you how to think CSS layouts, not just memorize syntax.

Get the course

When I encounter a new product, one of the first things that comes to mind is how they implemented the CSS. This was no different when I came across Threads by Meta. I quickly explored the mobile app and noticed that I could preview public posts on the web.

This presented an opportunity for me to dig deeper. I came across a few interesting findings, which I will discuss in this article.

Let’s dive in!

Using CSS grid for the post layout

One of the most noteworthy use cases of CSS Grid in a production app is found in Threads. CSS Grid is used to build the post layout.

Take a look:

: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;
}

Fun fact: the first grid column is named --barcelona. I’m curious to know the reason behind this choice.

The post layout consists of a 2-column * 4-row grid. There is no main container; each item within the post is manually placed using the grid-column and grid-row properties.

The user avatar

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

The avatar is positioned in the first column and spans the first two rows. It’s worth noting the presence of padding-top. Although I couldn’t find a specific reason for it in the production code, it seems to be fine-tuning the UI alignment.

Here is a before & after look for an avatar with and without the padding-top treatment:

The other reason for applying the padding-top here could be to push the avatar all the way down and make it closer to the line.

Using odd values for the grid rows

Why use 21px and 19px as row values? After inspecting further, it seems to be a form of fine-tuning for the UI. The sum of the row heights is 40px, which accounts for the avatar height plus the padding-top (36px + 4px).

You might be curious why these values are not standardized. Design systems are commonly associated with the belief that designers must strictly follow predefined rules for UI elements.

However, this example shows that using manually adjusted values can be acceptable. It’s okay to deviate from strict guidelines in certain situations.

Limitations of Using Fixed-Size Rows

Due to the fixed widths of the first two rows, it’s not possible to add padding to them. Nevertheless, as long as you’re aware of this limitation, it can be worked around by using margins instead.

Here is an example:

Adding top and bottom padding didn’t affect the post header due to the fixed-size rows.

The space between the layout columns feels a bit hacky

The current gap between the layout columns is zero. Instead, the image has a size of 36*36 pixels, whereas its container is 48 pixels in width.

This mimics the spacing here. I don’t know why the team opt-in for that, but I would prefer to use gap instead.

Why not use named CSS grid areas?

Based on what I’ve observed so far, there are three variations of the grid layout, and all of them could benefit from using named grid areas.

I tried to replicate the grid and build it based on the named areas. It looks easier to scan than specifying values for the columns and rows.

To demonstrate this, let’s assign a grid-area to each item in the layout:

.AvatarContainer {
  grid-area: avatar;
}

.HeaderContainer {
  grid-area: header;
}

.BodyContainer {
  grid-area: body;
}

.ThreadlineContainer {
  grid-area: line;
}

.FooterContainer {
  grid-area: footer;
}

Variation 1: the default

Then, we can start working on the variations. Here is the default layout:

.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";
}

Note the use of . to represent empty spaces.

Variation 2: the reply

A variation is when someone replies to another.

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

Variation 3: the default with a thread line

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

Using named grid areas here made it possible to change the layout by editing in one place only.

SVG for the thread lines

To be honest, what initially caught my attention in the Threads app was the swirl line. I became curious about how it was constructed since I had previously written about a similar topic a few weeks ago.

See the following figure:

That line connecting my avatar to Mark’s one is an SVG path. It consists of three parts.

The length of the first part is calculated with JavaScript.

Inline CSS variables for CSS grid

I’m happy to see a thing that I and many others advocated for is being used on a large-scale app like Threads.

In the user profile, the tabs grid layout is built with an inline CSS variable that includes the count of the tabs.

This is useful. When the number of tabs increased, we only need to change the value of the CSS variable. Neat, right?

Overflow wrapping

I noticed the use of overflow-wrap: anywhere for the post body. I haven’t used or heard of that keyword before. I use break-word.

As per MDN, it’s the same as break-word but with one additional thing:

Soft wrap opportunities introduced by the word break are considered when calculating min-content intrinsic sizes.

I still didn’t find a difference when using break-word vs anywhere. I’m very curious to know why, if any of the Threads team is reading this.

The use of dynamic viewport units

I like the use of the dynamic viewport unit dvh for the splash screen.

If you want to learn more, I wrote a detailed article on the new viewport units.

Defensive CSS strategies

To make sure that a flexbox layout won’t break because of the minimum content length, min-width: 0 is used to reset that behavior.

Read more about this in my defensive CSS post about the minimum content size in flexbox.

Conclusion

That’s it for today. I enjoyed inspecting the CSS and getting to know how the Threads team is building the product. I’m sure there are a lot of things that I haven’t noticed because this is the preview-only version on the web.