Gibt es eine einfache Möglichkeit, CSS neu zu laden, ohne die Seite neu zu laden?

88

Ich versuche, einen Live-In-Page-CSS-Editor mit einer Vorschaufunktion zu erstellen, mit der das Stylesheet neu geladen und angewendet werden kann, ohne dass die Seite neu geladen werden muss. Was wäre der beste Weg, dies zu tun?

Stephen Belanger
quelle
1
2014 und diese Frage ist auf der Homepage ...
Kroltan
2019, fast 2020, und diese Frage
taucht

Antworten:

51

<link>Schreiben Sie auf der Seite "Bearbeiten", anstatt Ihr CSS wie gewohnt (mit einem Tag) einzuschließen, alles in ein <style>Tag. Durch Bearbeiten der innerHTMLEigenschaft wird die Seite automatisch aktualisiert, auch ohne einen Roundtrip zum Server.

<style type="text/css" id="styles">
    p {
        color: #f0f;
    }
</style>

<textarea id="editor"></textarea>
<button id="preview">Preview</button>

Das Javascript mit jQuery:

jQuery(function($) {
    var $ed = $('#editor')
      , $style = $('#styles')
      , $button = $('#preview')
    ;
    $ed.val($style.html());
    $button.click(function() {
        $style.html($ed.val());
        return false;
    });
});

Und das sollte es sein!

Wenn Sie wirklich ausgefallen sein möchten, hängen Sie die Funktion an den Keydown im Textbereich an, obwohl Sie möglicherweise unerwünschte Nebenwirkungen haben (die Seite ändert sich während der Eingabe ständig).

Bearbeiten : getestet und funktioniert (zumindest in Firefox 3.5, sollte aber mit anderen Browsern in Ordnung sein). Siehe Demo hier: http://jsbin.com/owapi

nickf
quelle
3
IE-Barfs innerHTMLfür <style>Elemente (und <script>).
JPot
3
Was ist, wenn es href'ed ist?
Allenhwkim
Übrigens können Sie dem Keydown im Textbereich eine Funktion hinzufügen, diese aber beispielsweise mit einem Bindestrich drosseln .
Camilo Martin
109

Möglicherweise nicht zutreffend für Ihre Situation, aber hier ist die jQuery-Funktion, die ich zum Neuladen externer Stylesheets verwende:

/**
 * Forces a reload of all stylesheets by appending a unique query string
 * to each stylesheet URL.
 */
function reloadStylesheets() {
    var queryString = '?reload=' + new Date().getTime();
    $('link[rel="stylesheet"]').each(function () {
        this.href = this.href.replace(/\?.*|$/, queryString);
    });
}
Harto
quelle
3
Sie können es mit ted.mielczarek.org/code/mozilla/bookmarklet.html
Luke Stanley
36
Dieser nicht-jquery Einzeiler arbeitet für mich in Chrom:var links = document.getElementsByTagName("link"); for (var i = 0; i < links.length;i++) { var link = links[i]; if (link.rel === "stylesheet") {link.href += "?"; }}
Claude
Ich bin nicht sicher, ob es daran liegt, dass ich gerade die Seite auf Chrome von der Festplatte öffne, aber das funktioniert bei mir nicht.
Joao Carlos
13

Es ist absolut nicht erforderlich, jQuery dafür zu verwenden. Die folgende JavaScript-Funktion lädt alle Ihre CSS-Dateien neu:

function reloadCss()
{
    var links = document.getElementsByTagName("link");
    for (var cl in links)
    {
        var link = links[cl];
        if (link.rel === "stylesheet")
            link.href += "";
    }
}
Dan Bray
quelle
1
Ich verwende dies in der Konsole, damit ich meinem Code nichts anderes hinzufügen muss
loco.loop
@Bram die geschweifte Klammer ist optional. Der Code funktioniert gut.
Dan Bray
1
Tolle Antwort, da es nicht auf jQuery beruht! :)
Gustavo Straube
9

Schauen Sie sich Andrew Daveys schickes Vogue-Projekt an - http://aboutcode.net/vogue/

mcintyre321
quelle
Genau das habe ich gesucht. Das CSS wird neu geladen, sobald das Stylesheet geändert wird, ohne dass die Seite manuell aktualisiert werden muss. Vielen Dank für das Teilen :)
Devner
Kann Vogue lokal auf Wamp betrieben werden?
Chrisdillon
Ich habe versucht, ein Skript neu zu laden, wie Vogue. In Chrome ist dies jedoch ein Problem, da die neuesten Stylesheet-Dateien im Browser verbleiben und funktionieren. Zum Beispiel ändere ich in einem Element den Hintergrund von Rot nach Weiß und muss die letzte Farbe Rot deaktivieren.
Peter
7

