切换样式表会闪烁

4
我有一个网站有两个样式表,一个用于白天阅读,另一个用于夜晚阅读。我有一张图片,带有 onclick 事件调用一个函数来更改样式表。问题是,对于新访问者,当他们第一次点击按钮时,页面会完全没有样式(即没有样式表),只持续了半秒钟,然后才出现新的样式表。我知道出现这种情况的原因是在添加新样式表之前,我移除了当前样式表的 rel="stylesheet"。是否有任何方法可以改进该函数,以便即使针对新访客也没有短暂的延迟?谢谢。
function changeStyleSheet() {
    var a = document.getElementById('stylesheet1');
    var b = document.getElementById('stylesheet2');
    var now1 = $(a).attr('rel');
    var now2 = $(b).attr('rel');
    if (now1 == 'stylesheet') {
        a.setAttribute('rel', 'alt-stylesheet');
        b.setAttribute('rel', 'stylesheet');
    } else {
        b.setAttribute('rel', 'alt-stylesheet');
        a.setAttribute('rel', 'stylesheet');
    }
};
4个回答

4

您尝试过交换属性的设置顺序吗?比如先设置您要切换到的样式表的rel属性,然后再设置您要从中切换出来的样式表的rel属性?

在HTML中将两个rel属性都设置为stylesheet,在页面加载时使用javascript将其中一个更改为替代样式表。


不,我没有……让我试试。我最初没有这样做是因为我认为我不能同时将rel="stylesheet"设置为两个元素。 - preahkumpii
没有什么区别。看起来浏览器需要短暂的时间来加载第二个样式表或类似的东西。因为当我切换样式表后,它就不再闪烁了。 - preahkumpii
那么预加载样式表怎么样呢?在HTML中将两个rel属性都设置为stylesheet,当页面加载时,使用JavaScript将其中一个切换为备用样式表。 - Charlie Johnson
最后一个建议似乎已经起作用了...但是Opera仍然按照它自己的愚蠢方式运行。请提供另一个答案,以便我可以将其标记为正确(当前答案不正确)。 - preahkumpii
我已经编辑了答案,包括在HTML中设置rel属性,然后在加载后使用javascript进行更改。 - Charlie Johnson

1
为什么不使用类似以下的东西:
JavaScript
function changeStyle() {
    document.getElementById('stylesheet').href = 'style2.css';
}

HTML

<input type="button" onclick="changeStyle();"/>
<link rel="stylesheet" href="style1.css" id="stylesheet">

或者尝试使用this来加载多个样式表

要进行切换,请尝试这样做:

function changeStyle() {
    var a = document.getElementById('stylesheet').href;
    if (a === 'style1.css') {
        document.getElementById('stylesheet').href = 'style2.css';
    } else {
        document.getElementById('stylesheet').href = 'style1.css';        
    }
}​

看起来更容易。但是如果要切换回去,比如一个开关,该怎么做? - preahkumpii
把它放在一个if函数里,给我一秒钟。 - jacktheripper
好的,我尝试了一下。它没有起作用。我还需要在head标签中调用这两个表格吗?如果是这样,我要在它们上面放置'rel'和'id'吗?如果我有两个具有相同id的表格(错误),并且函数正在寻找其中一个,那么可能会出现问题。 - preahkumpii
问题在于,由于有多个元素,它依赖于在链接中单独定义的 JavaScript:changeSheets(#) 部分。我有一个按钮必须同时执行两个操作。 - preahkumpii

1

如果您不需要维护两个单独的样式表,那么通过在body中的父元素上应用一个id可能更容易实现您的目标。在我的演示中,我为简单起见使用了body元素,但如果不可能,您可以简单地将站点内容包装在一个div中并添加一个id。然后,只需在CSS选择器前加上相关的id即可应用相关样式。

在我的演示中,我正在使用以下JavaScript:

var sel = document.getElementById('styles'),
    b = document.getElementsByTagName('body')[0];
sel.onchange = function() {
    b.id = this.value;
};​

还有 CSS:

#styles1 h1 {
    margin-top: 1em;
    color: #f00;
    background-color: #000;
    text-align: center;
    font-size: 2em;
}

#styles1 div {
    width: 80%;
}

#styles2 h1 {
    margin-top: 1em;
    color: #000;
    background-color: #fff;
    text-align: right;
    font-size: 1.5em;
    font-style: italic;
}

#styles2 div {
    width: 50%;
    margin: 0 auto 1em auto;
}

/* the following is for the element holding the style-switcher select */
#styles1 #themes,
#styles2 #themes {
    width: auto;
    position: absolute;
    top: 0;
    left: 0;
    background-color: #fff;
}​

JS Fiddle演示

使用上述方法,当样式更改时,您不应该注意到任何闪烁,因为样式表已经加载。如果您的页面特别复杂,则可能会出现可见的闪烁,但它应该比切换到新样式表的闪烁要短暂得多。


0

除非你的两个样式表具有非常相似的结构,否则你最终会得到一个奇怪的闪烁/渲染:

变化顺序(你希望的):

  • 样式表1 - 应用
  • 样式表2 - 应用
  • 样式表1 - 移除

这意味着在短暂的一秒钟内,你将应用两个样式表(如果它们只是设置颜色调色板并且都在同一个元素上,那么这不是问题,但如果更冗长/重要,则会成为问题)。

如果这是一个问题,你可以考虑做一些让样式表更改看起来很棒的事情 - 比如在样式更改之前淡出页面/元素,更改样式,然后再淡入。

如果这不是一个问题,你应该能够使用jacktheripper提供的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接