The <style-switcher>
element
(One of the custom elements I use around here.)
Alternative stylesheets (created with <link rel="alternate stylesheet">
) are a neat feature in HTML, but no modern browser exposes UI for switching between them.
That’s where the <style-switcher>
custom element
comes in.
Table of Contents
Usage
As with any custom element, the close tag cannot be omitted.
<style-switcher></style-switcher>
The element takes one attribute, label
, which you can
use to supply text for labeling the switcher’s drop-down menu.
label=""
attribute<style-switcher label="Choose a theme"></style-switcher>
But where does the custom element get the list of themes from? It
just finds all the <link rel=stylesheet>
elements in the
page. If a <link>
element has a title=""
attribute, it uses that as a human-readable description of the
stylesheet. If title=""
is missing, it synthesizes a
description from the contents of the href=""
attribute.
<style-switcher>
usage<link rel=stylesheet href=/css/default.css>
<link rel="alternate stylesheet" href=green-links.css
title="Basic theme with green links">
<link rel="alternate stylesheet" href=red-links.css
title="Basic theme with red links">
…
<style-switcher label="Choose a theme"></style-switcher>
How it works
It’s pretty much the simplest thing. There’s a change
event handler on the <select>
element which disables
all of the stylesheets except for the selected one. (There’s a bit of
redundant code for disabling stylesheets, marked like
this below. This is a workaround for
a
Blink and WebKit bug that’s been around for ages.)
function updateStylesheets(event) {
const selected_href = event.target.value;
for (const sheet of document.querySelectorAll("link[rel~=stylesheet]")) {
if (sheet.getAttribute("href") == selected_href) {
sheet.relList.remove("alternate");
sheet.disabled = false;
sheet.disabled = true;
sheet.disabled = false;
} else {
sheet.relList.add("alternate");
sheet.disabled = true;
}
}
}
A note about progressive enhancement
I’m an advocate for custom elements that enhance the markup they
contain, that still more-or-less function when the custom element
fails to initialize. (This pattern’s called
HTML web
components these days.) You’ve probably noticed
that <style-switcher>
doesn’t seem to fit that
pattern.
I’d argue that it actually does. All of the functionality
of <style-switcher>
is optional enhancement—the widget
is completely unnecessary to the function of the page. It’s a
nice-to-have feature. So, in the situation where it fails to load,
there’s simply nothing visible to the user. The user has no idea
they’re missing out on anything, which is totally fine.