Home » Html » Replacing css file on the fly (and apply the new style to the page)

Replacing css file on the fly (and apply the new style to the page)

Posted by: admin November 29, 2017 Leave a comment

Questions:

I have a page which has <link> in the header that loads the CSS named light.css. I also have a file named dark.css. I want a button to swap the style of the page all together (there are 40 selectors used in css file and some do not match in two files).

How can I remove reference to light.css with JS and remove all the styles that were applied and then load dark.css and apply all the styles from that? I can’t simply reset all of the elements, since some of the styles are applied through different css files and some are dynamically generated by JS. Is there a simple, yet effective way to do that without reloading the page? Vanilla JS is preferable, however I will use jQuery for later processing anyways, so jQ is also fine.

Answers:

From Omnimint:

The Javascript:

function changeCSS(cssFile, cssLinkIndex) {

    var oldlink = document.getElementsByTagName("link").item(cssLinkIndex);

    var newlink = document.createElement("link");
    newlink.setAttribute("rel", "stylesheet");
    newlink.setAttribute("type", "text/css");
    newlink.setAttribute("href", cssFile);

    document.getElementsByTagName("head").item(0).replaceChild(newlink, oldlink);
}

The HTML:

<html>
    <head>
        <title>Changing CSS</title>
        <link rel="stylesheet" type="text/css" href="positive.css"/>
    </head>
    <body>
        <a href="#" onclick="changeCSS('positive.css', 0);">STYLE 1</a> 
        <a href="#" onclick="changeCSS('negative.css', 0);">STYLE 2</a>
    </body>
</html>

For simplicity, I used inline javascript. In production you would want to use unobtrusive event listeners.

Questions:
Answers:

Put all the stylesheets in the markup and then toggle their disabled properties as needed:

<link rel="stylesheet"           href="main.css">
<link rel="stylesheet alternate" href="light.css" id="light-styles" title="Light">
<link rel="stylesheet alternate" href="dark.css"  id="dark-styles"  title="Dark">

<script>
    // Example: enable "Dark"
    document.getElementById('dark-styles').disabled  = false;
    document.getElementById('light-styles').disabled = true;
</script>

(Avoid the nonstandard <link disabled>. Setting HTMLLinkElement#disabled is fine though.)

Questions:
Answers:

Using jquery you can definitely swap the css file. Do this on button click.

var cssLink = $('link[href*="light.css"]');
cssLink.replaceWith('<link href="dark.css" type="text/css" rel="stylesheet">');

Or as sam’s answer, that works too. Here is the jquery syntax.

$('link[href*="light.css"]').prop('disabled', true);
$('link[href*="dark.css"]').prop('disabled', false);

Questions:
Answers:

If you set an ID on the link element

<link rel="stylesheet" id="stylesheet" href="stylesheet1.css"/>

you can target it with Javascript

document.getElementsByTagName('head')[0].getElementById('stylesheet').href='stylesheet2.css';

or just..

document.getElementById('stylesheet').href='stylesheet2.css';

Here’s a more thorough example:

<head>
    <script>
    function setStyleSheet(url){
       var stylesheet = document.getElementById("stylesheet");
       stylesheet.setAttribute('href', url);
    }
    </script>

    <link id="stylesheet" rel="stylesheet" type="text/css" href="stylesheet1.css"/>
</head>
<body>
    <a onclick="setStyleSheet('stylesheet1.css')" href="#">Style 1</a>
    <a onclick="setStyleSheet('stylesheet2.css')" href="#">Style 2</a>
</body>

Questions:
Answers:

Using jquery .attr() you can set href of your link tag .i.e

Sample code

$("#yourButtonId").on('click',function(){
   $("link").attr(href,yourCssUrl);
});

Questions:
Answers:

Maybe I’m thinking too complicated, but since the accepted answer was not working for me I thought I’d share my solution as well.

Story:
What I wanted to do was to include different ‘skins’ of my page in the head as additional stylesheets that where added to the ‘main’ style and switch them by pressing a button on the page (no browser settings or stuff).

Problem:
I thought @sam’s solution was very elegant but it did not work at all for me. At least part of the problem is that I’m using one main CSS file and just add others on top as ‘skins’ and thus I had to group the files with the missing ‘title’ property.

Here is what I came up with.
First add all ‘skins’ to the head using ‘alternate’:

<link rel="stylesheet" href="css/main.css" title='main'>
<link rel="stylesheet alternate" href="css/skin1.css" class='style-skin' title=''>
<link rel="stylesheet alternate" href="css/skin2.css" class='style-skin' title=''>
<link rel="stylesheet alternate" href="css/skin3.css" class='style-skin' title=''>

Note that I gave the main CSS file the title=’main’ and all others have a class=’style-skin’ and no title.

To switch the skins I’m using jQuery. I leave it up to the purists to find an elegant VanillaJS version:

var activeSkin = 0;    
$('#myButton').on('click', function(){
    var skins = $('.style-skin');
    if (activeSkin > skins.length) activeSkin=0;
    skins.each(function(index){
        if (index === activeSkin){
            $(this).prop('title', 'main');
            $(this).prop('disabled', false);
        }else{
            $(this).prop('title', '');
            $(this).prop('disabled', true);
        }
    });
    activeSkin++
});

What it does is it iterates over all available skins, takes the (soon) active one, sets the title to ‘main’ and activates it. All other skins are disabled and title is removed.