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?
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?
Risposte:
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 innerHTML
proprietà 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
innerHTML
per gli <style>
elementi (e <script>
).
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);
});
}
var links = document.getElementsByTagName("link"); for (var i = 0; i < links.length;i++) { var link = links[i]; if (link.rel === "stylesheet") {link.href += "?"; }}
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 += "";
}
}
Dai un'occhiata allo sgargiante progetto Vogue di Andrew Davey - http://aboutcode.net/vogue/
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())
}
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>');
};
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:
Che cosa fa?
Ricarica CSS aggiungendo i parametri della stringa di query (come soluzioni sopra):
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=">
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)();
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
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'">
rel="reload"
ma l'esempio dice rel="preload"
.
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);
}