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

推荐订阅源

cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
雷峰网
雷峰网
Recent Announcements
Recent Announcements
月光博客
月光博客
G
Google Developers Blog
腾讯CDC
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
T
Tenable Blog
云风的 BLOG
云风的 BLOG
W
WeLiveSecurity
博客园 - 【当耐特】
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
博客园 - 聂微东
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
人人都是产品经理
人人都是产品经理
P
Privacy International News Feed
MyScale Blog
MyScale Blog
K
Kaspersky official blog
T
The Blog of Author Tim Ferriss
Attack and Defense Labs
Attack and Defense Labs
Spread Privacy
Spread Privacy
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
aimingoo的专栏
aimingoo的专栏
I
Intezer
Vercel News
Vercel News
小众软件
小众软件
Simon Willison's Weblog
Simon Willison's Weblog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
N
Netflix TechBlog - Medium
P
Proofpoint News Feed
Latest news
Latest news
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tor Project blog
S
Security Affairs
P
Proofpoint News Feed
博客园 - 三生石上(FineUI控件)
博客园 - Franky
C
Cyber Attacks, Cyber Crime and Cyber Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
美团技术团队
Recent Commits to openclaw:main
Recent Commits to openclaw:main
S
Security @ Cisco Blogs
L
LINUX DO - 热门话题
Know Your Adversary
Know Your Adversary
Project Zero
Project Zero
D
Docker
L
Lohrmann on Cybersecurity
F
Full Disclosure

Bram.us

What’s new in Web UI (Google I/O 2026) Cranking View Transtions up to 11 (2026.05.07 @ All Day Hey!) Cranking View Transtions up to 11 (2026.04.28 @ Beyond Tellerrand) Do Websites Need to Function Exactly the Same on Every Platform? View Transitions: Use the new attr() or match-element for the view-transition-name? Introducing view-transitions-toolkit, a collection of utility functions to more easily work with View Transitions. Cranking View Transtions up to 11 (2026.03.25 @ devs.gent) More Easy Light-Dark Mode Switching: light-dark() is about to support images! Detect at-rule support in CSS with @supports at-rule(@keyword)
CSS position: sticky now sticks to the nearest scroller on a per axis basis!
Published by Bramus! · 2026-03-30 · via Bram.us

Recording of the demo.

~

If you’ve ever tried to build a data table with a sticky header and a sticky first column, you know the pain. You’d think a simple position: sticky with top: 0 and left: 0 would be enough, but the reality was that only one of both would stick.

A recent change to CSS fixes this: position: sticky now plays nice with single-axis scrollers, allowing you to have sticky elements that track different scroll containers on different axes. This change is available in for testing in Chrome 148 with the experimental web platform features flag flipped.

~

# The Situation

To understand the impact, let’s quickly review the standard setup for a responsive table. You start with a wide HTML <table> full of data. To prevent this wide table from breaking your page layout on small screen devices, you typically wrap it in a container with overflow-x: auto.

<div class="table-wrapper" style="overflow-x: auto;">
  <table>
    …
  </table>
</div>

Because you want the column headers (the <thead>) to stay visible when scrolling down the document, you apply position: sticky; top: 0; to them. Simultaneously, you want your first column to stay visible when scrolling sideways through the data, so you apply position: sticky; left: 0; there.

.table-wrapper {
  overflow-x: auto;
}

.table-wrapper thead {
  position: sticky;
  top: 0;
}

.table-wrapper td:first-child {
  position: sticky;
  left: 0;
}

However, this doesn’t work as expected. While the first column will stick to the left edge of the table wrapper when scrolling horizontally, the headers will scroll out of view along with the rest of the page.

This is because the .table-wrapper becomes the sticky reference for both axes. Because the wrapper only scrolls horizontally, the vertical sticking becomes completely ineffective. Your top: 0 headers would just happily scroll out of view along with the rest of the page 😭

To get around this, you had to rely on lots of JavaScript to synchronize the scroll position, or rely on duplicated headers.

