user4383942
user4383942

Reputation:

Elegant way of swapping theme stylesheets without reloading page

I am looking for a way to hot-swap stylesheets while the page is loaded. Here is my current solution, it works but it has some limitations/issues.

html head:

<link id="theme" href="themes/theme1.css" rel="stylesheet" type="text/css">

js:

themes = [
  "themes/theme1.css",
  "themes/theme2.css"
];

function themeSwitch() {
  var currentTheme = $("#theme").attr('href');
  var themeID = themes.indexOf(currentTheme);
  themeID =  (themeID + 1) % themes.length;
  $("#theme").attr('href', themes[themeID]);
}

My issue with this approach is when the function is called the change is not instant as the browser needs to make an additional GET request for the css file. Another issue is if the user temporarily disconnects while using the page they will be left without a theme.

Upvotes: 0

Views: 910

Answers (1)

Jaromanda X
Jaromanda X

Reputation: 1

use alternate stylesheet makes it easy (example for two themes is trivial)

<link id="theme" href="themes/theme1.css" rel="stylesheet" type="text/css">
<link id="alttheme" href="themes/theme2.css" rel="alternate stylesheet" type="text/css">

function themeSwitch() {
    var t1 = document.getElementById('theme');
    var t2 = document.getElementById('alttheme');
    t1.disabled = !t1.disabled;
    t2.disabled = !t1.disabled;
}

A more generic way, which allows any number of themes

<link class="theme" href="themes/theme1.css" rel="stylesheet" type="text/css">
<link class="theme" href="themes/theme2.css" rel="alternate stylesheet" type="text/css">
<link class="theme" href="themes/theme3.css" rel="alternate stylesheet" type="text/css">

var currentTheme = 0;
var themes = [].slice.call(document.querySelectorAll('link.theme'));

function themeSwitch() {
    currentTheme = (currentTheme + 1) % themes.length;
    themes.forEach(function(theme, index) {
        theme.disabled = (index !== currentTheme);
    });
}

And last of all, though you haven't tagged jQuery, you do use jQuery in your code, so, for the sake of the jQuery set:

<link class="theme" href="themes/theme1.css" rel="stylesheet" type="text/css">
<link class="theme" href="themes/theme2.css" rel="alternate stylesheet" type="text/css">
<link class="theme" href="themes/theme3.css" rel="alternate stylesheet" type="text/css">

var currentTheme = 0;
var themes = $('link.theme');

function themeSwitch() {
    currentTheme = (currentTheme + 1) % themes.length;
    themes.each(function(index, theme) {
        theme.disabled = (index !== currentTheme);
    });
}

Upvotes: 3

Related Questions