Switch it up!

4 step tutorial: CSS Switch setup

switch

Nowadays, our digital devices offer OS settings for light and dark view modes. The specifics of how exactly these controls should work are stirring up much discussion. How do we best accommodate our users, cater for their needs as well as their different personal preferences?

Should a website detect such device settings and adjust?

Or should the site not probe the device but offer the option to switch instead?

That is a bigger debate which has yet to find a good conclusion. This tutorial focuses on setting up a CSS Switch for an enhanced user experience, be that for the sake of better accessibility or for pure visual enjoyment and fun. We'll be using plain vanilla JS (rather than jQuery) as there's no need for a whole library for a simple switch.

Benefits of CSS switches

By definition, the CSS switch will give our users a choice of how to view our content. They might prefer less colour, or larger type size. Our fancy layout might be too busy for their taste. Our animated elements too distracting or right down annoying or even preventing some people from viewing our site.

Making no assumptions on taste or abilities, giving users options is something that can only be a good thing :) If our site's design is quite dark and moody yet presents lots to read, for example, then giving people the option to switch to dark text on light background will be welcomed by many.

Or our site's design uses a subtle colour scheme and very light font weights which is something that could be to the detriment of legibility and therefore accessibility. Offering people a choice will be useful to accommodate personal preferences as well as needs.

A typical CSS switch works by prompting the browser to load in an alternate stylesheet and apply it. The website is given a default CSS which is applied when loaded/viewed. Links to the alternative CSS files are included and triggered by the switch via JavaScript. Usually, the default CSS will include all settings for design and layout and the alternatives will include overrides for their respective versions.

illustration of CSS loading via browserAlternate stylesheets can be loaded and accessed via the in-built browser tools already - the CSS switch merely adds this option to the site itself, clearly visible and making it easy to use for anyone.

default CSS

Let's assume we're using one main CSS for our site which is already linked to from within the <head> tag. And this is the big one, i.e. the CSS which holds all design settings. It's called the persistent stylesheet and used by default.

<link rel="stylesheet" href="style.css">

alternate CSS

For the different design version, we'll now add a link to this alternate stylesheet, again inside the <head> tag. These files include all settings to change the design as available. We might only have two CSS for the light/dark views. Or add an additional one for a high contrast version.

<link rel="alternate stylesheet" title="hicontrast" href="style-hicontract.css">

Note the added title attribute which is used for the switch functions to identify each alternate CSS correctly.

the switch

The switch can take any shape, a sliding button, checkbox or simple link. It's best to follow the project's UI patterns and consider how this function will fit. The switch function itself works with JavaScript, triggered via the onclick=" " event.

<a href="#" onclick="setActiveStyleSheet('hicontrast');">
	<!-- text or icon for switch -->
</a>

One of the easiest accessibility enhancements is to set up a CSS switch for the high contrast version. This design will focus primarily on setting a strong contrast between text and background colour to increase legibility. Typically, a high contrast design will set a dark background with bright text and adjust typesetting accordingly.

While designed with accessibility in mind for people with low vision, these versions are also popular, and often preferred, in certain settings (e.g. when in a cinema, aiming to keep light emissions low) or when concentration is lagging. A great addition to most site ~ let's take this as the example to set up a CSS switch on this page.

project folder

screenshot of folder structure

Our final set up will look as follows:

#1 finalise persistent CSS

This is the master CSS, the big one already included in our website - added inside the <head> tag:

<link rel="stylesheet" href="css/style.css" />

Note: the link to CSS file sets the rel to stylesheet only and includes no title. This defines this CSS as the default to be loaded. It's important to keep in mind that no title should be set for the persistent stylesheet.

Before working on any alternatives to our design, let's check our CSS thoroughly and make sure we're happy. As our plan is to change colours, it will be best to ensure that colour rules set are minimal, as few as possible, making the most of the cascade and allowing for overrides with few rules.

#2 create alternate CSS

We'll save a new, empty file into our CSS folder, naming it according to its purpose. Giving our alternate CSS file a name reflecting the new version's design will make it easier to work with :)

In our case we're adding a high contrast version so let's call the file style-hicontrast.css.
The new CSS will now change background and text colours to a high contrast, reversing colours in the process. At its most basic, this is to set the background to black and the text colour to white.

body {
	background: #000;
	color: #fff;					
}

Note: to apply this new CSS to the page as we work on the code, we can simply add an extra link to the new file as persistent CSS, i.e. using the same code as used under #1. This will then load both CSS on page load and we can work on our overrides easily. When done, we'll add the required details to define this as alternate CSS to ready it for the switch.

switching CSS in browser:
And if we want to switch between the default and the alternate CSS in the browser, we'll use rel="alternate stylesheet" and add the title. This makes the file available to the browser for easy previewing. In Firefox, for example, we can change the CSS on the fly via top menu > View > Page Style: select our alternate CSS from dropdown.

