CSS-Datei im laufenden Betrieb ersetzen (und den neuen Stil auf die Seite anwenden)

71

Ich habe eine Seite <link>in der Kopfzeile, die das benannte CSS lädt light.css. Ich habe auch eine Datei mit dem Namen dark.css. Ich möchte, dass eine Schaltfläche den Stil der Seite insgesamt vertauscht (in der CSS-Datei werden 40 Selektoren verwendet, und einige stimmen nicht in zwei Dateien überein).

Wie kann ich light.cssmit JS den Verweis auf entfernen und alle angewendeten Stile entfernen und dann dark.cssalle Stile daraus laden und anwenden? Ich kann nicht einfach alle Elemente zurücksetzen, da einige der Stile über verschiedene CSS-Dateien angewendet werden und andere dynamisch von JS generiert werden. Gibt es eine einfache und dennoch effektive Möglichkeit, dies zu tun, ohne die Seite neu zu laden? Vanilla JS ist vorzuziehen, aber ich werde jQuery trotzdem für die spätere Verarbeitung verwenden, daher ist jQ auch in Ordnung.

Xeos
quelle
1
Ich wählte Mattew Antwort , weil mit dieser Methode kann ich leicht die für () Schleife erweitern , um mehr Dateien und Swap handhaben lightund darkin anderen Skripten / Stylesheets.
Xeos

Antworten:

70

Sie können einen neuen Link erstellen und den alten durch den neuen ersetzen. Wenn Sie es in eine Funktion einfügen, können Sie es überall dort wiederverwenden, wo es benötigt wird.

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

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

Der Einfachheit halber habe ich Inline-Javascript verwendet. In der Produktion möchten Sie unauffällige Ereignis-Listener verwenden.

Matthew Johnson
quelle
9
Ich denke, dass das einfache Aktualisieren der hrefEigenschaft genauso gut funktionieren könnte:oldlink.href = cssFile; // done
Sam
Wahr. Dies ersetzt den gesamten Verbindungsknoten im DOM.
Matthew Johnson
Wenn Sie eine Art Live-Reload durchführen möchten, ist dies wahrscheinlich der richtige Weg, da die href möglicherweise dieselbe ist und der Browser möglicherweise nichts unternimmt, wenn sich die href nicht tatsächlich geändert hat.
Flcoder
1
Beim Wechseln von CSS-Dateien bleibt die HTML-Datei aufgrund der Lücke beim Herunterladen der Datei und beim Rendern der Stile ohne Stile. Ich denke, es sollte immer ein Standard-Stylesheet geben, das grundlegende Stile hinzufügt. Mobile Browser benötigen einfach viel Zeit, um das CSS-Stylesheet zu ersetzen. Auch der Link-Index kann auf verschiedenen Seiten variieren, da eine statische Website von jekyll
Irshad
Sie können eine absolute URL verwenden, um zu umgehen, dass sich Seiten in verschiedenen Ordnern befinden oder so. Ich mag die Idee eines Standard-Stylesheets, um zu verhindern, dass die FOUC angezeigt wird. Schöner Tipp!
Matthew Johnson
79

Sie können alle Stylesheets in das Dokument aufnehmen und sie dann nach Bedarf aktivieren / deaktivieren.

Beim Lesen der Spezifikation sollten Sie in der Lage sein, ein alternatives Stylesheetdisabled zu aktivieren, indem Sie seine Eigenschaft von true in false ändern. Dies scheint jedoch nur von Firefox korrekt ausgeführt zu werden.

Ich denke, Sie haben ein paar Möglichkeiten:

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

Einstellen und umschalten 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>

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

Sie können einen Stylesheet-Knoten mit getElementById , querySelector usw. auswählen .

(Vermeiden Sie den Nichtstandard <link disabled>. Das Deaktivieren von HTMLLinkElement # ist jedoch in Ordnung.)

Sam
quelle
@sam jetzt tut es mir leid, dass ich keine Antwort auf die Frage eines anderen akzeptieren kann :) ... nur, gibt es irgendwelche Auswirkungen auf die Leistung der Seite? Wird der deaktivierte Link vom Browser ignoriert, bevor dieses Attribut auf false gesetzt wird?
Dzenesiz
8
Leider wird die Einstellung disabledals Attribut nicht empfohlen: "Die Verwendung von deaktiviert als HTML-Attribut ist nicht Standard und wird nur von einigen Browsern verwendet (W3 # 27677). Verwenden Sie es nicht." -> developer.mozilla.org/en-US/docs/Web/HTML/Element/…
Daniel
@ dzenesiz-Browser können das Herunterladen eines alternativen Stylesheets überspringen, bis es benötigt wird, aber ich weiß nicht, wie sie sich tatsächlich verhalten.
Sam
3
Um zu verdeutlichen, was @Daniel gesagt hat, ist das HTML-Attribut nicht Standard, ABER laut Mozilla ist die DOM-Eigenschaft IS. Das Umschalten mit Javascript auf die oben beschriebene Weise ist in der Tat standardkonform. Sofern mir nichts fehlt, sollte dies die akzeptierte Antwort sein.
Emersonthis
1
Das CSS-Objektmodell sagt dies über das disabledFlag aus: "Hinweis: Auch wenn es nicht gesetzt ist, bedeutet dies nicht unbedingt, dass das CSS-Stylesheet tatsächlich zum Rendern verwendet wird." Dies ist wahrscheinlich der Grund, warum die Antwort unter Firefox funktioniert, nicht jedoch unter Webkit & Blink ( Epyphany & Chromium ).
Cristian Ciupitu
14

