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

推荐订阅源

博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
月光博客
月光博客
AI
AI
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
CXSECURITY Database RSS Feed - CXSecurity.com
WordPress大学
WordPress大学
GbyAI
GbyAI
L
Lohrmann on Cybersecurity
O
OpenAI News
Schneier on Security
Schneier on Security
P
Palo Alto Networks Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Troy Hunt's Blog
V2EX - 技术
V2EX - 技术
W
WeLiveSecurity
L
LINUX DO - 最新话题
人人都是产品经理
人人都是产品经理
S
Security Affairs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
Arctic Wolf
Recorded Future
Recorded Future
Microsoft Security Blog
Microsoft Security Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
G
GRAHAM CLULEY
N
Netflix TechBlog - Medium
TaoSecurity Blog
TaoSecurity Blog
C
Check Point Blog
Scott Helme
Scott Helme
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
PCI Perspectives
PCI Perspectives
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Vercel News
Vercel News
The Hacker News
The Hacker News
Y
Y Combinator Blog
Latest news
Latest news
SecWiki News
SecWiki News
Hugging Face - Blog
Hugging Face - Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Google Online Security Blog
Google Online Security Blog
Webroot Blog
Webroot Blog
Google DeepMind News
Google DeepMind News
Recent Commits to openclaw:main
Recent Commits to openclaw:main
C
Cisco Blogs
博客园_首页
H
Hackread – Cybersecurity News, Data Breaches, AI and More
宝玉的分享
宝玉的分享
L
LINUX DO - 热门话题

Miriam Eric Suzanne

Butter bells, fresh from the kiln Butter bells, fresh from the kiln Butter bells, fresh from the kiln I had to look it up I Laser-cut pottery throwing gauge Tech continues to be political Aggregating my distributed self A web component for CodePen embeds? We don A slash-why proposal User styles on the web Custom element, two ways New year, same (terrible) Mia CSS @scope Reclaiming my time Cascade Layers Javascript automation on Mac Personal Histories Ancient Web Browsers Critical CSS? Not So Fast! CSS tie-dye gradient backgrounds Personal website redesign Request for Comments: Sass Color Spaces A long-term plan for logical properties? Container queries in browsers! I never let things be small A whole cascade of layers This content won No demo [website] reno 2 days of cordwainery Body margin 8px The gray areas of HWB color Miriam, for the archive Complex vs compound selectors The spam has arrived Am I on the IndieWeb yet? My theatrical delusions A Complete Guide to CSS Cascade Layers Container queries explainer & proposal Very Extremely Practical CSS Art An open CSS notebook Custom Property “Stacks" Alcohol affects the frontal cortex Embracing the Universal Web CSS most normalizer-est Introducing Sass Modules F*CSS Not clear to me, an installation Framed | Born to choose this way Last Bullet, live music video A Dark Plain, live music video Guts | Let Rejecting maleness Chosen family (thank you) Mia Speaking of pride More CSS Charts, with Grid & Custom Properties (Mis)gender Stop Being Productive Fun with Viewport Units Gods on the Lam Body & gender fragments Trans Interviews & Photography Getting Started with CSS Grid Just Like That Adaptation: SideSaddle/Myths Justice [under construction] Some clarifications on trans language Some kind of resistance tour Loops in CSS Preprocessors An Interview with Miriam Suzanne Estrogentrification Miriam, a how-to guide Holes / SideSaddle midwest tour Underground music showcase Species of the stars PROPHETIA VETITUM MUNDI Pig Sez, song demo I UMS day 4 (the end) UMS day 3 A Dark Plain, song demo UMS day 2 UMS day 1 Media Archeology Lab, Artist in Residence Stratified design (re)Thinking on your feet Five(5), song demo Poetry readings are terrible Explosive growth Get curious The Posture of Contour Starting from a seed Portrait of Sondra & Dan Creative modes and cycles Ordinary tools of thought Portrait of Kitten Karlyle (nsfw) Fuck the muse Susy 1.0 release
Eleventy buckets & cascade layers
2024-07-06 · via Miriam Eric Suzanne

Outside of static-site templates, one goal of this refresh is to keep things as ‘vanilla’ as possible.

This isn’t some purist stance on my part. There are a lot of great tools that we recommend to clients every day. But this is my personal site, and a place to experiment. What happens when I let go of all the tools that I’m used to, and rely entirely on the web platform?

Along the way, I’m trying to find the best pattern for organizing my CSS into Cascade Layers. Layering can be done within a file, using the @layer <name> { … } rule block, or it can be done with a layer(<name>) function on-import. I prefer the latter for my top-level layers, because:

  • The layering can happen in one central place
  • Renaming and reordering is more more flexible
  • There’s less nesting in the CSS files

A few other rough criteria for how I write CSS:

  • Component-specific styles can be embedded in ‘single file components’ (WebC handles this well), but most of my CSS will be global
  • I like the global styles split into ‘partials’, so it’s not all one long document[1]
  • Each partial will be assigned to a cascade layer

Without any build steps, I get an HTML <head> that contains something like:

