web-dev-qa-db-fra.com

Remplacer le fichier css à la volée (et appliquer le nouveau style à la page)

J'ai une page qui a <link> dans l'en-tête qui charge le CSS nommé light.css. J'ai aussi un fichier nommé dark.css. Je veux un bouton pour échanger le style de la page tous ensemble (il y a 40 sélecteurs utilisés dans le fichier CSS et certains ne correspondent pas dans deux fichiers).

Comment puis-je supprimer la référence à light.css avec JS et supprimer tous les styles qui ont été appliqués, puis charger dark.css et en appliquer tous les styles? Je ne peux pas simplement réinitialiser tous les éléments, car certains styles sont appliqués via différents fichiers CSS et certains sont générés dynamiquement par JS. Existe-t-il un moyen simple mais efficace de le faire sans recharger la page? Vanilla JS est préférable, mais jQuery sera utilisé pour les traitements ultérieurs de toute façon, jQ convient donc également.

48
Xeos

Vous pouvez créer un nouveau lien et remplacer l'ancien par le nouveau. Si vous la mettez dans une fonction, vous pouvez la réutiliser à tout moment.

Le 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);
}

Le 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>

Pour plus de simplicité, j'ai utilisé le javascript en ligne. En production, vous souhaiterez utiliser des écouteurs d'événements discrets.

50
Matthew Johnson

Vous pouvez inclure toutes les feuilles de style dans le document, puis les activer/désactiver au besoin.

Dans ma lecture de la spécification, vous devriez pouvoir activer une autre feuille de style en modifiant sa propriété disabled de true à false , mais seul Firefox semble le faire correctement.

Donc, je pense que vous avez quelques options:

Basculer rel=alternate

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

<script>
function enableStylesheet (node) {
  node.rel = 'stylesheet';
}

function disableStylesheet (node) {
  node.rel = 'alternate stylesheet';
}
</script>

Définir et basculer disabled

<link rel="stylesheet" href="main.css">
<link rel="stylesheet" href="light.css" id="light" class="alternate">
<link rel="stylesheet" href="dark.css"  id="dark"  class="alternate">

<script>
function enableStylesheet (node) {
  node.disabled = false;
}

function disableStylesheet (node) {
  node.disabled = true;
}

document
  .querySelectorAll('link[rel=stylesheet].alternate')
  .forEach(disableStylesheet);
</script>

Basculer media=none

<link rel="stylesheet" href="main.css">
<link rel="stylesheet" href="light.css" media="none" id="light">
<link rel="stylesheet" href="dark.css"  media="none" id="dark">

<script>
function enableStylesheet (node) {
  node.media = '';
}

function disableStylesheet (node) {
  node.media = 'none';
}
</script>

Vous pouvez sélectionner un nœud de feuille de style avec getElementById , querySelector , etc.

(Évitez le <link disabled> non standard. Définir HTMLLinkElement # disabled convient cependant.)

64
sam

En utilisant jQuery, vous pouvez certainement échanger le fichier css. Faites ceci sur le clic du bouton.

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

Ou comme la réponse de sam , ça marche aussi. Voici la syntaxe de jquery.

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

Si vous définissez un ID sur l'élément de lien

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

vous pouvez le cibler avec Javascript

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

ou juste..

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

Voici un exemple plus complet:

<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>
6
davidcondrey

Cette question est assez ancienne, mais je suggérerais une approche non mentionnée ici, dans laquelle vous allez inclure les deux fichiers CSS dans le code HTML, mais le code CSS sera comme

light.css

/*** light.css ***/

p.main{
   color: #222;
}

/*** other light CSS ***/

et dark.css sera comme

/*** dark.css ***/

.dark_layout p.main{
   color: #fff;
   background-color: #222;
}

/*** other dark CSS ***/

basicall chaque sélecteur dans dark.css sera un enfant de .dark_layout

Ensuite, tout ce que vous avez à faire est de changer la classe de l'élément body si quelqu'un choisit de changer le thème du site.

$("#changetheme").click(function(){
   $("body").toggleClass("dark_layout");
});

Et maintenant, tous vos éléments auront le css sombre une fois que l'utilisateur clique sur #changetheme. C'est très facile à faire si vous utilisez n'importe quel type de pré-processeur CSS.

Vous pouvez également ajouter des animations CSS pour les arrière-plans et les couleurs, ce qui facilite grandement la transition.

5
void

En utilisant jquery .attr () vous pouvez définir href de votre tag link .i.e 

Exemple de code

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

Je pense peut-être trop compliqué, mais comme la réponse acceptée ne fonctionnait pas pour moi, je pensais aussi partager ma solution.

Récit:
Ce que je voulais faire, c’était d’inclure différents «skins» de ma page dans la tête en tant que feuilles de style supplémentaires qui étaient ajoutées au style «principal» et de les changer en appuyant sur un bouton de la page (aucun paramètre de navigateur ou autre élément). .

Problème:
Je pensais que la solution de @ sam était très élégante, mais elle ne fonctionnait pas du tout pour moi. Une partie au moins du problème est que j'utilise un fichier CSS principal et que j'en rajoute d'autres en tant que "skins" et que je dois donc grouper les fichiers avec la propriété missing "title" property.

Voici ce que je suis venu avec.
D'abord, ajoutez tous les 'skins' à la tête en utilisant 'alternatif':

<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=''>

Notez que j'ai donné au fichier CSS principal le titre = 'main' et que tous les autres ont un class = 'style-skin' et aucun titre.

Pour changer de peau, j'utilise jQuery. Je laisse aux puristes le soin de trouver une version élégante de VanillaJS:

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++
});

Qu'est-ce qu'il fait est qu'il itère sur tous les peaux disponibles, prend celui (bientôt) actif, met le titre sur 'main' et l'active. Tous les autres skins sont désactivés et le titre est supprimé.

0
Flow