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?
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?
Respostas:
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 innerHTML
propriedade 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
innerHTML
para <style>
elementos (e <script>
).
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);
});
}
var links = document.getElementsByTagName("link"); for (var i = 0; i < links.length;i++) { var link = links[i]; if (link.rel === "stylesheet") {link.href += "?"; }}
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 += "";
}
}
Confira o projeto snazzy da Vogue de Andrew Davey - http://aboutcode.net/vogue/
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())
}
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>');
};
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:
O que isso faz?
Ele recarrega o CSS adicionando parâmetros de string de consulta (como soluções acima):
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=">
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)();
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
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'">
rel="reload"
mas o exemplo diz rel="preload"
.
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);
}