<style webc:keep>
  @layer reset, config, default, layout, component, utility;

  @import url('/css/reset.css') layer(reset);

  @import url('/css/config/colors.css') layer(config);
  @import url('/css/config/sizes.css') layer(config);

  @import url('/css/default/type.css') layer(default);
  @import url('/css/default/links.css') layer(default);
  @import url('/css/default/buttons.css') layer(default);
  @import url('/css/default/forms.css') layer(default);
  @import url('/css/default/media.css') layer(default);
  @import url('/css/default/blocks.css') layer(default);

  @import url('/css/layout/page.css') layer(layout);
  @import url('/css/layout/nav.css') layer(layout);
  @import url('/css/layout/header.css') layer(layout);
  @import url('/css/layout/main.css') layer(layout);
  @import url('/css/layout/footer.css') layer(layout);

  @import url('/css/utility/a11y.css') layer(utility);
</style>

The component styles are missing from that global list. CSS is designed to be global, and the best way to write minimal CSS (in my experience) is to focus more on reusable patterns over individual components. So I don’t expect much to end up in our component layer, but there’s always something. We can access those styles as a WebC asset bundle:

<style webc:keep
  @raw="`@import url(${getBundleFileUrl('css')}) layer(component);`"
></style>

I love that there’s very little build-time magic involved! Still, that’s a whole wall of imports, and I have a decades-old flinch reflex when I see that. Should I be worried?

Am I creating performance issues?

I’m not a performance expert, so I asked mastodon, and got a generally positive but mixed response.

It might not be the best performance, but (with HTTP 2/3) it shouldn’t be bad. My personal site doesn’t need eXtreme optimization, so that might be good enough for me? I’ll probably ship it, and find out.

Still, I know the first step in optimizing CSS is to concatenate – so I did explore a few approaches along the way, which could work if I need them.

Sass can load-css into layers

In the past, I’ve used Sass. I like Sass a lot. In Sass, I concatenate and layer the partials using meta.load-css() in my primary Sass file:

@use 'sass:meta';

@layer reset {
  @meta.load-css('reset');
}

@layer config {
  @meta.load-css('config/colors');
  @meta.load-css('config/sizes');
}

// etc.

That works pretty well. It’s what I’ve been doing on this site ever since I originally added layers.

But if I’m not using Sass for anything else, maybe I can avoid the dependency altogether?

When in Eleventy, do as the Eleventies do

I’m already using WebC, which provides asset bundling. I’ve already used that feature (above) to concatenate individual component styles. That compiles all the CSS into one bundle, and all the JS into another (unless you opt-out with webc:keep). Those bundles are available as either raw output or external files:

<!-- direct output -->
<style @raw="getBundle('css')" webc:keep></style>
<script @raw="getBundle('js')" webc:keep></script>

<!-- external files output -->
<link :href="getBundleFileUrl('css')" rel="stylesheet" webc:keep></style>
<script :src="getBundleFileUrl('js')" webc:keep></script>

But you can take that even further with asset bucketing – assigning <style>, <link>, or <script> tags to individually named CSS or JS buckets:

<style webc:bucket="good">/* … */</style>
<link webc:bucket="bad" href="terrible.css" rel="stylesheet" >
<style webc:bucket="bad">/* … */</style>
<style webc:bucket="ugly">/* … */</style>

And each bucket will get bundled up individually:

<!-- just the bad styles -->
<style @raw="getBundle('css', 'bad')" webc:keep></style>

Are you thinking what I’m thinking? Probably. It’s the title of the post.

Bundles let you concatenate CSS partials, and buckets let you group them as needed. That’s what I’m trying to do.

My CSS partials are external stylesheets, not attached to any particular WebC component, so first I have to pull them into buckets. I can do that with <link> tags in the header:

<link rel="stylesheet" href="../../_css/reset.css" webc:bucket="reset">
<link rel="stylesheet" href="../../_css/config/colors.css" webc:bucket="config">
<link rel="stylesheet" href="../../_css/config/sizes.css" webc:bucket="config">
<link rel="stylesheet" href="../../_css/config/fonts.css" webc:bucket="config">
<!-- etc -->

Since I’m using webc:bucket and not webc:keep, these <link> tags won’t appear in the HTML output. But now I have my buckets.

Since I’m interested in layering the buckets ‘on import’, I’ll need to generate external stylesheets. And since layering is not yet possible with the <link> tag, I’ll need to use @import rules instead. WebC makes that simple enough, using JS template tags. These, I’ll keep around:

<style
  webc:keep
  @raw="`@import url(${getBundleFileUrl('css', 'reset')}) layer(reset);`"
></style>
<style
  webc:keep
  @raw="`@import url(${getBundleFileUrl('css', 'config')}) layer(config);`"
></style>
<!-- etc -->

We can simplify that even more, using webc:for loops. I don’t know if there’s a way to access the list of buckets in WebC, so (for now) I’ve just added some front-matter data. While I’m at it, I’ll use that data to define my layer order up-front:

<!-- <style>@layer reset, config, default, etc;</style> -->
<style
  webc:keep
  @raw="`@layer ${($data.layers).join(', ')};`"
></style>

<!-- <style>@import url('bucket-name.css') layer(bucket-name);</style> -->
<style
  webc:keep
  webc:for="layer of ($data.layers)"
  @raw="`@import url(${getBundleFileUrl('css', layer)}) layer(${layer});`"
></style>

That’s it! Not quite as compact as the other two approaches, but it’s close – and it works great, without any extra dependencies.

I might be able to simplify that even further with webc:type='js', but I’ll cross that bridge if I decide that concatenation is worth the effort.


  1. Back in the late aughts and early 2010s, I was a big fan of CSSEdit (now part of Espresso, I believe). One of the best features was viewing a single massive CSS file as though it contained many smaller folders. Maybe I should go back to that approach, or even back to that specific app? ↩︎