从 JavaScript 设置 CSS 伪类规则

IT技术 javascript css pseudo-class css-in-js
2021-01-20 13:40:04

我正在寻找一种方法来从 JavaScript 更改伪类选择器(例如:link、:hover 等)的 CSS 规则。

所以类似于 CSS 代码:a:hover { color: red }在 JS 中。

我在其他任何地方都找不到答案;如果有人知道这是浏览器不支持的内容,那也将是一个有用的结果。

6个回答

您不能单独在特定元素上设置伪类的样式,就像不能在内联 style="..." 属性中设置伪类一样(因为没有选择器)。

您可以通过更改样式表来实现,例如添加规则:

#elid:hover { background: red; }

假设您要影响的每个元素都有一个唯一的 ID 以允许选择它。

理论上你想要的文档是http://www.w3.org/TR/DOM-Level-2-Style/Overview.html这意味着你可以(给定一个预先存在的嵌入或链接的样式表)使用如下语法:

document.styleSheets[0].insertRule('#elid:hover { background-color: red; }', 0);
document.styleSheets[0].cssRules[0].style.backgroundColor= 'red';

当然,IE 需要自己的语法:

document.styleSheets[0].addRule('#elid:hover', 'background-color: red', 0);
document.styleSheets[0].rules[0].style.backgroundColor= 'red';

较旧和较小的浏览器可能不支持任何一种语法。动态样式表摆弄很少做,因为它很烦人,很少需要,而且在历史上很麻烦。

@fluteflute 如果您尝试操作来自不同域的 CSS 文件,则该操作被认为是不安全的(我猜这是一种同源策略)。耻辱!检查是否符合同源策略的简单函数: function sameOrigin(url) { var loc = window.location, a = document.createElement('a'); a.href = url; return a.hostname === loc.hostname && a.port === loc.port && a.protocol === loc.protocol; }
2021-03-16 13:40:04
Firefox:“错误:操作不安全。”
2021-03-22 13:40:04
为什么没有选择这个作为答案?
2021-04-01 13:40:04
不推荐仅仅为了将样式应用到特定元素而操作样式表,因为它会导致浏览器在每次更改样式表时重排整个文档。stubbornella.org/content/2009/03/27/...
2021-04-09 13:40:04

为此拼凑了一个小型库,因为我确实认为在 JS 中存在操作样式表的有效用例。原因如下:

  • 设置必须计算或检索的样式 - 例如从 cookie 设置用户的首选字体大小。
  • 设置行为(非美学)样式,尤其是对于 UI 小部件/插件开发人员。选项卡、轮播等通常需要一些基本的 CSS 才能发挥作用 - 不应要求核心功能的样式表。
  • 优于内联样式,因为 CSS 规则适用于所有当前和未来的元素,并且在 Firebug / Developer Tools 中查看时不会弄乱 HTML。

一个处理跨浏览器问题的函数:

addCssRule = function(/* string */ selector, /* string */ rule) {
  if (document.styleSheets) {
    if (!document.styleSheets.length) {
      var head = document.getElementsByTagName('head')[0];
      head.appendChild(bc.createEl('style'));
    }

    var i = document.styleSheets.length-1;
    var ss = document.styleSheets[i];

    var l=0;
    if (ss.cssRules) {
      l = ss.cssRules.length;
    } else if (ss.rules) {
      // IE
      l = ss.rules.length;
    }

    if (ss.insertRule) {
      ss.insertRule(selector + ' {' + rule + '}', l);
    } else if (ss.addRule) {
      // IE
      ss.addRule(selector, rule, l);
    }
  }
};

只需将 css 放在模板字符串中。

const cssTemplateString = `.foo:[psuedoSelector]{prop: value}`;

然后创建一个样式元素并将字符串放在样式标签中并将其附加到文档中。

const styleTag = document.createElement("style");
styleTag.innerHTML = cssTemplateString;
document.head.insertAdjacentElement('beforeend', styleTag);

特殊性将解决其余的问题。然后您可以动态删除和添加样式标签。这是库的简单替代方法,并且可以处理 DOM 中的样式表数组。快乐编码!

我不喜欢这个解决方案。你的 CSS 不会被缓存。
2021-03-12 13:40:04
insertAdjacentElement在主要浏览器(Chrome、Firefox、Edge)中需要 2 个参数,第一个参数建立相对于参考元素的位置(参见此处)。这是最近的变化吗?(在答案中添加了“beforeend”)。
2021-03-24 13:40:04

我的技巧是使用属性选择器。属性更容易通过 javascript 设置。

css

.class{ /*normal css... */}
.class[special]:after{ content: 'what you want'}

javascript

  function setSpecial(id){ document.getElementById(id).setAttribute('special', '1'); }

html

<element id='x' onclick="setSpecial(this.id)"> ...  
这个方法究竟是如何改变 .class[special]:after 伪元素的 CSS 属性的,比如背景颜色或其他任何东西?
2021-03-24 13:40:04
这个解决方案使用了 jQuery——当提问者要求使用纯 Javascript 时,为这样简单的事情引入一个 jQuery 大小的依赖是不好的。
2021-03-31 13:40:04
虽然现在几乎所有网站都使用 jquery,但我将修改它以使用纯 javascript。
2021-04-04 13:40:04