动态替换 css 文件(并将新样式应用到页面)

IT技术 javascript jquery html css
2021-02-07 22:23:03

我有一个页面,其中包含<link>加载名为 .css 的 CSS 的页眉light.css我还有一个名为dark.css. 我想要一个按钮来一起交换页面的样式(css 文件中使用了 40 个选择器,有些在两个文件中不匹配)。

如何删除对light.csswith JS 的引用并删除所有已应用的样式,然后dark.css从中加载和应用所有样式?我不能简单地重置所有元素,因为有些样式是通过不同的 css 文件应用的,有些是由 JS 动态生成的。有没有一种简单而有效的方法可以在不重新加载页面的情况下做到这一点?Vanilla JS 更可取,但无论如何我都会使用 jQuery 进行后续处理,因此 jQ 也很好。

6个回答

您可以在文档中包含所有样式表,然后根据需要激活/停用它们。

在我阅读规范时,您应该能够通过将其disabled属性从 true更改为 false激活备用样式表,但似乎只有 Firefox 才能正确执行此操作。

所以我认为你有几个选择:

切换 rel=alternate

<link rel="stylesheet"           href="main.css">
<link rel="stylesheet alternate" href="light.css" id="light" title="Light">
<link rel="stylesheet alternate" href="dark.css"  id="dark"  title="Dark">

<script>
function enableStylesheet (node) {
  node.rel = 'stylesheet';
}

function disableStylesheet (node) {
  node.rel = 'alternate stylesheet';
}
</script>

设置和切换 disabled

<link rel="stylesheet" href="main.css">
<link rel="stylesheet" href="light.css" id="light" class="alternate">
<link rel="stylesheet" href="dark.css"  id="dark"  class="alternate">

<script>
function enableStylesheet (node) {
  node.disabled = false;
}

function disableStylesheet (node) {
  node.disabled = true;
}

document
  .querySelectorAll('link[rel=stylesheet].alternate')
  .forEach(disableStylesheet);
</script>

切换 media=none

<link rel="stylesheet" href="main.css">
<link rel="stylesheet" href="light.css" media="none" id="light">
<link rel="stylesheet" href="dark.css"  media="none" id="dark">

<script>
function enableStylesheet (node) {
  node.media = '';
}

function disableStylesheet (node) {
  node.media = 'none';
}
</script>

您可以使用getElementByIdquerySelector选择样式表节点

