Jim Nielsen’s Blog
Preferences
Theme: This feature requires JavaScript as well as the default site fidelity (see below).
Fidelity:

Controls the level of style and functionality of the site, a lower fidelity meaning less bandwidth, battery, and CPU usage. Learn more.

Any Day Can Be CSS Naked Day

A while ago, I coded a little script that allowed me to append ?noCSS to a page on my website and it would automatically strip all the styles from the document, leaving solely the pure HTML. It was a neat little trick to ensure I kept my HTML semantic over time.

Fast forward to now, I was recently browsing Twitter (against my better judgement) and learned about a thing called CSS Naked Day from @zachleat. It reminded me of my old query param hack which could make it CSS naked day any day of the week.

Doing it at anytime isn’t a new idea. Zach does this on his website, providing the ability to toggle the visibility of styles.

Screenshot of zachleat.com with an arrow pointing to the UI toggle to turn CSS on or off.

Also, when I looked up Zach’s tweet that made me think of my old query parameter, I stumbled on this tweet from @mxbck along the same lines:

I somehow never noticed that @zachleat's site has an on/off switch for CSS & webfonts in the footer and damn I ❤️ heart that idea. every day can be CSS naked day!

This is all a long way of saying: I made a thing to turn styles on/off on the client. Rather than stick a UI control on the screen, my approach is via the URL bar. Essentially, you add a little script to your website, add the ?css-naked query param to any page you load, and your styles will be gone. You can navigate from page to page and it will persist your choice of stripping out styles until you opt-out. Check out the code for css-naked on Github.

Try It Out

Want to see how it works? You can try it on any page on the web! To do so, load a web page with the query param ?css-naked, open the console in the browser’s DevTools, and run this dynamic import:

import("https://cdn.jsdelivr.net/gh/jimniels/css-naked@0.1.0/css-naked.js");

Screenshot of blog.jim-nielsen.com with and without CSS naked applied.

If you embed it on your site, it’ll persist your choice to be in “CSS Naked Mode” across pages.

Animated gif illustrating how CSS Naked strips styles across page loads.

Technical Notes For Those Interested

Why is the script a module? I use some ES6 syntax in my CSS naked script, which is why the usage examples request you import the script as a module. It’s a lazy way of ensuring browsers using the script cut the mustard of this modern syntax. No ESM support? No problem. Nothing breaks. It simply won’t work. Could I have written it in ES5 or below? Yeah, but what fun is that?

How does it work? Go ahead and read the code, it’s short. In essence, the script digs into the DOM and strips out all <style> and <link rel="stylesheet" > tags, then finds any DOM nodes with a style attribute and clears it.

It’s JavaScript? I know, I know. There are a lot of things “wrong” about this approach. First, it doesn’t work without JavaScript. Second, external styles are always loaded. If you install this on your own site and enter “CSS Naked Mode”, you’ll likely get an unsightly flash of styled content as you navigate between pages. This is because the browser loads the document, loads the CSS, paints, then asynchronously loads the script that strips the styles. If you wanted to do this proper, you’d likely build this as a combo of server/client solution. The server could accept the query parameter then persist that choice across requests. For each request, the server could then strip out all references to styles (that it knows about) so they don’t ever get requested on the client. But if you have third-party dependencies, you’d still have the issue of them injecting their own styles into your DOM. Even with all of that said, there’s still the problem of web components and shadow DOM styles (which I haven’t attempted to solve for). And don't even get me started on iframes with embedded styles. In short, this is in no ways a comprehensive solution. It’s merely a little trick I use on some of my own stuff to double-check my HTML semantics.