<link rel="alternate stylesheet" title="hicontrast" href="css/style-hicontrast.css" />

#3 styleswitcher.js

We'll be going back to one of the old classics from A List Apart for this one: Alternative Style: Working With Alternate Style Sheets by Paul Sowden, 2001. This article is quite old by now but it's still one of the most direct and clear tutorials on the subject. And it's been working perfectly ever since. Please do read the original article as I'll merely quote the core JS code here for reference.

We'll now need to set up the functions for the switch. First the script checks for the existing links to stylesheets, their title and the keyword 'alternate' which in turn are used for the switch function.

function setActiveStyleSheet(title) {
  var i, a, main;
  for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
	if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
	  a.disabled = true;
	  if(a.getAttribute("title") == title) a.disabled = false;
	}
  }
}

function getActiveStyleSheet() {
  var i, a;
  for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
	if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && !a.disabled) return a.getAttribute("title");
  }
  return null;
}

function getPreferredStyleSheet() {
  var i, a;
  for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
	if(a.getAttribute("rel").indexOf("style") != -1
	   && a.getAttribute("rel").indexOf("alt") == -1
	   && a.getAttribute("title")
	   ) return a.getAttribute("title");
  }
  return null;
}

Please note the code quoted here does not include the cookie script, please see the original source for full code.

↓ download JS file from alistapart.com

We'll now save this file into the 'js' folder in our site's directory and link to it from our pages. Traditionally, this script tag is added just before the closing </body> tag. These days, there are many other methods ~ make sure to check on other dependencies and scripts of your project and use the methods that fit.

<!-- JS -->
<script src="js/styleswitcher.js"></script>

#4 set up switch

With both CSS and the JS functions ready, we'll now add the switch itself. Let's use a simple list to offer the two settings, more could then be added later quite easily.

<div id="switch">
	<ul>
	  <li class="default" >
		<a href="#" onclick="setActiveStyleSheet('style');">
			default
		</a>
	  </li>
	  <li class="hicontrast">
	  	<a href="#" onclick="setActiveStyleSheet('hicontrast');">
			high contrast
	  	  </a>
		</li>
	</ul>
</div>	

The links are empty, refreshing the page on click and the switching function is added via the addition of the onclick event. Our switch will use simple text initially ~ possibilities for design are endless and can be explored later.

onclick="setActiveStyleSheet('style');" = loads persistent CSS

onclick="setActiveStyleSheet('hicontrast');" = loads alternate CSS

the result: basic switch

Try out the switch to see the result of these most basic overrides. We can see that the colour change works fine overall, yet elements such as the headings or code examples are not changed and will need more tweaks. We also have to bear in mind that the drastic change to light text on dark will require fine-tuning of typesetting for better legibility.

fine-tuning

With the switch function working, we can spend some time to refine the new version for better use of colour. High contrast does not have to be pure black and white ~ so we can adjust the overall colour scheme and tweak the typesetting for best results. Colours for headings and code samples to be set to lighter shades for increased contrast.

/* light on dark defaults */
body {
	background: #252424;
	color: #F2F2F2;	
}
/* link styling */
a:link, a:visited {
	color: #19a4c3;
}
a:hover, a:active, a:focus {
	color: #bd9cf1;
}
/* typesetting & colour */
article p {
	line-height: 1.6;
}
article p.qu:before {
	color: #bd9cf1;
	opacity: 1;
}
h2, h3 {
	color: #bd9cf1;
}
h2 em, h2 + aside {
	color: #e6e6e6;
}
code {
	font-size: 1.2em;
	background: #0A0A0A;
	color: #72a7fb;
	border: 1px solid #333;
	border-bottom: 1px dashed #666;
}
code pre {
	color: #72a7fb;
}

code:after {
	background: #000;
	opacity: 1;
}
code.js {
	color: #a0e706;
}
code.js pre {
	color: #a0e706;
}
/* content toggles */
.lbl-toggle {
	font-size: 2em;
	line-height: 1;
	font-weight: 300;
	color: #a4d0da;	
}
.lbl-toggle:hover {
	color: #bd9cf1;
}
.lbl-toggle::before {
	background: #a4d0da;
}
.toggle:checked + .lbl-toggle {
	color: #bd9cf1;
}
.toggle:checked + .lbl-toggle::before {
	background: #bd9cf1;
}

As final step we design the 2 options as buttons, presented as icons with a tooltip for extra info. Our final switch here shows the most simple approach for the sake of clarity.

