Existe-t-il un moyen simple de recharger le CSS sans recharger la page?

90

J'essaie de créer un éditeur css en direct sur la page avec une fonction de prévisualisation qui rechargerait la feuille de style et l'appliquerait sans avoir besoin de recharger la page. Quelle serait la meilleure façon de procéder?

Stephen Bélanger
la source
1
2014 et cette question est sur la page d'accueil ...
Kroltan
1
2019, presque 2020, et cette question
surgit

Réponses:

51

Sur la page "modifier", au lieu d'inclure votre CSS de la manière habituelle (avec une <link>balise), écrivez le tout dans une <style>balise. La modification de la innerHTMLpropriété de qui mettra automatiquement à jour la page, même sans aller-retour vers le serveur.

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

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

Le Javascript, en utilisant jQuery:

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

Et ça devrait être ça!

Si vous vouliez être vraiment sophistiqué, attachez la fonction au clavier de la zone de texte, bien que vous puissiez obtenir des effets secondaires indésirables (la page changerait constamment à mesure que vous tapez)

Edit : testé et fonctionne (dans Firefox 3.5, au moins, mais devrait être bien avec d'autres navigateurs). Voir la démo ici: http://jsbin.com/owapi

nickf
la source
3
IE barfs sur innerHTMLpour les <style>éléments (et <script>).
JPot
3
et si c'est href'ed?
allenhwkim
Btw, vous pouvez attacher une fonction à la touche enfoncée sur la zone de texte mais l' étrangler avec lo-dash (par exemple).
Camilo Martin
109

Peut-être pas applicable à votre situation, mais voici la fonction jQuery que j'utilise pour recharger des feuilles de style externes:

/**
 * 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
la source
3
Vous pouvez en faire un signet en utilisant ted.mielczarek.org/code/mozilla/bookmarklet.html
Luke Stanley
36
Ce one-liner non-jquery fonctionne pour moi en 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
Je ne sais pas si c'est parce que je viens d'ouvrir la page sur Chrome à partir du disque, mais cela ne fonctionne pas pour moi.
Joao Carlos
14

Il n'est absolument pas nécessaire d'utiliser jQuery pour cela. La fonction JavaScript suivante rechargera tous vos fichiers CSS:

function reloadCss()
{
    var links = document.getElementsByTagName("link");
    for (var cl in links)
    {
        var link = links[cl];
        if (link.rel === "stylesheet")
            link.href += "";
    }
}
Dan Bray
la source
1
J'utilise ceci dans la console donc je n'ai pas besoin d'ajouter quoi que ce soit d'autre dans mon code
loco.loop
@Bram l'accolade est facultative. Le code fonctionne bien.
Dan Bray
1
Excellente réponse car elle ne repose pas sur jQuery! :)
Gustavo Straube
9

Découvrez le projet chic Vogue d'Andrew Davey - http://aboutcode.net/vogue/

mcintyre321
la source
C'est exactement ce que je cherchais. Il recharge le CSS dès que la feuille de style est modifiée, sans qu'il soit nécessaire de rafraîchir manuellement la page. Merci beaucoup pour le partage :)
Devner
Vogue peut-il être exécuté localement sur wamp?
chrisdillon
J'ai essayé de recharger le script, comme Vogue. Mais dans Chrome, c'est un problème, car les fichiers de feuille de style les plus anciens restent dans le navigateur et fonctionnent. Par exemple, dans un élément, je change le fond du rouge au blanc, et je dois désactiver la dernière couleur rouge.
Peter
7

Une version plus courte en Vanilla JS et en une ligne:

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

Ou élargi:

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

Encore une solution jQuery

Pour une seule feuille de style avec l'ID "css", essayez ceci:

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

Enveloppez-le dans une fonction qui a un scrope global et vous pouvez l'utiliser à partir de la Developer Console dans Chrome ou Firebug dans Firefox:

var reloadCSS = function() {
  $('#css').replaceWith('<link id="css" rel="stylesheet" href="css/main.css?t=' + Date.now() + '"></link>');
};
mattdlockyer
la source
1
salut, j'ai ceci, dont certains ne fonctionnent que ceux: (même si j'ai le temps supplémentaire pour le rendre unique (c'est sur Firefox): <code> function swapStyleSheet (feuille) {var sheet = sheet + '? t =' + Date.now (); $ ('# pagestyle'). ReplaceWith ('<link id = "css" rel = "styleheet" 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

Sur la base de solutions précédentes, j'ai créé un signet avec du code 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);

Image de Firefox:

entrez la description de l'image ici

Qu'est ce que ça fait?

Il recharge le CSS en ajoutant des paramètres de chaîne de requête (comme solutions ci-dessus):

LukLed
la source
0

Oui, rechargez la balise css. Et n'oubliez pas de rendre la nouvelle URL unique (généralement en ajoutant un paramètre de requête aléatoire). J'ai du code pour le faire mais pas avec moi pour le moment. Éditera plus tard ...

edit: trop tard ... harto et nickf m'ont battu ;-)

dormeur
la source
0

j'ai maintenant ceci:

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

créez n'importe quel élément de votre page avec l'id changeCss avec un attribut href contenant la nouvelle URL css. et un élément de lien avec le css de départ:

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

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

Une autre réponse: il existe un bookmarklet appelé ReCSS . Je ne l'ai pas beaucoup utilisé, mais semble fonctionner.

Il y a un bookmarklet sur cette page à glisser-déposer sur votre barre d'adresse (je n'arrive pas à en créer un ici). En cas de panne, voici le 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
la source
0

simple si vous utilisez php Ajoutez simplement l'heure actuelle à la fin du css comme

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

Alors maintenant, à chaque fois que vous rechargez quoi que ce soit, l'heure change et le navigateur pense que c'est un fichier différent puisque le dernier bit ne cesse de changer ...

asiimwedismas
la source
0

De manière simple, vous pouvez utiliser rel = "preload" au lieu de rel = "stylesheet" .

<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">
Gagan
la source
Vous avez dit d'utiliser rel="reload"mais l'exemple dit rel="preload".
haykam
Merci @haykam de m'avoir corrigé, je l'ai mis à jour.
Gagan
0

Étant donné que cette question a été affichée dans le stackoverflow en 2019, j'aimerais ajouter ma contribution en utilisant un JavaScript plus moderne.

Plus précisément, pour les feuilles de style CSS qui ne sont pas en ligne - car cela est déjà couvert par la question d'origine, d'une manière ou d'une autre.

Tout d'abord, notez que nous n'avons toujours pas d'objets de feuille de style constructibles. Cependant, nous espérons les avoir débarqués bientôt.

En attendant, en supposant le contenu HTML suivant:

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

On aurait pu, en 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
la source