Note: While there are pure CSS solutions to make sure the headers also stick within the .table-wrapper, the problem described here is different: instead of getting the headers to stick inside the same scroller, you want the headers to be stuck against a different scroller (here: the .table-wrapper for horizontally sticky stuff, and the document’s scroller for vertically sticky stuff).

~

# The Change

Thanks to a recent change in the overflow specification that allows containers to be a scroller for only a single axis, position: sticky can now track two different scrollers — one per axis — for the stickiness.

This means that for our wide data table:

  • The first column can be sticky on the horizontal axis against the table wrapper.
  • The headers can be sticky on the vertical axis against a completely different scroller — such as the document itself!

No more duplicating headers. No more scroll-syncing JavaScript. Just plain CSS doing exactly what you’d expect it to do.

This change is available for testing in Chrome 148 with the Experimental Web Platform Features flag enabled.

The request for this change was filed back in 2017, in CSS WG Issue #865. It’s not that often you see three-digit issues get resolved and implemented 😅

~

# See it in action

You can see this new behavior in action in this CodePen demo:

See the Pen
CSS `position: sticky` for Single Axis Scroll Containers
by Bramus (@bramus)
on CodePen.

If you view the demo in a supported browser, the first column will stick to the left edge of the table wrapper when scrolling horizontally, and the top headers will stick to the top of the viewport when scrolling vertically.

~

# An Important Detail: Watch your overflow

If you look closely at the CSS in the demo, you might notice a very specific detail in how the .table-wrapper is styled.

.table-wrapper {
  overflow: auto clip;
}

To make the wrapper scroll horizontally, you might instinctively reach for overflow-x: scroll (or auto). However, doing so will actually break the vertical stickiness we just achieved!

Why? Because in CSS, if you set overflow-x to scroll or auto, the browser automatically computes overflow-y to auto as well (assuming its value was visible). This turns the wrapper into a scroll container on the vertical axis too, which means it once again traps our headers and becomes their sticky reference.

To fix this, we need to explicitly tell the browser not to create a scroll container on the block axis. We do this by using the clip keyword:

.table-wrapper {
  /* ❌ This makes overflow-y compute to auto, breaking vertical stickiness */
  /* overflow-x: auto; */

  /* ✅ This creates a scroller on the inline axis, but clips the block axis */
  overflow: auto clip; 
}

By setting overflow-y to clip (via the overflow shorthand), the wrapper does not become a scrollport on the vertical axis. The headers are therefore free to track the document viewport instead.

~

# Browser Support

💡 Although this post was originally published in March 2026, the section below is constantly being updated. Last update: March 30, 2026.

At the time of writing, this feature is only supported in Chrome 148 as an experimental feature.

Chromium (Blink)

👨‍🔬 Available in Chromium 148.0.7742.0 with the experimental web platform features flag flipped on.

Firefox (Gecko)

❌ No support

Subscribe to Bug #2023702 for updates.

Safari (WebKit)

❌ No support

~

# Feature Detection

Because older browsers still use the inner container as the sticky reference for both axes, you might want to feature-detect this new behavior to provide JS-based fallbacks or conditionally load specific styles.

While we can’t easily detect this layout behavior directly with an @supports query in CSS yet — I have an open issue at the CSSWG for this — you can feature detect this using JavaScript. The CodePen demo linked above includes a script that does exactly this.

It handles the detection by evaluating how the browser resolves the sticky positioning offsets within a scrolling wrapper. Feel free to peek at the JS tab in the Pen to grab the snippet for your own projects.

UPDATE 2026.05.27 The resolution at the CSSWG is in and Chrome Engineering is already busy implementing it in Chromium with the CL getting merged as I type this.

Thanks to this addition, detection is now possible in CSS using the following snippet:

@supports named-feature(single-axis-scroll-container) {
  /* Single Axis Scroll Containers are supported */
}

This detection mechanism is available starting with Chrome 150, paving the way to shipping Single-Axis Scroll Containers to Chrome Stable later this year.

~

# Spread the word

Feel free to reshare one of the following posts on social media to help spread the word:

~