/* switch */
#switch {
	border: 2px solid #5F3C94;
	border-radius: 48px;
	padding: 0;
	font-size: 2em;
	margin: 0 0 24px 0;
	width: 173px;
}
#switch h3 {
	font-weight: 300;
	text-transform: uppercase;
	margin: 0 1em 0 0;
	display: none;
}
#switch ul {
	display: inline;	
}
#switch ul li {
	display: inline-block;
	margin: 12px 0 0 0;
}
#switch ul li a:link {
	display: block;
	padding: 0 .5em;
	width: 64px;
	height: 64px;
}
/* icons */
#switch ul li a svg {
	display: block;
	width: 64px;
	height: 64px;
	margin: 0 auto;
	border-radius: 50%;
	-webkit-transition: all .2s ease-in-out;  
	-moz-transition: all .2s ease-in-out;  
	-o-transition: all .2s ease-in-out;  
	transition: all .2s ease-in-out;
}
#switch ul li a:link svg, #switch ul li a:visited svg {
	fill: #5F3C94;
	background: #fff;
}
#switch ul li a:hover svg {
	fill:  #fff;
	background: #5F3C94;
}
#switch ul li a:active svg, #switch ul li a:focus svg {
	background: #19a4c3;
}
/* tooltip */
#switch ul li a:after {
	font-size: 26px;
	line-height: 1.2;
	font-weight: 600;
	display: block;
	width: 12em;
	position: absolute;
	top: .5em;	
}
#switch ul li.default a:hover:after{
	content: 'set default view';
	left: 200px;
}
#switch ul li.hicontrast a:hover:after{
	content: 'set high contrast view';
	left: 128px;
}

the result: final switch

switch

Adding this function to any web project should tie into the overall UI seamlessly and most importantly be accessible and easy to use. Implementation options are a simple on/off switch for a high contrast version alone, a preferences set with multiple options — all depending on context and user groups.

About the featured switches

  1. light the default design version: dark set text on light background; use of 2 core colours for UI, headings and highlights.
  2. dark the dark version of the design: reverses colours and sets light text on dark background; colours for UI, headings and highlights edited for lighter tone; typesetting update to adjust size and line height for legibility.
  3. black+white the desaturated black & white design version: strips the design of all colour, using black/white and shades only; typesetting updated to adjust size and line height for legibility; presentation of media (image/video) uses CSS greyscale filter.
  4. large the large, bold design version: the most elaborate of the designs adds detail to background; changes to typefaces; typesize is responsive, scaling up with increasing viewports size.

Switch example: colour overload

Let me give you one good example of when a CSS switch is useful to allow possible annoyances to be removed. This is a single webpage which is loaded with colour via an animated gradient background. Something which some will love - and some will absolutely hate. An 'off' switch was the only way :)

Background:
The example is the addendum page for small site I created with the main purpose of introducing web experts to my web students and anyone interested :) It's an informal little listing of people and I used colour mainly as an added touch, to hint at areas of expertise. I created a supplementary page to elaborate on this concept and felt like going all out on colour for this page alone. For the sheer fun of it.

Take a look at the page: People of the web - Addendum.

The animated gradient (otherwise reserved for smaller elements on the site only) is applied to the background of the entire page. This is a drastic change to the feel of the site. It delivers a splash of colour which then slowly moves, gradually changing colour cycling through the different tones. Text is set in white and is clearly legible overall.

This might be fine for most people while the movement of colour alone might hinder legibility for others, not ideal. Most affected are the large words set in different colours. The changing colour combinations play games with your eyes as the shades used for the text make it appear to fade in and out of visibility depending on background colour passing by. A typical scenario when one size does not fit all and offering a 'way out' via stripping the colour will be best.

To allow people to get rid of the colour in motion, I've added a CSS switch which removes the background colour and changes the text to dark. The page is now presented in keeping with the rest of the site and with consistency restored, hopefully everyone will be happy :)

colour splash! :)

As a quick demo of how this motion effect might go wrong elsewhere - try it out on this very page here. This is the same colour gradient as the example page, set to a much faster speed to make the motion more obvious (and more obviously disruptive).

With the mixed content, the moving colours quickly become tiresome and slow down reading. Concentration fades. This shows that overly bold design touches like colour and motion have to be handled with care, applied only when fitting context and audience. In the case of this tutorial, a colour effect like this would be counter-productive and the worst idea :D

In comparison, the addendum page example consists of only text which is set at a fairly large size to maintain legibility on a busy or bold background. This might not be to everyone's taste but the combination of white text and the slow speed of the motion presents a readable page at least.

Closing thoughts

Adding a CSS switch can bring so many advantages, can be a ton of fun and is definitely something we should consider and keep in mind. As we saw, it was not very complicated nor took long to set up switches for versions which had a different purpose and feel. These alternative version did not require many additions to change our page's design quite drastically and are well worth the time and effort.

Here are a few things to keep in mind if you're planning to add alternative versions.

design demo © eyesrc.org