从 JavaScript 设置 CSS 伪类规则

问题描述 投票:0回答:12

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

所以 CSS 代码的模拟:

a:hover { color: red }
在 JS 中。

我在别处找不到答案;如果有人知道这是浏览器不支持的东西,那也会是一个有用的结果。

javascript css pseudo-class css-in-js
12个回答
214
投票

你不能单独在特定元素上设置伪类的样式,就像你不能在内联 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';

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


30
投票

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

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

19
投票

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

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

然后创建一个style元素,将字符串放在style标签中,附加到文档中

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

特异性会解决其余的问题。然后您可以动态删除和添加样式标签。这是库的一个简单替代方案,并且会扰乱 DOM 中的样式表数组。快乐编码!


18
投票

应对跨浏览器的功能:

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

8
投票

我的技巧是使用属性选择器。属性更容易通过 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)"> ...  

5
投票

还有一个选择。不要直接操作伪类,而是创建模拟相同事物的真实类,如“悬停”类或“访问”类。使用通常的“。”设置类的样式。语法,然后您可以使用 JavaScript 在适当的事件触发时从元素中添加或删除类。


5
投票

您可以在不同的 CSS 文件中设置不同的规则,而不是直接使用 javascript 设置伪类规则,然后使用 Javascript 关闭一个样式表并打开另一个样式表。 A List Apart 中描述了一种方法(qv. 了解更多详情)。

将 CSS 文件设置为,

<link rel="stylesheet" href="always_on.css">
<link rel="stylesheet" title="usual" href="preferred.css"> <!-- on by default -->
<link rel="alternate stylesheet" title="strange" href="alternate.css"> <!-- off by default -->

然后使用 javascript 在它们之间切换:

function setActiveStyleSheet(title) {
   var i, a, main;
   for(i=0; (a = document.getElementsByTagName("link")<i>); i++) {
     if(a.getAttribute("rel").indexOf("style") != -1
        && a.getAttribute("title")) {
       a.disabled = true;
       if(a.getAttribute("title") == title) a.disabled = false;
     }
   }
}

5
投票

您可以考虑的一个选择是使用 CSS 变量。这个想法是将要更改的属性设置为 CSS 变量。然后,在您的 JS 中,更改该变量的值。

看下面的例子

function changeColor(newColor) {
  document.documentElement.style.setProperty("--anchor-hover-color", newColor);
  // ^^^^^^^^^^^-- select the root 
}
:root {
  --anchor-hover-color: red;
}

a:hover { 
  color: var(--anchor-hover-color); 
}
<a href="#">Hover over me</a>

<button onclick="changeColor('lime')">Change to lime</button>
<button onclick="changeColor('red')">Change to red</button>


2
投票

如前所述,这不是浏览器支持的东西。

如果您没有动态地提出样式(即将它们从数据库中拉出或其他东西),您应该能够通过向页面主体添加一个类来解决这个问题。

CSS 看起来像:

a:hover { background: red; }
.theme1 a:hover { background: blue; }

改变它的 javascript 是这样的:

// Look up some good add/remove className code if you want to do this
// This is really simplified

document.body.className += " theme1";  

0
投票

这里有一个解决方案,包括两个函数:addCSSclass 向文档添加一个新的 css 类,toggleClass 将其打开

示例显示向 div 添加自定义滚动条

// If newState is provided add/remove theClass accordingly, otherwise toggle theClass
function toggleClass(elem, theClass, newState) {
  var matchRegExp = new RegExp('(?:^|\\s)' + theClass + '(?!\\S)', 'g');
  var add = (arguments.length > 2 ? newState : (elem.className.match(matchRegExp) === null));

  elem.className = elem.className.replace(matchRegExp, ''); // clear all
  if (add) elem.className += ' ' + theClass;
}

function addCSSclass(rules) {
  var style = document.createElement("style");
  style.appendChild(document.createTextNode("")); // WebKit hack :(
  document.head.appendChild(style);
  var sheet = style.sheet;

  rules.forEach((rule, index) => {
    try {
      if ("insertRule" in sheet) {
        sheet.insertRule(rule.selector + "{" + rule.rule + "}", index);
      } else if ("addRule" in sheet) {
        sheet.addRule(rule.selector, rule.rule, index);
      }
    } catch (e) {
      // firefox can break here          
    }
    
  })
}

let div = document.getElementById('mydiv');
addCSSclass([{
    selector: '.narrowScrollbar::-webkit-scrollbar',
    rule: 'width: 5px'
  },
  {
    selector: '.narrowScrollbar::-webkit-scrollbar-thumb',
    rule: 'background-color:#808080;border-radius:100px'
  }
]);
toggleClass(div, 'narrowScrollbar', true);
<div id="mydiv" style="height:300px;width:300px;border:solid;overflow-y:scroll">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a eros metus. Nunc dui felis, accumsan nec aliquam quis, fringilla quis tellus. Nulla cursus mauris nibh, at faucibus justo tincidunt eget. Sed sodales eget erat consectetur consectetur. Vivamus
  a diam volutpat, ullamcorper justo eu, dignissim ante. Aenean turpis tortor, fringilla quis efficitur eleifend, iaculis id quam. Quisque non turpis in lacus finibus auctor. Morbi ullamcorper felis ut nulla venenatis fringilla. Praesent imperdiet velit
  nec sodales sodales. Etiam eget dui sollicitudin, tempus tortor non, porta nibh. Quisque eu efficitur velit. Nulla facilisi. Sed varius a erat ac volutpat. Sed accumsan maximus feugiat. Mauris id malesuada dui. Lorem ipsum dolor sit amet, consectetur
  adipiscing elit. Sed a eros metus. Nunc dui felis, accumsan nec aliquam quis, fringilla quis tellus. Nulla cursus mauris nibh, at faucibus justo tincidunt eget. Sed sodales eget erat consectetur consectetur. Vivamus a diam volutpat, ullamcorper justo
  eu, dignissim ante. Aenean turpis tortor, fringilla quis efficitur eleifend, iaculis id quam. Quisque non turpis in lacus finibus auctor. Morbi ullamcorper felis ut nulla venenatis fringilla. Praesent imperdiet velit nec sodales sodales. Etiam eget
  dui sollicitudin, tempus tortor non, porta nibh. Quisque eu efficitur velit. Nulla facilisi. Sed varius a erat ac volutpat. Sed accumsan maximus feugiat. Mauris id malesuada dui.
</div>


-1
投票

在 jquery 中,您可以轻松设置悬停伪类。

$("p").hover(function(){
$(this).css("background-color", "yellow");
}, function(){
$(this).css("background-color", "pink");
});

-4
投票

如果你使用 REACT ,有一种叫做 radium 的东西。它在这里非常有用:

  • 如果指定了交互样式,则将处理程序添加到道具,例如onMouseEnter for :hover,必要时包装现有的处理程序

  • 如果触发了任何处理程序,例如通过悬停,Radium 调用 setState 来更新组件上特定于 Radium 的字段 状态对象

  • 重新渲染时,解决任何适用的交互样式,例如:hover,通过在特定于 Radium 的元素中查找元素的键或 ref 状态

© www.soinside.com 2019 - 2024. All rights reserved.