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

Javascript 动态替换css文件(并将新样式应用于页面),javascript,jquery,html,css,Javascript,Jquery,Html,Css,我有一个页面,标题中有,加载名为light.CSS的CSS。我还有一个名为dark.css的文件。我想要一个按钮来交换所有页面的样式(有40个选择器在css文件中使用,有些在两个文件中不匹配) 如何使用JS删除对light.css的引用,删除所有应用的样式,然后加载dark.css并应用其中的所有样式?我不能简单地重置所有元素,因为有些样式是通过不同的css文件应用的,有些是由JS动态生成的。有没有一种简单而有效的方法可以在不重新加载页面的情况下实现这一点?Vanilla JS更可取,不过我会在

我有一个页面,标题中有
,加载名为
light.CSS的CSS。我还有一个名为
dark.css
的文件。我想要一个按钮来交换所有页面的样式(有40个选择器在css文件中使用,有些在两个文件中不匹配)


如何使用JS删除对
light.css
的引用,删除所有应用的样式,然后加载
dark.css
并应用其中的所有样式?我不能简单地重置所有元素,因为有些样式是通过不同的css文件应用的,有些是由JS动态生成的。有没有一种简单而有效的方法可以在不重新加载页面的情况下实现这一点?Vanilla JS更可取,不过我会在以后处理时使用jQuery,所以jQ也可以。

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

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>

更改CSS

为了简单起见,我使用了内联javascript。在生产环境中,您可能希望使用不引人注目的事件侦听器。

使用jquery,您完全可以交换css文件。在点击按钮时执行此操作

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

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

在我阅读规范时,您应该能够做到这一点,但似乎只有Firefox能够做到这一点

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

切换
rel=alternate
切换
media=none

函数启用样式表(节点){
node.media='';
}
函数禁用样式表(节点){
node.media='none';
}
可以使用等选择样式表节点

(避免使用非标准的
。设置也可以。)

使用jquery.attr()可以设置链接标记的href

示例代码

$("#yourButtonId").on('click',function(){
   $("link").attr(href,yourCssUrl);
});

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

<link rel="stylesheet" id="stylesheet" href="stylesheet1.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>

函数设置样式表(url){
var stylesheet=document.getElementById(“样式表”);
stylesheet.setAttribute('href',url);
}

也许我的想法太复杂了,但既然公认的答案对我不起作用,我想我也应该分享我的解决方案

故事:
我想做的是将我页面的不同“皮肤”作为附加样式表包含在标题中,这些样式表添加到“主”样式中,并通过按页面上的按钮进行切换(无浏览器设置或其他内容)

问题:
我认为@sam的解决方案非常优雅,但对我来说根本不起作用。至少有一部分问题是,我使用的是一个主CSS文件,而只是在上面添加其他文件作为“皮肤”,因此我必须使用缺少的“title”属性对文件进行分组

以下是我的想法。
首先使用“备用”将所有“皮肤”添加到头部:

<link rel="stylesheet" href="css/main.css" title='main'>
<link rel="stylesheet alternate" href="css/skin1.css" class='style-skin' title=''>
<link rel="stylesheet alternate" href="css/skin2.css" class='style-skin' title=''>
<link rel="stylesheet alternate" href="css/skin3.css" class='style-skin' title=''>

它所做的是迭代所有可用的皮肤,获取(很快)激活的皮肤,将标题设置为“main”并激活它。所有其他皮肤都被禁用,标题也被删除。

这个问题已经很老了,但我建议使用一种在这里没有提到的方法,即在HTML中包含两个CSS文件,但CSS将类似于

/*** dark.css ***/

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

/*** other dark CSS ***/
light.css

/*** light.css ***/

p.main{
   color: #222;
}

/*** other light CSS ***/
黑暗。css将像

/*** dark.css ***/

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

/*** other dark CSS ***/
basicall dark.css中的每个选择器都是
.dark\u layout

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

$("#changetheme").click(function(){
   $("body").toggleClass("dark_layout");
});
现在,一旦用户单击
#changetheme
,您的所有元素都将具有黑色css。如果您使用的是任何类型的CSS预处理器,那么这很容易做到


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

只需将您的
链接
href属性更新到新的CSS文件中即可

function setStyleSheet(fileName){
       document.getElementById("WhatEverYouAssignIdToStyleSheet").setAttribute('href', fileName);
    }

我选择Mattew的答案是因为使用该方法,我可以轻松地扩展for()循环,以处理多个文件,并在其他脚本/样式表中交换
light
dark
。我认为只需更新
href
属性也可以:
oldlink.href=cssFile;//完成
True。这将替换DOM中的整个链接节点。如果您想拉一个实时重新加载类型的东西,这可能是最好的方法,因为href可能是相同的,如果href没有实际更改,浏览器可能不会实际执行任何操作。在切换css文件时,下载文件和呈现样式的间隙使得html没有样式。我想,应该有一个默认样式表,它添加了基本样式,总是在那里。移动浏览器只是花了很多时间来替换css样式表。此外,链接的索引在不同的页面中可能会有所不同,如果Jekylly生成了一个静态网站,那么您可以使用绝对URL来绕过不同文件夹中的页面或诸如此类的内容。我喜欢使用默认样式表来防止FOUC显示。好小费@山姆:很抱歉,我不能接受别人问题的答案:)。。。只是,对page的性能有影响吗?在属性设置为false之前,浏览器是否会忽略禁用链接?不幸的是,将
禁用
设置为属性会被讨论:“将禁用作为HTML属性使用是非标准的,并且仅由某些浏览器使用(W3#27677)。请勿使用它。”->@dzenesiz浏览器可以跳过下载备用样式表,直到需要时才下载,但我不知道它们的实际行为。为了澄清@Daniel所说的,HTML属性是非标准的,但根据Mozilla的说法,DOM属性是。因此,以上述方式将其与javascript切换实际上是符合标准的。除非我遗漏了什么,否则这应该是公认的答案
var activeSkin = 0;    
$('#myButton').on('click', function(){
    var skins = $('.style-skin');
    if (activeSkin > skins.length) activeSkin=0;
    skins.each(function(index){
        if (index === activeSkin){
            $(this).prop('title', 'main');
            $(this).prop('disabled', false);
        }else{
            $(this).prop('title', '');
            $(this).prop('disabled', true);
        }
    });
    activeSkin++
});
/*** light.css ***/

p.main{
   color: #222;
}

/*** other light CSS ***/
/*** dark.css ***/

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

/*** other dark CSS ***/
$("#changetheme").click(function(){
   $("body").toggleClass("dark_layout");
});
function setStyleSheet(fileName){
       document.getElementById("WhatEverYouAssignIdToStyleSheet").setAttribute('href', fileName);
    }