Wenn Sie eine ID für das Linkelement festlegen

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

Sie können es mit Javascript ausrichten

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

oder nur..

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

Hier ist ein ausführlicheres Beispiel:

<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>
Davidcondrey
quelle
8

Mit jquery können Sie die CSS-Datei definitiv austauschen. Klicken Sie dazu auf die Schaltfläche.

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

Oder als Sams Antwort funktioniert das auch. Hier ist die jquery-Syntax.

$('link[href*="light.css"]').prop('disabled', true);
$('link[href*="dark.css"]').prop('disabled', false);
Krishna
quelle
1
Es könnte besser sein, aber ich mag es, wie Sie Sams jQ-Anteil sauber definiert und mir geholfen haben, alles klar zu verstehen.
RozzA
8

Diese Frage ist ziemlich alt, aber ich würde einen Ansatz vorschlagen, der hier nicht erwähnt wird, bei dem Sie beide CSS-Dateien in den HTML-Code aufnehmen, aber das CSS wird so aussehen

light.css

/*** light.css ***/

p.main{
   color: #222;
}

/*** other light CSS ***/

und dark.css wird wie sein

/*** dark.css ***/

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

/*** other dark CSS ***/

Grundsätzlich ist jeder Selektor in dark.css ein Kind von .dark_layout

Dann müssen Sie nur noch die Klasse der Körperelemente ändern, wenn jemand das Thema der Website ändert.

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

Und jetzt haben alle Ihre Elemente das dunkle CSS, sobald der Benutzer darauf klickt #changetheme. Dies ist sehr einfach, wenn Sie CSS-Präprozessoren verwenden.

Sie können auch CSS-Animationen für Hintergründe und Farben hinzufügen, wodurch der Übergang sehr reibungslos verläuft.

Leere
quelle
4

Mit jquery .attr () Sie können einstellen , href Ihr von Link - Tag .ie

Beispielcode

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

Vielleicht denke ich zu kompliziert, aber da die akzeptierte Antwort für mich nicht funktionierte, dachte ich, ich würde auch meine Lösung teilen.

Story:
Ich wollte verschiedene "Skins" meiner Seite als zusätzliche Stylesheets in den Kopf aufnehmen, die dem "Haupt" -Stil hinzugefügt wurden, und sie durch Drücken einer Schaltfläche auf der Seite wechseln (keine Browsereinstellungen oder ähnliches).

Problem:
Ich fand die Lösung von @ sam sehr elegant, aber sie hat bei mir überhaupt nicht funktioniert. Zumindest ein Teil des Problems besteht darin, dass ich eine Haupt-CSS-Datei verwende und nur andere als "Skins" hinzufüge. Daher musste ich die Dateien mit der fehlenden "title" -Eigenschaft gruppieren .

Folgendes habe ich mir ausgedacht.
Fügen Sie zuerst alle "Skins" mit "Alternate" zum Kopf hinzu:

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

Beachten Sie, dass ich der CSS-Hauptdatei den Titel = 'main' gegeben habe und alle anderen eine class = 'style-skin' und keinen Titel haben.

Zum Wechseln der Skins verwende ich jQuery. Ich überlasse es den Puristen, eine elegante VanillaJS-Version zu finden:

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

Es durchläuft alle verfügbaren Skins, nimmt die (bald) aktive, setzt den Titel auf "main" und aktiviert ihn. Alle anderen Skins sind deaktiviert und der Titel wird entfernt.

Fließen
quelle
0

Aktualisieren Sie einfach Ihr Linkhref-Attribut in Ihrer neuen CSS-Datei.

function setStyleSheet(fileName){
       document.getElementById("WhatEverYouAssignIdToStyleSheet").setAttribute('href', fileName);
    }
Hanzla Habib
quelle