C'è un modo semplice per ricaricare CSS senza ricaricare la pagina?


90

Sto cercando di creare un editor CSS live in-page con una funzione di anteprima che ricarichi il foglio di stile e lo applichi senza dover ricaricare la pagina. Quale sarebbe il modo migliore per farlo?


1
2014 e questa domanda è sulla home page ...
Kroltan

1
2019, quasi 2020, e questa domanda
appare

Risposte:


51

Nella pagina "modifica", invece di includere il tuo CSS nel modo normale (con un <link>tag), scrivi tutto in un <style>tag. La modifica della innerHTMLproprietà di ciò aggiornerà automaticamente la pagina, anche senza un viaggio di andata e ritorno al server.

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

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

Il Javascript, utilizzando jQuery:

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

E questo dovrebbe essere tutto!

Se vuoi essere davvero stravagante, collega la funzione al tasto giù nell'area di testo, anche se potresti ottenere alcuni effetti collaterali indesiderati (la pagina cambierebbe costantemente durante la digitazione)

Modifica : testato e funziona (almeno in Firefox 3.5, anche se dovrebbe andare bene con altri browser). Guarda la demo qui: http://jsbin.com/owapi


3
IE barf su innerHTMLper gli <style>elementi (e <script>).
JPot

3
cosa succede se è href'ed?
allenhwkim

A proposito, puoi allegare una funzione al keydown nella textarea ma limitarla con lo-dash (ad esempio).
Camilo Martin

109

Forse non applicabile alla tua situazione, ma ecco la funzione jQuery che uso per ricaricare fogli di stile esterni:

/**
 * 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);
    });
}

3
Puoi renderlo un segnalibro usando ted.mielczarek.org/code/mozilla/bookmarklet.html
Luke Stanley

36
Questo one-liner non jquery funziona per me in chrome:var links = document.getElementsByTagName("link"); for (var i = 0; i < links.length;i++) { var link = links[i]; if (link.rel === "stylesheet") {link.href += "?"; }}
Claude

Non sono sicuro che sia perché sto solo aprendo la pagina su Chrome dal disco, ma questo non funziona per me.
Joao Carlos

14

Non è assolutamente necessario utilizzare jQuery per questo. La seguente funzione JavaScript ricaricherà tutti i tuoi file CSS:

function reloadCss()
{
    var links = document.getElementsByTagName("link");
    for (var cl in links)
    {
        var link = links[cl];
        if (link.rel === "stylesheet")
            link.href += "";
    }
}

1
Lo sto usando nella console quindi non ho bisogno di aggiungere altro nel mio codice
loco.loop

@Bram la parentesi graffa è facoltativa. Il codice funziona bene.
Dan Bray

1
Ottima risposta poiché non si basa su jQuery! :)
Gustavo Straube

9

Dai un'occhiata allo sgargiante progetto Vogue di Andrew Davey - http://aboutcode.net/vogue/


Questo è esattamente quello che stavo cercando. Ricarica il CSS non appena il foglio di stile viene modificato, senza la necessità di aggiornare manualmente la pagina. Grazie
mille

Vogue può essere gestito localmente su wamp?
Chrisdillon

Ho provato a ricaricare lo script, come Vogue. Ma in Chrome è un problema, perché i file del foglio di stile più vecchi rimangono nel browser e funzionano. Ad esempio, in un elemento cambio lo sfondo da rosso a bianco e devo disabilitare l'ultimo colore rosso.
Peter

7

Una versione più breve in Vanilla JS e in una riga:

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

O espanso:

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

6

Un'altra soluzione jQuery

Per un singolo foglio di stile con ID "css" prova questo:

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

Avvolgilo in una funzione con scrope globale e puoi usarlo dalla Console per gli sviluppatori in Chrome o Firebug in Firefox:

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

1
ciao, ho questo, che in qualche modo funziona solo quelli :( anche se ho aggiunto il tempo per renderlo unico (questo è su firefox): <code> function swapStyleSheet (sheet) {var sheet = sheet + '? 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 (" clic ", function (event) {swapStyleSheet (" <c: url value = 'site2.css' /> ");}); </code>
tibi

3

Sulla base delle soluzioni precedenti, ho creato un segnalibro con codice JavaScript:

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

Immagine da Firefox:

inserisci qui la descrizione dell'immagine

Che cosa fa?

Ricarica CSS aggiungendo i parametri della stringa di query (come soluzioni sopra):


0

Sì, ricarica il tag css. E ricorda di rendere unico il nuovo URL (di solito aggiungendo un parametro di query casuale). Ho il codice per farlo ma non con me adesso. Modificherà più tardi ...

modifica: troppo tardi ... harto e nickf mi hanno battuto ;-)


0

ora ho questo:

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

crea qualsiasi elemento nella tua pagina con id changeCss con un attributo href con il nuovo URL css in esso. e un elemento di collegamento con il css iniziale:

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

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

0

Un'altra risposta: c'è un bookmarklet chiamato ReCSS . Non l'ho usato ampiamente, ma sembra funzionare.

C'è un bookmarklet in quella pagina da trascinare e rilasciare sulla barra degli indirizzi (non riesco a crearne uno qui). Nel caso in cui sia rotto, ecco il codice:

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)();

0

semplice se stai usando php Basta aggiungere l'ora corrente alla fine del css come

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

Quindi ora ogni volta che ricarichi qualunque cosa sia, l'ora cambia e il browser pensa che sia un file diverso poiché l'ultimo bit continua a cambiare .... Puoi farlo per qualsiasi file e costringere il browser ad aggiornarsi sempre usando qualsiasi linguaggio di scripting desideri


0

In un modo semplice puoi usare rel = "preload" invece di rel = "stylesheet" .

<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">

Hai detto di usare rel="reload"ma l'esempio dice rel="preload".
haykam

Grazie @haykam per avermi corretto, l'ho aggiornato.
Gagan

0

Poiché questa domanda è stata mostrata nello stackoverflow nel 2019, vorrei aggiungere il mio contributo utilizzando un JavaScript più moderno.

In particolare, per i fogli di stile CSS che non sono in linea, poiché in qualche modo è già coperto dalla domanda originale.

Prima di tutto, nota che ancora non abbiamo oggetti del foglio di stile costruibili. Tuttavia, speriamo di averli atterrati presto.

Nel frattempo, assumendo il seguente contenuto HTML:

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

Potremmo avere, 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);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.