(避免非标准的<link disabled>虽然设置HTMLLinkElement#disabled很好。)

只是为了澄清@Daniel 所说的,HTML 属性是非标准的,但根据 Mozilla,DOM 属性是。因此,以上述方式使用 javascript 切换它实际上是符合标准的。除非我遗漏了什么,否则这应该是公认的答案。
2021-03-13 22:23:03
@dzenesiz 浏览器可以跳过下载替代样式表,直到需要它为止,但我不知道它们的实际行为。
2021-03-26 22:23:03
不幸disabled的是,不鼓励将其设置为属性:“将禁用作为 HTML 属性的使用是非标准的,并且仅由某些浏览器使用(W3 #27677)。不要使用它。” -> developer.mozilla.org/en-US/docs/Web/HTML/Element/...
2021-03-28 22:23:03
@sam 现在我很抱歉我不能接受别人的问题的答案:)...只是,对页面的性能有什么影响吗?在该属性设置为 false 之前,浏览器是否忽略了禁用的链接?
2021-03-30 22:23:03
CSS对象模型说,这对disabled标志:“注意:即使取消它并不一定意味着CSS样式表实际上是用于渲染”。这可能是答案适用于 Firefox 而不适用于 Webkit & Blink ( Epyphany & Chromium ) 的原因。
2021-03-30 22:23:03

您可以创建一个新链接,并用新链接替换旧链接。如果你把它放在一个函数中,你可以在任何需要的地方重用它。

Javascript:

function changeCSS(cssFile, cssLinkIndex) {

    var oldlink = document.getElementsByTagName("link").item(cssLinkIndex);

    var newlink = document.createElement("link");
    newlink.setAttribute("rel", "stylesheet");
    newlink.setAttribute("type", "text/css");
    newlink.setAttribute("href", cssFile);

    document.getElementsByTagName("head").item(cssLinkIndex).replaceChild(newlink, oldlink);
}

HTML:

<html>
    <head>
        <title>Changing CSS</title>
        <link rel="stylesheet" type="text/css" href="positive.css"/>
    </head>
    <body>
        <a href="#" onclick="changeCSS('positive.css', 0);">STYLE 1</a> 
        <a href="#" onclick="changeCSS('negative.css', 0);">STYLE 2</a>
    </body>
</html>

为简单起见,我使用了内联 javascript。在生产中,您可能希望使用不显眼的事件侦听器。

您可以使用绝对 URL 来绕过位于不同文件夹或诸如此类的页面。我喜欢使用默认样式表来防止 FOUC 显示的想法。不错的提示!
2021-03-13 22:23:03
如果你想拉一个实时重新加载类型的东西,这可能是要走的路,因为 href 可能是相同的,如果 href 没有真正改变,浏览器实际上可能不会做任何事情。
2021-03-14 22:23:03
真的。这将替换 DOM 中的整个链接节点。
2021-03-30 22:23:03
我认为简单地更新href属性也可以正常工作:oldlink.href = cssFile; // done
2021-04-07 22:23:03
在切换 css 文件时,下载文件和渲染样式之间的差距使 html 没有样式。我想,应该有一个默认样式表,它总是在那里添加基本样式。移动浏览器只需花费大量时间来替换 css 样式表。考虑到 jekyll 生成的静态网站,不同页面的链接索引可能会有所不同
2021-04-08 22:23:03

如果您在链接元素上设置了 ID

<link rel="stylesheet" id="stylesheet" href="stylesheet1.css"/>

你可以用 Javascript 定位它

document.getElementsByTagName('head')[0].getElementById('stylesheet').href='stylesheet2.css';

要不就..

document.getElementById('stylesheet').href='stylesheet2.css';

这是一个更彻底的例子:

<head>
    <script>
    function setStyleSheet(url){
       var stylesheet = document.getElementById("stylesheet");
       stylesheet.setAttribute('href', url);
    }
    </script>

    <link id="stylesheet" rel="stylesheet" type="text/css" href="stylesheet1.css"/>
</head>
<body>
    <a onclick="setStyleSheet('stylesheet1.css')" href="#">Style 1</a>
    <a onclick="setStyleSheet('stylesheet2.css')" href="#">Style 2</a>
</body>

这个问题已经很老了,但我建议采用一种此处未提及的方法,在该方法中,您将在 HTML 中包含两个 CSS 文件,但 CSS 将类似于

光.css

/*** light.css ***/

p.main{
   color: #222;
}

/*** other light CSS ***/

dark.css会像

/*** dark.css ***/

.dark_layout p.main{
   color: #fff;
   background-color: #222;
}

/*** other dark CSS ***/

基本上dark.css中的每个选择器都将是 .dark_layout

然后,如果有人选择更改网站的主题,您需要做的就是更改 body 元素的类。

$("#changetheme").click(function(){
   $("body").toggleClass("dark_layout");
});

现在,一旦用户单击 ,您的所有元素都将具有深色 css #changetheme如果您使用任何类型的 CSS 预处理器,这很容易做到。

您还可以为背景和颜色添加 CSS 动画,使过渡非常平滑。

使用 jquery 你绝对可以交换 css 文件。单击按钮时执行此操作。

var cssLink = $('link[href*="light.css"]');
cssLink.replaceWith('<link href="dark.css" type="text/css" rel="stylesheet">');

或者作为山姆的回答,这也有效。这是 jquery 语法。

$('link[href*="light.css"]').prop('disabled', true);
$('link[href*="dark.css"]').prop('disabled', false);
它可能会更好,但我喜欢你如何清晰地定义 sam 的 jQ 部分并帮助我清楚地理解一切。
2021-04-06 22:23:03