Existe uma maneira fácil de recarregar o css sem recarregar a página?

88

Estou tentando fazer um editor de css in-page ao vivo com uma função de visualização que recarregaria a folha de estilo e aplicaria sem precisar recarregar a página. Qual seria a melhor maneira de fazer isso?

Stephen Belanger
fonte
1
2014 e esta pergunta está na página inicial ...
Kroltan
2019, quase 2020, e esta questão ainda está aparecendo na página inicial ...
ZER0

Respostas:

51

Na página "editar", em vez de incluir seu CSS da maneira normal (com uma <link>tag), escreva tudo em uma <style>tag. A edição da innerHTMLpropriedade de que atualizará automaticamente a página, mesmo sem uma viagem de ida e volta para o servidor.

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

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

O Javascript, usando jQuery:

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

E deve ser isso!

Se você quiser ser realmente sofisticado, anexe a função à tecla pressionada na área de texto, embora você possa obter alguns efeitos colaterais indesejados (a página mudaria constantemente enquanto você digita)

Editar : testado e funciona (no Firefox 3.5, pelo menos, embora deva funcionar em outros navegadores). Veja a demonstração aqui: http://jsbin.com/owapi

nickf
fonte
3
IE no barfs innerHTMLpara <style>elementos (e <script>).
JPot
3
e se for href'ed?
allenhwkim
A propósito, você pode anexar uma função à tecla pressionada na área de texto, mas acelerá-la com lo-traço (por exemplo).
Camilo Martin
109

Possivelmente não se aplica à sua situação, mas aqui está a função jQuery que uso para recarregar folhas de estilo externas:

/**
 * 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
fonte
3
Você pode torná-lo um favorito usando ted.mielczarek.org/code/mozilla/bookmarklet.html
Luke Stanley
36
Este one-liner não jquery funciona para mim no 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
Não tenho certeza se é porque estou apenas abrindo a página no Chrome do disco, mas isso não está funcionando para mim.
João Carlos
14

Não há absolutamente nenhuma necessidade de usar jQuery para isso. A seguinte função JavaScript recarregará todos os seus arquivos 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
fonte
1
Estou usando isso no console, então não preciso adicionar mais nada no meu código
loco.loop
@Bram a chave é opcional. O código funciona bem.
Dan Bray
1
Ótima resposta, pois não depende do jQuery! :)
Gustavo Straube
9

Confira o projeto snazzy da Vogue de Andrew Davey - http://aboutcode.net/vogue/

mcintyre321
fonte
Isso é exatamente o que venho procurando. Ele recarrega o CSS assim que a folha de estilo é alterada, sem a necessidade de atualizar a página manualmente. Muito obrigado por compartilhar :)
Devner
A Vogue pode ser executada localmente no wamp?
chrisdillon
Tentei recarregar o script, como a Vogue. Mas no Chrome é problema, porque os arquivos de folha de estilo mais antigos permanecem no navegador e funcionando. Por exemplo, em um elemento eu mudo o backround de vermelho para branco e devo desativar a última cor vermelha.
Peter
7

Uma versão mais curta em Vanilla JS e em uma linha:

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

Ou expandido:

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

Mais uma solução jQuery

Para uma única folha de estilo com id "css", tente o seguinte:

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

Envolva-o em uma função que possui scrope global e você pode usá-lo no console do desenvolvedor no Chrome ou Firebug no Firefox:

var reloadCSS = function() {
  $('#css').replaceWith('<link id="css" rel="stylesheet" href="css/main.css?t=' + Date.now() + '"></link>');
};
Mattdlockyer
fonte
1
oi, eu tenho isso, que de alguma forma só funciona :( embora eu tenha o tempo adicionado para torná-lo único (isso está no 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 (" click ", function (event) {swapStyleSheet (" <c: url value = 'site2.css' /> ");}); </code>
tibi
3

Com base em soluções anteriores, criei um favorito com código 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);

Imagem do Firefox:

insira a descrição da imagem aqui

O que isso faz?

Ele recarrega o CSS adicionando parâmetros de string de consulta (como soluções acima):

LukLed
fonte
0

Sim, recarregue a tag css. E lembre-se de tornar o novo url exclusivo (geralmente anexando um parâmetro de consulta aleatório). Eu tenho um código para fazer isso, mas não comigo agora. Editarei mais tarde ...

editar: tarde demais ... harto e nickf chegaram antes de mim ;-)

slebetman
fonte
0

agora eu tenho isso:

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

faça qualquer elemento em sua página com id changeCss com um atributo href com o novo url css nele. e um elemento de link com o css inicial:

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

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

Outra resposta: há um bookmarklet chamado ReCSS . Eu não usei muito, mas parece funcionar.

Há um bookmarklet nessa página para arrastar e soltar em sua barra de endereço (não consigo fazer um aqui). Caso esteja quebrado, aqui está o código:

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
fonte
0

simples se você estiver usando php Basta acrescentar a hora atual no final do css como

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

Agora, toda vez que você recarrega o que quer que seja, o tempo muda e o navegador pensa que é um arquivo diferente, já que o último bit continua mudando ... Você pode fazer isso para qualquer arquivo e forçar o navegador a sempre atualizar usando a linguagem de script que você quiser

asiimwedismas
fonte
0

De maneira simples, você pode usar rel = "preload" em vez de rel = "stylesheet" .

<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">
Gagan
fonte
Você disse para usar, rel="reload"mas o exemplo diz rel="preload".
haykam
Obrigado @haykam por me corrigir, eu atualizei.
Gagan
0

Como essa pergunta foi mostrada no stackoverflow em 2019, gostaria de adicionar minha contribuição usando um JavaScript mais moderno.

Especificamente, para folhas de estilo CSS que não são embutidas - uma vez que já foi abordado na questão original, de alguma forma.

Em primeiro lugar, observe que ainda não temos objetos de folha de estilo construtíveis. No entanto, esperamos que eles sejam desembarcados em breve.

Nesse ínterim, presumindo o seguinte conteúdo 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>

Poderíamos ter, em 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
fonte