有没有一种简单的方法可以在不重新加载页面的情况下重新加载CSS?

发布于 2024-08-16 19:51:13 字数 79 浏览 6 评论 0原文

我正在尝试制作一个带有预览功能的实时页内 css 编辑器,该编辑器可以重新加载样式表并应用它,而无需重新加载页面。解决这个问题的最佳方法是什么?

I'm trying to make a live, in-page css editor with a preview function that would reload the stylesheet and apply it without needing to reload the page. What would be the best way to go about this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

心清如水 2024-08-23 19:51:13

可能不适用于您的情况,但这是我用于重新加载外部样式表的 jQuery 函数:

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

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);
    });
}
属性 2024-08-23 19:51:13

在“编辑”页面上,不要以正常方式包含 CSS(使用 标记),而是将其全部写入

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

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

Javascript,使用 jQuery:

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

应该就是这样了!

如果您想要真正的奇特,请将该功能附加到文本区域的按键上,尽管您可能会得到一些不需要的副作用(页面会在您键入时不断变化)

编辑:经过测试并且有效(至少在 Firefox 3.5 中是这样,但其他浏览器应该没问题)。请参阅此处的演示:http://jsbin.com/owapi

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

俏︾媚 2024-08-23 19:51:13

完全没有必要为此使用 jQuery。以下 JavaScript 函数将重新加载所有 CSS 文件:

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

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 += "";
    }
}
情深如许 2024-08-23 19:51:13

Vanilla JS 中的一个较短版本,一行:

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

它循环遍历所有样式表链接,并将时间戳附加(或更新)到 URL。

A shorter version in Vanilla JS and in one line:

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

It loops trough all stylesheet links and appends (or updates) a timestamp to the URL.

终止放荡 2024-08-23 19:51:13

查看 Andrew Davey 的时尚 Vogue 项目 - http://aboutcode.net/vogue/

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

甜味超标? 2024-08-23 19:51:13

另一种 jQuery 解决方案

对于 id 为“css”的单个样式表,请尝试以下操作:

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

将其包装在具有全局作用域的函数中,您可以从 Chrome 中的开发者控制台或 Firefox 中的 Firebug 使用它:

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

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>');
};
樱花落人离去 2024-08-23 19:51:13

基于以前的解决方案,我使用 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);

来自 Firefox 的图像:

在此处输入图像描述

它有什么作用?

它通过添加查询字符串参数来重新加载 CSS(如上面的解决方案):

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):

鹿港巷口少年归 2024-08-23 19:51:13

由于这个问题在 2019 年的 stackoverflow 中出现过,我想使用更现代的 JavaScript 来添加我的贡献。

具体来说,对于非内联的 CSS 样式表 - 因为这已经在原始问题中以某种方式涵盖了。

首先,请注意,我们仍然没有可构造样式表对象。不过,我们希望它们能够尽快落地。

同时,假设有以下 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>

我们可以在 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);
}

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);
}
最美的太阳 2024-08-23 19:51:13

我现在有这个:

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

在页面中使用 id changeCss 制作任何元素,并使用 href 属性,其中包含新的 css url。和一个带有起始 css 的链接元素:

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

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

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=">
把梦留给海 2024-08-23 19:51:13

另一个答案:
有一个名为 ReCSS 的书签。我没有广泛使用它,但似乎有效。

该页面上有一个书签,可以拖放到地址栏上(这里似乎无法制作)。如果它坏了,代码如下:

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

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)();
陈年往事 2024-08-23 19:51:13

您可以以简单的方式使用 rel="preload" 而不是 rel="stylesheet"

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

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'">
玩物 2024-08-23 19:51:13

基于此页面上的 https://stackoverflow.com/a/59176853/3917091

function refreshStylesheets() {
  // In my case, I'm getting all urls on my site (mysite.dev).
  (document.querySelectorAll('link[rel="stylesheet"][href*="mysite.dev\/"],link[rel="stylesheet"][data-href*="mysite.dev\/"]') || []).forEach(async link => {
    // Reload the file, by data-href first if it's available, otherwise use href
    const reload = await fetch(link.dataset.href || link.href, { cache: "reload" }),
      // Generate url
      url = URL.createObjectURL(await reload.blob());

    // preserve real url
    if (!link.dataset.href) link.dataset.href = link.href;
    link.href = url.toString();
  });
}

与附加到 URL 相比,这样做的优点是实际上会将其从浏览器缓存中删除。使用其他脚本效果很好,但是当您刷新页面时,它会恢复为缓存的内容。小烦恼。但是,这不会在刷新后恢复。

这是一种快速更改 css 进行测试的好方法,无需始终刷新 ctrl F5,然后通过服务器端更新文件名或查询来推出更改样式表上的字符串正常。

data-href“保留”很重要,或者永久刷新缓存只能在每个页面视图中起作用一次。


可以为 script[src] 编写相同类型的脚本,但我不建议这样做,因为某些事情执行两次可能会出现各种错误,例如事件侦听器。

Based on https://stackoverflow.com/a/59176853/3917091 on this page

function refreshStylesheets() {
  // In my case, I'm getting all urls on my site (mysite.dev).
  (document.querySelectorAll('link[rel="stylesheet"][href*="mysite.dev\/"],link[rel="stylesheet"][data-href*="mysite.dev\/"]') || []).forEach(async link => {
    // Reload the file, by data-href first if it's available, otherwise use href
    const reload = await fetch(link.dataset.href || link.href, { cache: "reload" }),
      // Generate url
      url = URL.createObjectURL(await reload.blob());

    // preserve real url
    if (!link.dataset.href) link.dataset.href = link.href;
    link.href = url.toString();
  });
}

The advantage this has, over appending to the url, is that this actually removes it from the browser cache. Using other scripts works great, but when you refresh the page, it reverts to what it had cached. Minor annoyance. However, this does not revert upon refresh.

It's a nice way to quickly change css for testing without ctrl F5 refresh all of the time, and then you roll out the change by server-side updating the filename or the query string on the style sheet as normal.

The data-href 'preserving' is important, or the permanency of refreshing on your cache only works once per page-view.


The same sort of script can be written for script[src] but I would not advise that, because you may end up with all kinds of bugs with certain things being done twice, like event listeners.

行至春深 2024-08-23 19:51:13

是的,重新加载 css 标签。并记住使新的 url 唯一(通常通过附加随机查询参数)。我有代码可以做到这一点,但现在还没有。稍后编辑...

编辑:太晚了...harto 和 nickf 打败了我;-)

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

未蓝澄海的烟 2024-08-23 19:51:13

如果你使用 php 就很简单
只需在 css 末尾附加当前时间,就像

<link href="css/name.css?<?php echo 
time(); ?>" 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文