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

推荐订阅源

V
Visual Studio Blog
The Last Watchdog
The Last Watchdog
Cisco Talos Blog
Cisco Talos Blog
A
Arctic Wolf
WordPress大学
WordPress大学
The Hacker News
The Hacker News
C
Cybersecurity and Infrastructure Security Agency CISA
H
Help Net Security
GbyAI
GbyAI
V
V2EX
Security Latest
Security Latest
Cyberwarzone
Cyberwarzone
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
P
Privacy International News Feed
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tor Project blog
P
Privacy & Cybersecurity Law Blog
C
Cisco Blogs
月光博客
月光博客
B
Blog
T
Threat Research - Cisco Blogs
I
Intezer
Recent Announcements
Recent Announcements
Latest news
Latest news
S
Schneier on Security
美团技术团队
量子位
H
Hacker News: Front Page
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Webroot Blog
Webroot Blog
N
News | PayPal Newsroom
Martin Fowler
Martin Fowler
博客园 - 三生石上(FineUI控件)
雷峰网
雷峰网
爱范儿
爱范儿
T
Tailwind CSS Blog
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 聂微东
Cloudbric
Cloudbric
MyScale Blog
MyScale Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Microsoft Security Blog
Microsoft Security Blog
人人都是产品经理
人人都是产品经理
S
Securelist
Hacker News: Ask HN
Hacker News: Ask HN
Y
Y Combinator Blog
Attack and Defense Labs
Attack and Defense Labs
TaoSecurity Blog
TaoSecurity Blog

Starred Articles

Improvements to Web for AI Should Benefit All Users New to the web platform in April  |  Blog  |  web.dev Delivering a dynamic hexagonal world map in just 10kb | Calibre My house alerts me when my cat climbs into the ceiling Eames Pavilion System Squarespace & Web Standards: How We Helped Bring HTML Video & Audio Lazy Loading to Today’s Browsers | Scott Jehl, Web Designer/Developer The Web is a Guitar Amp Now (Literally) Making keyboard navigation effortless I used Claude Code and GSD to build the accessibility tool I’ve always wanted - blakewatson.com Sizing chaos Scroll indicators on tables with background colours using animation-timeline Webspace Invaders Fresh Hot CSS: Trig Functions The Year Of The Linux Desktop (for fitness games) Almost Plain Text, Nicely Done – Email is good. Uncrate's 100-ish favorite things on Amazon VS Code – highlight just the active indent guide How musicals use motifs to tell stories Good Tidings! Review: MoErgo Go60, a split ergonomic and fully programmable keyboard The line and the stream. — Ethan Marcotte Testing HTML Light DOM Web Components: Easier Than Expected! Steam Machine Caira AI Mirrorless Camera A Treatise on AI Chatbots Undermining the Enlightenment Talking CSS, Web Components, App Design and (gulp) AI on ShopTalk Show Microsoft™ Ergonomic Keyboard (now sold by Incase) A new, new logo for the W3C Chris Coyier Solved by CSS Scroll State Queries: hide a header when scrolling down, show it again when scrolling up. closedBy=any · October 16, 2025 Paxos accidentally mints more than twice the global GDP in PayPal stablecoins The CSS Podcast is back! And I’m a co-host now. Who needs a flying car when you have display: grid Junior Dev Tip: "Scroll Up" WWW Ep212 With Dave Rupert · October 2, 2025 DHH Is Way Worse Than I Thought | jakelazaroff.com A custom --light-dark() function in CSS that works with any type of value (not just colors!) in just 3 LOC Make accessible carousels  |  Blog  |  Chrome for Developers 37 pm · Paul Robert Lloyd Against the protection of stocking frames. — Ethan Marcotte “Why would anybody start a website?” Necropolis Should Men Be the Head of Every Household? The History of Themeable User Interfaces Speeding up my Learning Log process Eight years of Jessie How our dog increased my appreciation for accessibility In the Future All Food Will Be Cooked in a Microwave, and if You Can’t Deal With That Then You Need to Get Out of the Kitchen Somewhere Between Lost and Found Impact of AI on Tech Content Creators Progressive Enhancement and Web Components Sizzle Rizzle · July 4, 2025 The Cascade
Enhancing Web Components Safely with Self-Destructing CSS | Scott Jehl, Web Designer/Developer
2025-11-17 · via Starred Articles

By Scott Jehl

A month ago, I wrote about a defensive CSS convention I've been calling Self-Destructing CSS. As CSS patterns go these days this one is delightfully low-tech, but in my work I've seen it have an outsized impact in ensuring usable experiences for increasingly-heavy websites when network or device conditions aren't ideal.

This notion of delivering "optimistically" while planning for failure is something I've written about before, but the set-it-and-forget-it nature of this latest stab at it makes it my favorite yet. And funny enough, while it's just another take on careful Progressive Enhancement, this one actually feels more like "graceful degradation" to me! Hmm. I won't dwell on that one.

Anyway, last week, Brian Kardell pointed out to me over on Bluesky that the problem Self-Destructing CSS addresses reminded him of one that commonly occurs with Web Components, when developers hide custom elements until they are "defined" by their JavaScript. That's an anti-pattern I covered in my Web Components course, and it's common because it aims to work around a very real issue: often, we don't want our users to see a component until it's "ready."

That (anti)-pattern looks like this:

:not(:defined) {
  visibility: hidden;
}

Let's break that down. CSS gives us the pseudo-state :defined which will match any custom element once it is defined by JavaScript. For example, if you have an element <my-element> in your HTML, it starts out essentially a div with a more descriptive name. That "~div" could be useful on its own, but typically developers will define its custom behavior using the customElements APIs now built into browsers (effectively turning it into a "web component," if you please). That element definition looks like this:

customElements.define('my-element', class extends HTMLElement {
  /*...lifecycle additions can go here */
});

Once defined, my-element will be selectable in CSS via :defined, along with all of the other "defined" HTML elements. To be clear, that includes every built-in element defined by the browser, so that :defined selector alone isn't terribly useful on its own, and might do better paired with an element selector instead. That said, if we're trying to style all undefined custom elements to hide them before they're defined, then a selector that matches the opposite of :defined is pretty handy. That's how folks arrived at hiding content with :not(:defined) { visibility: hidden; }.

Unfortunately, while this pattern is clever, it's also risky: if JS fails to run or load in any reasonable amount of time, those elements will remain hidden. I've seen this pattern cause content to be invisible for long periods while popular budget-tier devices struggle to churn through massive JavaScript bundles, even if they're on a fast network.

After a brief delay, hiding content entirely just isn't worth whatever effect you're hoping to achieve.

Improving :not(:defined) with Self-Destructing CSS

As I commented in this HTML standard issue about it, this situation is a great use case for self-destructing CSS.

So moving forward, if you need to hide un-enhanced Custom Elements, I suggest you do not do this:

:not(:defined) {
  visibility: hidden;
}

And instead, do this!

@keyframes hideBriefly {
  0%, 100% { visibility: hidden; } 
}
:not(:defined) { animation: hideBriefly 2s; }

Here, just as before, as soon as your element gets defined, the hiding will instantly and automatically unapply. But it will also unapply itself after two seconds no matter what, should the JavaScript take that long to do its thing, or fail to run at all. That last part is critical, because in our medium, we can't expect things to just work like they do on our machine. In fact, they usually don't.

Anyway, that's Self-Destructing CSS for web components. Go play some defense out there on behalf of your users! Oh, and if you want to take this the extra mile, make sure that your initially-delivered HTML is useful/meaningful/functional before the JavaScript loads. Otherwise, you might as well just hide it without a fallback, I guess!