Eine kürzere Version in Vanilla JS und in einer Zeile:

for (var link of document.querySelectorAll("link[rel=stylesheet]")) link.href = link.href.replace(/\?.*|$/, "?" + Date.now())

Oder erweitert:

for (var link of document.querySelectorAll("link[rel=stylesheet]")) {
  link.href = link.href.replace(/\?.*|$/, "?" + Date.now())
}
flori
quelle
6

Noch eine jQuery-Lösung

Versuchen Sie für ein einzelnes Stylesheet mit der ID "css" Folgendes:

$('#css').replaceWith('<link id="css" rel="stylesheet" href="css/main.css?t=' + Date.now() + '"></link>');

Schließen Sie es in eine Funktion mit globalem Umfang ein, und Sie können es über die Entwicklerkonsole in Chrome oder Firebug in Firefox verwenden:

var reloadCSS = function() {
  $('#css').replaceWith('<link id="css" rel="stylesheet" href="css/main.css?t=' + Date.now() + '"></link>');
};
mattdlockyer
quelle
1
Hallo, ich habe diese, die einige, wie nur funktioniert :( obwohl ich die Zeit hinzugefügt habe, um es einzigartig zu machen (dies ist auf Firefox): <code> Funktion swapStyleSheet (Blatt) {var sheet = Blatt + '? t =' + Date.now (); $ ('# pagestyle'). ReplaceWith ('<link id = "css" rel = "stylesheet" href = "' + sheet + '"> </ link>');} $ (" # stylesheet1 "). on (" click ", function (event) {swapStyleSheet (" <c: url value = 'site.css' /> ");}); $ (" # stylesheet2 "). on (" click ", function (event) {swapStyleSheet (" <c: url value = 'site2.css' /> ");}); </ code>
tibi
3

Basierend auf früheren Lösungen habe ich ein Lesezeichen mit JavaScript-Code erstellt:

javascript: { var toAppend = "trvhpqi=" + (new Date()).getTime(); var links = document.getElementsByTagName("link"); for (var i = 0; i < links.length;i++) { var link = links[i]; if (link.rel === "stylesheet") { if (link.href.indexOf("?") === -1) { link.href += "?" + toAppend; } else { if (link.href.indexOf("trvhpqi") === -1) { link.href += "&" + toAppend; } else { link.href = link.href.replace(/trvhpqi=\d{13}/, toAppend)} }; } } }; void(0);

Bild von Firefox:

Geben Sie hier die Bildbeschreibung ein

Was tut es?

CSS wird neu geladen, indem Abfragezeichenfolgenparameter hinzugefügt werden (wie oben beschrieben):

LukLed
quelle
0

Ja, laden Sie das CSS-Tag neu. Denken Sie auch daran, die neue URL eindeutig zu machen (normalerweise durch Anhängen eines zufälligen Abfrageparameters). Ich habe Code, um dies zu tun, aber momentan nicht bei mir. Wird später bearbeitet ...

edit: zu spät ... harto und nickf haben mich geschlagen ;-)

Slebetman
quelle
0

Ich habe jetzt das:

    function swapStyleSheet() {
        var old = $('#pagestyle').attr('href');
        var newCss = $('#changeCss').attr('href');
        var sheet = newCss +Math.random(0,10);
        $('#pagestyle').attr('href',sheet);
        $('#profile').attr('href',old);
        }
    $("#changeCss").on("click", function(event) { 
        swapStyleSheet();
    } );

Erstellen Sie ein Element auf Ihrer Seite mit der ID changeCss mit einem href-Attribut mit der neuen CSS-URL. und ein Linkelement mit dem Start-CSS:

<link id="pagestyle" rel="stylesheet" type="text/css" href="css1.css?t=" />

<img src="click.jpg" id="changeCss" href="css2.css?t=">
Tibi
quelle
0

Eine andere Antwort: Es gibt ein Lesezeichen namens ReCSS . Ich habe es nicht ausgiebig benutzt, scheint aber zu funktionieren.

Auf dieser Seite befindet sich ein Lesezeichen, das Sie per Drag & Drop in Ihre Adressleiste ziehen können (hier kann anscheinend kein Lesezeichen erstellt werden). Falls das kaputt ist, hier ist der Code:

