Last week, Jeremy Keith wrote an excellent summary of the three ways to inject CSS into a web document. In short, he said:
There are three ways—that I know of—to associate styles with markup.
External CSS
<link rel="stylesheet" href="/path/to/styles.css">
Embedded CSS
<style>element { property: value; }</style>
Inline CSS
<element style="property: value"></element>
While talking about external CSS, he hinted at what I consider to be a distinct fourth way with its own unique use
cases:; using the Link:
HTTP header. I’d like to share with you how it works and why I think it needs to be
kept in people’s minds, even if it’s not suitable for widespread deployment today.
Injecting CSS using the Link:
HTTP Header
Every one of Jeremy’s suggestions involve adding markup to the HTML document itself. Which makes sense; you almost always
want to associate styles with a document regardless of the location it’s stored or the medium over which it’s transmitted. The most popular approach to adding CSS to a page uses the <link>
HTML element, but did you know… the <link>
element has a semantically-equivalent HTTP header, Link:
.
According to the specifications, the following HTTP responses are equivalent in terms of the CSS that would be loaded and applied to the document:
Traditional external CSS injection:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
<!doctype html>
<html>
<head>
<title>My page</title>
<link rel="stylesheet" href="/style/main.css">
</head>
<body>
<h1>My page</h1>
</body>
</html>
Link:
header CSS injection:
HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Link: </style/main.css>; rel="stylesheet" <!doctype html> <html> <head> <title>My page</title>
</head> <body> <h1>My page</h1> </body> </html>
Why is this important?
This isn’t something you should put on your website right now. This (21-year-old!) standard is still only really supported in Firefox and pre-Blink Opera, so you lose perhaps 95% of the Web (it could be argued that because CSS ought to be considered progressive enhancement, it’s tolerable so long as your HTML is properly-written).
If it were widely-supported, though, that would be a really good thing: HTTP headers beat meta/link tags for configurability, performance management, and separation of concerns. Need some specific examples? Sure: here’s what you could use HTTP stylesheet linking for:
- Performance improvement using aggressively preloaded “top” stylesheets before the DOM parser even fires up.
- Stylesheet injection by edge caches to provide regionalised/localised changes to brand identity.
- Strong separation of content and design by hosting content and design elements in different systems.
- Branding your staff intranet differently when it’s accessed from outside the network than inside it.
- Rebranding proprietary services on your LAN without deep inspection, using reverse proxies.
- Less-destructive user stylesheet injection by plugins etc. that doesn’t risk breaking icky on-page Javascript (e.g. theme switchers).
- Browser detection? 😂 You could use this technique today to detect Firefox. But you absolutely shouldn’t; if you think you need browser detection in CSS, use this instead.
Unfortunately right now though, stylesheet Link: headers remain consigned to the bin of “cool stylesheet standards that we could probably use if it weren’t for fucking Google”; see also alternate stylesheets.
Update: I later used this technique to make a seemingly-empty web page.