有没有一种简单的方法可以重新加载 css 而不用重新加载页面?

我正在尝试制作一个活的,页面内的 CSS 编辑器与预览功能,将重新加载样式表,并应用它而不需要重新加载页面。最好的办法是什么?

146378 次浏览

Yes, reload the css tag. And remember to make the new url unique (usually by appending a random query parameter). I have code to do this but not with me right now. Will edit later...

edit: too late... harto and nickf beat me to it ;-)

On the "edit" page, instead of including your CSS in the normal way (with a <link> tag), write it all to a <style> tag. Editing the innerHTML property of that will automatically update the page, even without a round-trip to the server.

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


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

The Javascript, using jQuery:

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

And that should be it!

If you wanted to be really fancy, attach the function to the keydown on the textarea, though you could get some unwanted side-effects (the page would be changing constantly as you type)

Edit: tested and works (in Firefox 3.5, at least, though should be fine with other browsers). See demo here: http://jsbin.com/owapi

Possibly not applicable for your situation, but here's the jQuery function I use for reloading external stylesheets:

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

Check out Andrew Davey's snazzy Vogue project - http://aboutcode.net/vogue/

One more jQuery solution

For a single stylesheet with id "css" try this:

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

Wrap it in a function that has global scrope and you can use it from the Developer Console in Chrome or Firebug in Firefox:

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

Based on previous solutions, I have created bookmark with JavaScript code:

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 from Firefox:

enter image description here

What does it do?

It reloads CSS by adding query string params (as solutions above):

i now have this:

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

make any element in your page with id changeCss with a href attribute with the new css url in it. and a link element with the starting css:

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


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

Another answer: There's a bookmarklet called ReCSS. I haven't used it extensively, but seems to work.

There's a bookmarklet on that page to drag and drop onto your address bar (Can't seem to make one here). In case that's broke, here's the 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)();

There is absolutely no need to use jQuery for this. The following JavaScript function will reload all your CSS files:

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

A shorter version in Vanilla JS and in one line:

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

Or expanded:

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

In a simple manner you can use rel="preload" instead of rel="stylesheet" .

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

simple if u are using php Just append the current time at the end of the css like

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

So now everytime u reload whatever it is , the time changes and browser thinks its a different file since the last bit keeps changing.... U can do this for any file u force the browser to always refresh using whatever scripting language u want

Since this question was shown in the stackoverflow in 2019, I'd like to add my contribution using a more modern JavaScript.

Specifically, for CSS Stylesheet that are not inline – since that is already covered from the original question, somehow.

First of all, notice that we still don't have Constructable Stylesheet Objects. However, we hope to have them landed soon.

In the meantime, assuming the following HTML content:

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


We could have, 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);
}