javascript:void(function()%7Bvar%20i,a,s;a=document.getElementsByTagName('link');for(i=0;i%3Ca.length;i++)%7Bs=a[i];if(s.rel.toLowerCase().indexOf('stylesheet')%3E=0&&s.href)%20%7Bvar%20h=s.href.replace(/(&%7C%5C?)forceReload=%5Cd%20/,'');s.href=h%20(h.indexOf('?')%3E=0?'&':'?')%20'forceReload='%20(new%20Date().valueOf())%7D%7D%7D)();
Christopher Schneider
quelle
0

einfach, wenn Sie PHP verwenden Fügen Sie einfach die aktuelle Zeit am Ende des CSS wie

<link href="css/name.css?<?php echo 
time(); ?>" rel="stylesheet">

Jedes Mal, wenn Sie neu laden, was auch immer es ist, ändert sich die Zeit und der Browser denkt, dass es sich um eine andere Datei handelt, da sich das letzte Bit ständig ändert. Sie können dies für jede Datei tun und den Browser zwingen, immer mit der gewünschten Skriptsprache zu aktualisieren

Asiimwedismas
quelle
0

Auf einfache Weise können Sie rel = "Preload" anstelle von rel = "Stylesheet" verwenden .

<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">
Gagan
quelle
Sie sagten zu verwenden, rel="reload"aber das Beispiel sagt rel="preload".
Haykam
Danke @haykam für die Korrektur, ich habe es aktualisiert.
Gagan
0

Da diese Frage 2019 im Stackoverflow angezeigt wurde, möchte ich meinen Beitrag mit einem moderneren JavaScript hinzufügen.

Speziell für CSS-Stylesheets, die nicht inline sind - da dies irgendwie bereits von der ursprünglichen Frage abgedeckt ist.

Beachten Sie zunächst, dass wir immer noch keine konstruierbaren Stylesheet-Objekte haben. Wir hoffen jedoch, dass sie bald gelandet sind.

In der Zwischenzeit wird folgender HTML-Inhalt angenommen:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link id="theme" rel="stylesheet" type="text/css" href="./index.css" />
    <script src="./index.js"></script>
  </head>
  <body>
    <p>Hello World</p>
    <button onclick="reload('theme')">Reload</button>
  </body>
</html>

Wir könnten haben in index.js:

// Utility function to generate a promise that is 
// resolved when the `target` resource is loaded,
// and rejected if it fails to load.
//
const load = target =>
  new Promise((rs, rj) => {
    target.addEventListener("load", rs, { once: true });
    target.addEventListener(
      "error",
      rj.bind(null, `Can't load ${target.href}`),
      { once: true }
    );
  });


// Here the reload function called by the button.
// It takes an `id` of the stylesheet that needs to be reloaded
async function reload(id) {
  const link = document.getElementById(id);

  if (!link || !link.href) {
    throw new Error(`Can't reload '${id}', element or href attribute missing.`);
  }

  // Here the relevant part.
  // We're fetching the stylesheet from the server, specifying `reload`
  // as cache setting, since that is our intention.
  // With `reload`, the browser fetches the resource *without* first looking
  // in the cache, but then will update the cache with the downloaded resource.
  // So any other pages that request the same file and hit the cache first,
  // will use the updated version instead of the old ones.
  let response = await fetch(link.href, { cache: "reload" });

  // Once we fetched the stylesheet and replaced in the cache,
  // We want also to replace it in the document, so we're
  // creating a URL from the response's blob:
  let url = await URL.createObjectURL(await response.blob());

  // Then, we create another `<link>` element to display the updated style,
  // linked to the original one; but only if we didn't create previously:
  let updated = document.querySelector(`[data-link-id=${id}]`);

  if (!updated) {
    updated = document.createElement("link");
    updated.rel = "stylesheet";
    updated.type = "text/css";
    updated.dataset.linkId = id;
    link.parentElement.insertBefore(updated, link);

    // At this point we disable the original stylesheet,
    // so it won't be applied to the document anymore.
    link.disabled = true;
  }

  // We set the new <link> href...
  updated.href = url;

  // ...Waiting that is loaded...
  await load(updated);

  // ...and finally tell to the browser that we don't need
  // the blob's URL anymore, so it can be released.
  URL.revokeObjectURL(url);
}
ZER0
quelle