使用 javascript(或 jQuery)选择和操作 CSS 伪元素,例如 ::before 和 ::after

Selecting and manipulating CSS pseudo-elements such as ::before and ::after using javascript (or jQuery)

提问人:JBradwell 提问时间:2/18/2011 最后编辑:Temani AfifJBradwell 更新时间:11/5/2023 访问量:882410

问:

有没有办法使用jQuery选择/操作CSS伪元素,例如和(以及带有一个分号的旧版本)?::before::after

例如,我的样式表有以下规则:

.span::after{ content:'foo' }

如何使用 vanilla JS 或 jQuery 将“foo”更改为“bar”?

javascript jquery css jquery-selectors 伪元素

评论

1赞 Abhay Maurya 11/14/2016
公认的答案非常好。不过,如果你试图实现以下任何一点,答案是行不通的:1.通过JS改变:before的样式。2. 通过JS更改:before的内容 如果需要,请参阅我的回答。
0赞 guest271314 2/19/2017
查看 github.com/guest271314/pseudo/blob/master/pseudo.js
0赞 Temani Afif 5/1/2019
@Learner 现在所有这些都有一个答案:stackoverflow.com/a/49618941/8620333

答:

169赞 BoltClock 2/18/2011 #1

尽管它们是由浏览器通过 CSS 呈现的,就好像它们与其他真正的 DOM 元素一样,但伪元素本身并不是 DOM 的一部分,因为伪元素,顾名思义,不是真正的元素,因此你不能直接使用 jQuery(或任何 JavaScript API,甚至不是 Selectors API)来选择和操作它们。这适用于您尝试使用脚本修改其样式的任何伪元素,而不仅仅是 和 。::before::after

您只能在运行时通过 CSSOM (think ) 直接访问伪元素样式,jQuery beyond 不会公开该样式,该方法也不支持伪元素。window.getComputedStyle().css()

不过,您总能找到其他方法,例如:

  • 将样式应用于一个或多个任意类的伪元素,然后在类之间切换(参见 seucolega 的回答以获取快速示例)——这是惯用的方式,因为它使用简单的选择器(伪元素不是)来区分元素和元素状态,以及它们的使用方式

  • 通过更改文档样式表来操作应用于所述伪元素的样式,这更像是一种黑客攻击

93赞 Gustavo Sousa 3/17/2011 #2

您不能在 jQuery 中选择伪元素,因为它们不是 DOM 的一部分。 但是你可以将一个特定的类添加到父元素,并在CSS中控制它的伪元素。

在jQuery中:

<script type="text/javascript">
    $('span').addClass('change');
</script>

在 CSS 中:

span.change:after { content: 'bar' }
779赞 Nick Kline 4/21/2011 #3

您还可以将内容传递给具有 data 属性的伪元素,然后使用 jQuery 对其进行操作:

在 HTML 中:

<span>foo</span>

在jQuery中:

$('span').hover(function(){
    $(this).attr('data-content','bar');
});

在 CSS 中:

span:after {
    content: attr(data-content) ' any other text you may want';
}

如果你想防止“其他文本”出现,你可以将其与seucolega的解决方案结合起来,如下所示:

在 HTML 中:

<span>foo</span>

在jQuery中:

$('span').hover(function(){
    $(this).addClass('change').attr('data-content','bar');
});

在 CSS 中:

span.change:after {
    content: attr(data-content) ' any other text you may want';
}

评论

2赞 Kevin Peno 8/20/2011
规范中是否有用于对属性使用该函数的链接?我很惊讶我从未听说过这个......attrcontent
108赞 Maksim Vi. 1/20/2012
+1 ,太糟糕了,我无法将它与其他属性一起使用。演示attr()content
30赞 BoltClock 2/8/2012
这是因为除了 CSS2 之外,还没有现有的浏览器实现,而在 CSS2 中,它本身只为属性定义。attr()attr()content
10赞 3/23/2013
更新了属性引用的链接:w3.org/TR/css3-values/#attr-notation
7赞 Christian 9/12/2012 #4

一种有效但不是很有效的方法是向文档添加包含新内容的规则,并使用类引用它。 根据需要,类可能需要 Content 中每个值的唯一 ID。

$("<style type='text/css'>span.id-after:after{content:bar;}</style>").appendTo($("head"));
$('span').addClass('id-after');
42赞 Ivan Chaer 10/18/2012 #5

按照克里斯蒂安的建议,你也可以做:

$('head').append("<style>.span::after{ content:'bar' }</style>");

评论

2赞 K.S. 9/20/2016
这里应该添加一个 id 属性,以便在添加新元素之前可以选择和删除该元素。如果没有,可能会出现很多不必要的样式节点。
0赞 1/22/2021
不幸的是,您的样本不起作用,但这确实起作用了。const setPseudoElContent = (selector, value) => { const style = document.createElement('style'); style.innerHTML = ; document.head.appendChild(style); }${selector} {${value}; }
559赞 Blazemonger 2/12/2014 #6

你可能会认为这是一个简单的问题,jQuery可以做其他所有事情。不幸的是,问题归结为一个技术问题:css :after 和 :before 规则不是 DOM 的一部分,因此不能使用 jQuery 的 DOM 方法进行更改。

有一些方法可以使用 JavaScript 和/或 CSS 解决方法操作这些元素;您使用哪一个取决于您的确切要求。


我将从被广泛认为的“最佳”方法开始:

1) 添加/删除预定类

在这种方法中,你已经在 CSS 中创建了一个具有不同 or 样式的类。稍后将这个“新”类放在样式表中,以确保它覆盖::after:before

p:before {
    content: "foo";
}
p.special:before {
    content: "bar";
}

然后,您可以使用 jQuery(或 vanilla JavaScript)轻松添加或删除此类:

$('p').on('click', function() {
    $(this).toggleClass('special');
});

    $('p').on('click', function() {
      $(this).toggleClass('special');
    });
p:before {
  content: "foo";
  color: red;
  cursor: pointer;
}
p.special:before {
  content: "bar";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p>This is a paragraph.</p>
<p>This is another paragraph.</p>

  • 优点:使用jQuery易于实现;一次快速更改多种样式;强制分离关注点(将 CSS 和 JS 与 HTML 隔离)
  • 缺点:CSS 必须是预先编写的,因此 OR 的内容不是完全动态的:before:after

2)将新样式直接添加到文档的样式表中

可以使用 JavaScript 将样式直接添加到文档样式表中,包括 和 样式。jQuery 没有提供方便的快捷方式,但幸运的是 JS 并没有那么复杂::after:before

var str = "bar";
document.styleSheets[0].addRule('p.special:before','content: "'+str+'";');

var str = "bar";
document.styleSheets[0].addRule('p.special:before', 'content: "' + str + '";');
p:before {
  content: "foo";
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p class="special">This is a paragraph</p>
<p>This is another paragraph</p>

.addRule() 和相关的 .insertRule() 方法目前得到了很好的支持。

作为变体,您还可以使用 jQuery 向文档添加一个全新的样式表,但必要的代码并不简洁:

var str = "bar";
$('<style>p.special:before{content:"'+str+'"}</style>').appendTo('head');

var str = "bar";
$('<style>p.special:before{content:"' + str + '"}</style>').appendTo('head');
p:before {
  content: "foo";
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p class="special">This is a paragraph</p>
<p>This is another paragraph</p>

如果我们谈论的是“操作”值,而不仅仅是添加它们,我们还可以使用不同的方法读取现有的 :after 或 :before 样式:

var str = window.getComputedStyle(document.querySelector('p'), ':before') 
           .getPropertyValue('content');

var str = window.getComputedStyle($('p')[0], ':before').getPropertyValue('content');
console.log(str);

document.styleSheets[0].addRule('p.special:before', 'content: "' + str+str + '";');
p:before {
    content:"foo";
    color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p class="special">This is a paragraph</p>
<p>This is another paragraph</p>

当使用jQuery时,我们可以用$('p')[0]替换,以获得稍短的代码。document.querySelector('p')

  • 优点:任何字符串都可以动态插入到样式中
  • 缺点:原始样式不会改变,只是被覆盖;重复(ab)使用可以使DOM任意变大

3) 更改不同的 DOM 属性

您还可以在 CSS 中使用 attr() 来读取特定的 DOM 属性。(如果浏览器支持 :before,它也支持 attr()。通过将其与一些精心准备的 CSS 相结合,我们可以动态地更改 和 的内容(但不是其他属性,如边距或颜色):content::before:after

p:before {
    content: attr(data-before);
    color: red;
    cursor: pointer;
}

WSG集团

$('p').on('click', function () {
    $(this).attr('data-before','bar');
});

$('p').on('click', function () {
    $(this).attr('data-before','bar');
});
p:before {
    content: attr(data-before);
    color: red;
    cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p>This is a paragraph.</p>
<p>This is another paragraph.</p>

如果无法提前准备 CSS,则可以将其与第二种技术结合使用:

var str = "bar";

document.styleSheets[0].addRule('p:before', 'content: attr(data-before);');

$('p').on('click', function () {
    $(this).attr('data-before', str);
});

var str = "bar";
document.styleSheets[0].addRule('p:before', 'content: attr(data-before) !important;');

$('p').on('click', function() {
  $(this).attr('data-before', str);
});
p:before {
  content: "foo";
  color: red;
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p>This is a paragraph.</p>
<p>This is another paragraph.</p>

  • 优点:不会创建无穷无尽的额外样式
  • 缺点:在CSS中只能应用于内容字符串,而不能应用于URL或RGB颜色attr

评论

2赞 user2101068 6/20/2015
我正在尝试在 psedo 之后的 ::: 中动态设置字形值(即通过其十六进制值)。content: 元素(例如,content: “\e043”;)。它似乎对我不起作用,所以我假设它也不适用于字形的十六进制值?
0赞 Blazemonger 6/20/2015
@user2101068 您应该将其作为新问题发布。我必须看到你正在使用的所有代码。
0赞 user2101068 6/20/2015
Blazemonger,感谢您的快速回复..不幸的是,有相当多的代码,要剪掉相关的代码需要相当多的努力。我已经花了 12+ 个小时试图完成这项工作,这是我最后一次努力让它工作。我需要减少损失。我希望您在使用您在上面的 #3 中描述的技术(在代码片段之前)时能够验证我的假设 re: 十六进制值。我可以在内容元素中插入十六进制字符串,但它显示字形十六进制值的文本,而不是实际的字形。在没有看到所有代码的情况下进行印象?
1赞 Blazemonger 6/20/2015
@user2101068 不要使用十六进制字符串;相反,将实际的 Unicode 字符复制并粘贴到 HTML 属性中。jsfiddle.net/mblase75/Lcsjkc5y
0赞 Picard 9/2/2016
关于解决方案 2。& 3.实际上,如果你使用:document.styleSheets[0].insertRule(rule, index),你可以防止样式表(过度)增长,然后使用这个索引,你可以在不需要的时候删除规则:document.styleSheets[0].deleteRule(index)
5赞 Coyote 3/19/2014 #7

下面是 HTML:

<div class="icon">
  <span class="play">
    ::before
  </span>
</div>

“before”的计算样式为content: "VERIFY TO WATCH";

这是我的两行jQuery,它们使用添加一个额外的类来专门引用此元素,然后附加一个样式标签(带有 !important 标签)来更改 sudo-element 内容值的 CSS:

$("span.play:eq(0)").addClass('G');

$('body').append("<style>.G:before{content:'NewText' !important}</style>");

14赞 user595349 6/15/2014 #8

如果你想完全通过CSS操作::before或::after sudo元素,你可以用JS来做。见下文;

jQuery('head').append('<style id="mystyle" type="text/css"> /* your styles here */ </style>');

请注意元素如何具有 ID,如果样式动态更改,您可以使用该 ID 将其删除并再次追加到该 ID。<style>

这样,在JS的帮助下,你的元素就可以通过CSS完全按照你想要的方式设置样式。

9赞 aimiliano 7/10/2014 #9

谢谢大家! 我设法做了我想做的事:Dhttp://jsfiddle.net/Tfc9j/42/ 这里看一看

我希望外部 div 的不透明度与内部 div 的不透明度不同,并且随着单击而改变 somwewhere ;) 谢谢!

   $('#ena').on('click', function () {
        $('head').append("<style>#ena:before { opacity:0.3; }</style>");
    });

$('#duop').on('click', function (e) {

        $('head').append("<style>#ena:before { opacity:0.8; }</style>");

     e.stopPropagation(); 
    });

#ena{
    width:300px;
    height:300px;
    border:1px black solid;
    position:relative;
}
#duo{
    opacity:1;
    position:absolute;
    top:50px;
  width:300px;
    height:100px;
      background-color:white;
}
#ena:before {
    content: attr(data-before);
    color: white;
    cursor: pointer;
    position: absolute;
    background-color:red;
    opacity:0.9;
    width:100%;
    height:100%;
}


<div id="ena">
    <div id="duo">
        <p>ena p</p>
        <p id="duop">duoyyyyyyyyyyyyyy p</p>

    </div>   


</div>

评论

0赞 KingRider 12/29/2016
不尝试,使用最好预防appendhtml
1赞 pupitetris 10/27/2017
注意:在这里,每次处理其中一个点击时,您都会在头部附加一个样式标签。我会编写一种方法来删除旧的,然后再添加新的。
33赞 Nedudi 7/16/2014 #10

以下是访问 css 中定义的 :after 和 :before 样式属性的方法:

// Get the color value of .element:before
var color = window.getComputedStyle(
    document.querySelector('.element'), ':before'
).getPropertyValue('color');

// Get the content value of .element:before
var content = window.getComputedStyle(
    document.querySelector('.element'), ':before'
).getPropertyValue('content');

评论

3赞 Dreamer64 8/20/2021
这是如何访问,但如何更改?
4赞 Alexander Shutau 10/13/2014 #11

您可以创建一个假属性或使用现有属性并在伪元素的样式表中继承它。

var switched = false;

// Enable color switching
setInterval(function () {
    var color = switched ? 'red' : 'darkred';
    var element = document.getElementById('arrow');
    element.style.backgroundColor = color;
    
    // Managing pseudo-element's css
    // using inheritance.
    element.style.borderLeftColor = color;
    
    switched = !switched;
}, 1000);
.arrow {
    /* SET FICTIONAL PROPERTY */
    border-left-color:red;
    
    background-color:red;
    width:1em;
    height:1em;
    display:inline-block;
    position:relative;
}
.arrow:after {
    border-top:1em solid transparent;
    border-right:1em solid transparent;
    border-bottom:1em solid transparent;
    border-left:1em solid transparent;
    
    /* INHERIT PROPERTY */
    border-left-color:inherit;
    
    content:"";
    width:0;
    height:0;
    position:absolute;
    left:100%;
    top:-50%;
}
<span id="arrow" class="arrow"></span>

似乎它不适用于“内容”属性:(

4赞 Adarsh Hegde 4/20/2015 #12

这是不切实际的,因为我不是为了现实世界的使用而写的,只是为了给你一个可以实现的例子。

css = {
before: function(elem,attr){ 

if($("#cust_style") !== undefined){ 
$("body").append("<style> " + elem + ":before {"  + attr +  "} </style>"); 
} else {
 $("#cust_style").remove();
$("body").append("<style> " + elem + ":before {"  + attr +  "} </style>"); 
}

}, after: function(elem,attr){
if($("#cust_style") !== undefined){ 
$("body").append("<style> " + elem + ":after {"  + attr +  "} </style>"); 

} else { $("#cust_style").remove();
$("body").append("<style> " + elem + ":after {"  + attr +  "} </style>"); 
}
}
}

这当前添加了一个 / 或附加一个 Style 元素,该元素包含您的必要属性,该属性将影响目标元素的 After Pseudo 元素。

这可以用作

css.after("someElement"," content: 'Test'; position: 'absolute'; ") // editing / adding styles to :after

css.before( ... ); // to affect the before pseudo element.

如 after: 和 before: 伪元素无法通过 DOM 直接访问,目前无法自由编辑 css 的特定值。

我的方式只是一个例子,它不利于练习,你可以修改它,尝试一些你自己的技巧,并使其适合现实世界的使用。

所以,你自己用这个和其他的实验来做吧!

问候 - 阿达什·赫格德。

4赞 Gaurav Aggarwal 8/9/2016 #13

为什么要添加类或属性,而你可以将 a 附加到 headstyle

$('head').append('<style>.span:after{ content:'changed content' }</style>')
3赞 Abhay Maurya 11/14/2016 #14

这里有很多答案,但没有答案有助于操纵 or 的 css,即使是公认的答案也不行。:before:after

这是我建议的做法。假设你的 HTML 是这样的:

<div id="something">Test</div>

然后你在CSS中设置它的:before,并像这样设计它:

#something:before{
   content:"1st";
   font-size:20px;
   color:red;
}
#something{
  content:'1st';
}

请注意,我还在元素本身中设置了属性,以便您以后可以轻松取出它。 现在有一个点击,你想将:before的颜色更改为绿色,其字体大小为30px。您可以按如下方式实现此目的:contentbutton

在某个类上定义一个具有所需样式的 css:.activeS

.activeS:before{
   color:green !important;
   font-size:30px !important;
 }

现在,您可以通过将类添加到 :before 元素来更改 :before 样式,如下所示:

<button id="changeBefore">Change</button>
<script>
    $('#changeBefore').click(function(){
        $('#something').addClass('activeS');
    });
</script>

如果您只想获取 的内容,可以按以下步骤操作::before

<button id="getContent">Get Content</button>
<script>
    $('#getContent').click(function(){
        console.log($('#something').css('content'));//will print '1st'
    });
</script>

最终,如果你想通过jQuery动态地改变内容,你可以通过如下方式实现::before

<button id="changeBefore">Change</button>
<script>
    var newValue = '22';//coming from somewhere
    var add = '<style>#something:before{content:"'+newValue+'"!important;}</style>';
    $('#changeBefore').click(function(){
        $('body').append(add);
    });
</script>

点击上面的“changeBefore”按钮,将内容更改为“22”,这是一个动态值。:before#something

我希望它有所帮助

0赞 Tariq Javed 6/28/2017 #15

 $('.span').attr('data-txt', 'foo');
        $('.span').click(function () {
         $(this).attr('data-txt',"any other text");
        })
.span{
}
.span:after{ 
  content: attr(data-txt);
 }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='span'></div>

1赞 Yuri 8/1/2017 #16

你可以用我的插件来达到这个目的。

J质量:

(function() {
  $.pseudoElements = {
    length: 0
  };

  var setPseudoElement = function(parameters) {
    if (typeof parameters.argument === 'object' || (parameters.argument !== undefined && parameters.property !== undefined)) {
      for (var element of parameters.elements.get()) {
        if (!element.pseudoElements) element.pseudoElements = {
          styleSheet: null,
          before: {
            index: null,
            properties: null
          },
          after: {
            index: null,
            properties: null
          },
          id: null
        };

        var selector = (function() {
          if (element.pseudoElements.id !== null) {
            if (Number(element.getAttribute('data-pe--id')) !== element.pseudoElements.id) element.setAttribute('data-pe--id', element.pseudoElements.id);
            return '[data-pe--id="' + element.pseudoElements.id + '"]::' + parameters.pseudoElement;
          } else {
            var id = $.pseudoElements.length;
            $.pseudoElements.length++

              element.pseudoElements.id = id;
            element.setAttribute('data-pe--id', id);

            return '[data-pe--id="' + id + '"]::' + parameters.pseudoElement;
          };
        })();

        if (!element.pseudoElements.styleSheet) {
          if (document.styleSheets[0]) {
            element.pseudoElements.styleSheet = document.styleSheets[0];
          } else {
            var styleSheet = document.createElement('style');

            document.head.appendChild(styleSheet);
            element.pseudoElements.styleSheet = styleSheet.sheet;
          };
        };

        if (element.pseudoElements[parameters.pseudoElement].properties && element.pseudoElements[parameters.pseudoElement].index) {
          element.pseudoElements.styleSheet.deleteRule(element.pseudoElements[parameters.pseudoElement].index);
        };

        if (typeof parameters.argument === 'object') {
          parameters.argument = $.extend({}, parameters.argument);

          if (!element.pseudoElements[parameters.pseudoElement].properties && !element.pseudoElements[parameters.pseudoElement].index) {
            var newIndex = element.pseudoElements.styleSheet.rules.length || element.pseudoElements.styleSheet.cssRules.length || element.pseudoElements.styleSheet.length;

            element.pseudoElements[parameters.pseudoElement].index = newIndex;
            element.pseudoElements[parameters.pseudoElement].properties = parameters.argument;
          };

          var properties = '';

          for (var property in parameters.argument) {
            if (typeof parameters.argument[property] === 'function')
              element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property]();
            else
              element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property];
          };

          for (var property in element.pseudoElements[parameters.pseudoElement].properties) {
            properties += property + ': ' + element.pseudoElements[parameters.pseudoElement].properties[property] + ' !important; ';
          };

          element.pseudoElements.styleSheet.addRule(selector, properties, element.pseudoElements[parameters.pseudoElement].index);
        } else if (parameters.argument !== undefined && parameters.property !== undefined) {
          if (!element.pseudoElements[parameters.pseudoElement].properties && !element.pseudoElements[parameters.pseudoElement].index) {
            var newIndex = element.pseudoElements.styleSheet.rules.length || element.pseudoElements.styleSheet.cssRules.length || element.pseudoElements.styleSheet.length;

            element.pseudoElements[parameters.pseudoElement].index = newIndex;
            element.pseudoElements[parameters.pseudoElement].properties = {};
          };

          if (typeof parameters.property === 'function')
            element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] = parameters.property();
          else
            element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] = parameters.property;

          var properties = '';

          for (var property in element.pseudoElements[parameters.pseudoElement].properties) {
            properties += property + ': ' + element.pseudoElements[parameters.pseudoElement].properties[property] + ' !important; ';
          };

          element.pseudoElements.styleSheet.addRule(selector, properties, element.pseudoElements[parameters.pseudoElement].index);
        };
      };

      return $(parameters.elements);
    } else if (parameters.argument !== undefined && parameters.property === undefined) {
      var element = $(parameters.elements).get(0);

      var windowStyle = window.getComputedStyle(
        element, '::' + parameters.pseudoElement
      ).getPropertyValue(parameters.argument);

      if (element.pseudoElements) {
        return $(parameters.elements).get(0).pseudoElements[parameters.pseudoElement].properties[parameters.argument] || windowStyle;
      } else {
        return windowStyle || null;
      };
    } else {
      console.error('Invalid values!');
      return false;
    };
  };

  $.fn.cssBefore = function(argument, property) {
    return setPseudoElement({
      elements: this,
      pseudoElement: 'before',
      argument: argument,
      property: property
    });
  };
  $.fn.cssAfter = function(argument, property) {
    return setPseudoElement({
      elements: this,
      pseudoElement: 'after',
      argument: argument,
      property: property
    });
  };
})();

$(function() {
  $('.element').cssBefore('content', '"New before!"');
});
.element {
  width: 480px;
  margin: 0 auto;
  border: 2px solid red;
}

.element::before {
  content: 'Old before!';
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<div class="element"></div>

应指定值,就像在 jQuery.css 的正常函数中一样

此外,您还可以获取伪元素参数的值,如jQuery.css的正常函数:

console.log( $(element).cssBefore(parameter) );

WSG集团

(function() {
  document.pseudoElements = {
    length: 0
  };

  var setPseudoElement = function(parameters) {
    if (typeof parameters.argument === 'object' || (parameters.argument !== undefined && parameters.property !== undefined)) {
      if (!parameters.element.pseudoElements) parameters.element.pseudoElements = {
        styleSheet: null,
        before: {
          index: null,
          properties: null
        },
        after: {
          index: null,
          properties: null
        },
        id: null
      };

      var selector = (function() {
        if (parameters.element.pseudoElements.id !== null) {
          if (Number(parameters.element.getAttribute('data-pe--id')) !== parameters.element.pseudoElements.id) parameters.element.setAttribute('data-pe--id', parameters.element.pseudoElements.id);
          return '[data-pe--id="' + parameters.element.pseudoElements.id + '"]::' + parameters.pseudoElement;
        } else {
          var id = document.pseudoElements.length;
          document.pseudoElements.length++

            parameters.element.pseudoElements.id = id;
          parameters.element.setAttribute('data-pe--id', id);

          return '[data-pe--id="' + id + '"]::' + parameters.pseudoElement;
        };
      })();

      if (!parameters.element.pseudoElements.styleSheet) {
        if (document.styleSheets[0]) {
          parameters.element.pseudoElements.styleSheet = document.styleSheets[0];
        } else {
          var styleSheet = document.createElement('style');

          document.head.appendChild(styleSheet);
          parameters.element.pseudoElements.styleSheet = styleSheet.sheet;
        };
      };

      if (parameters.element.pseudoElements[parameters.pseudoElement].properties && parameters.element.pseudoElements[parameters.pseudoElement].index) {
        parameters.element.pseudoElements.styleSheet.deleteRule(parameters.element.pseudoElements[parameters.pseudoElement].index);
      };

      if (typeof parameters.argument === 'object') {
        parameters.argument = (function() {
          var cloneObject = typeof parameters.argument.pop === 'function' ? [] : {};

          for (var property in parameters.argument) {
            cloneObject[property] = parameters.argument[property];
          };

          return cloneObject;
        })();

        if (!parameters.element.pseudoElements[parameters.pseudoElement].properties && !parameters.element.pseudoElements[parameters.pseudoElement].index) {
          var newIndex = parameters.element.pseudoElements.styleSheet.rules.length || parameters.element.pseudoElements.styleSheet.cssRules.length || parameters.element.pseudoElements.styleSheet.length;

          parameters.element.pseudoElements[parameters.pseudoElement].index = newIndex;
          parameters.element.pseudoElements[parameters.pseudoElement].properties = parameters.argument;
        };

        var properties = '';

        for (var property in parameters.argument) {
          if (typeof parameters.argument[property] === 'function')
            parameters.element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property]();
          else
            parameters.element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property];
        };

        for (var property in parameters.element.pseudoElements[parameters.pseudoElement].properties) {
          properties += property + ': ' + parameters.element.pseudoElements[parameters.pseudoElement].properties[property] + ' !important; ';
        };

        parameters.element.pseudoElements.styleSheet.addRule(selector, properties, parameters.element.pseudoElements[parameters.pseudoElement].index);
      } else if (parameters.argument !== undefined && parameters.property !== undefined) {
        if (!parameters.element.pseudoElements[parameters.pseudoElement].properties && !parameters.element.pseudoElements[parameters.pseudoElement].index) {
          var newIndex = parameters.element.pseudoElements.styleSheet.rules.length || parameters.element.pseudoElements.styleSheet.cssRules.length || parameters.element.pseudoElements.styleSheet.length;

          parameters.element.pseudoElements[parameters.pseudoElement].index = newIndex;
          parameters.element.pseudoElements[parameters.pseudoElement].properties = {};
        };

        if (typeof parameters.property === 'function')
          parameters.element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] = parameters.property();
        else
          parameters.element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] = parameters.property;

        var properties = '';

        for (var property in parameters.element.pseudoElements[parameters.pseudoElement].properties) {
          properties += property + ': ' + parameters.element.pseudoElements[parameters.pseudoElement].properties[property] + ' !important; ';
        };

        parameters.element.pseudoElements.styleSheet.addRule(selector, properties, parameters.element.pseudoElements[parameters.pseudoElement].index);
      };
    } else if (parameters.argument !== undefined && parameters.property === undefined) {
      var windowStyle = window.getComputedStyle(
        parameters.element, '::' + parameters.pseudoElement
      ).getPropertyValue(parameters.argument);

      if (parameters.element.pseudoElements) {
        return parameters.element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] || windowStyle;
      } else {
        return windowStyle || null;
      };
    } else {
      console.error('Invalid values!');
      return false;
    };
  };

  Object.defineProperty(Element.prototype, 'styleBefore', {
    enumerable: false,
    value: function(argument, property) {
      return setPseudoElement({
        element: this,
        pseudoElement: 'before',
        argument: argument,
        property: property
      });
    }
  });
  Object.defineProperty(Element.prototype, 'styleAfter', {
    enumerable: false,
    value: function(argument, property) {
      return setPseudoElement({
        element: this,
        pseudoElement: 'after',
        argument: argument,
        property: property
      });
    }
  });
})();

document.querySelector('.element').styleBefore('content', '"New before!"');
.element {
  width: 480px;
  margin: 0 auto;
  border: 2px solid red;
}

.element::before {
  content: 'Old before!';
}
<div class="element"></div>


GitHub:https://github.com/yuri-spivak/managing-the-properties-of-pseudo-elements/

1赞 Tony 9/22/2017 #17

其他人评论说,在头部元素上附加一个完整的样式元素,如果你只做一次,这还不错,但如果你需要多次重置它,你最终会得到大量的样式元素。因此,为了防止这种情况,我在头部创建了一个带有 id 的空白样式元素,并像这样替换它的 innerHTML:

<style id="pseudo"></style>

那么 JavaScript 将如下所示:

var pseudo = document.getElementById("pseudo");

function setHeight() {
    let height = document.getElementById("container").clientHeight;
    pseudo.innerHTML = `.class:before { height: ${height}px; }`
}

setHeight()

现在,就我而言,我需要它来根据另一个元素的高度设置一个 before 元素的高度,并且它会在调整大小时发生变化,因此使用它,我可以在每次调整窗口大小时运行,并且它将正确替换。setHeight()<style>

希望这能帮助那些被困在尝试做同样事情的人。

96赞 Temani Afif 4/3/2018 #18

我们还可以依靠自定义属性(又名 CSS 变量)来操作伪元素。我们可以在规范中读到:

自定义属性是普通属性,因此可以在 任何元素,都可以用正常的继承级联规则来解析,可以用@media和其他条件规则来做条件,可以在 HTML 的 style 属性中使用,可以使用 CSSOM 读取或设置,等等。

考虑到这一点,我们的想法是在元素中定义自定义属性,伪元素将简单地继承它;因此,我们可以很容易地修改它。

1)使用内联样式

.box:before {
  content:var(--content,"I am a before element");
  color:var(--color, red);
  font-size:25px;
}
<div class="box"></div>
<div class="box" style="--color:blue;--content:'I am a blue element'"></div>
<div class="box" style="--color:black"></div>
<div class="box" style="--color:#f0f;--content:'another element'"></div>

2)使用CSS和类

.box:before {
  content:var(--content,"I am a before element");
  color:var(--color, red);
  font-size:25px;
}

.blue {
  --color:blue;
  --content:'I am a blue element';
}
.black {
  --color:black;
}
<div class="box"></div>
<div class="box black" ></div>
<div class="box blue"></div>

3)使用javascript

document.querySelectorAll('.box')[0].style.setProperty("--color", "blue");
document.querySelectorAll('.box')[1].style.setProperty("--content", "'I am another element'");
.box:before {
  content:var(--content,"I am a before element");
  color:var(--color, red);
  font-size:25px;
}
<div class="box"></div>
<div class="box"></div>

4)使用jQuery

$('.box').eq(0).css("--color", "blue");
/* the css() function with custom properties works only with a jQuery vesion >= 3.x
   with older version we can use style attribute to set the value. Simply pay
   attention if you already have inline style defined! 
*/
$('.box').eq(1).attr("style","--color:#f0f");
.box:before {
  content:"I am a before element";
  color:var(--color, red);
  font-size:25px;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>


它也可以用于复杂值:

.box {
  --c:"content";
  --b:linear-gradient(red,blue);
  --s:20px;
  --p:0 15px;
}

.box:before {
  content: var(--c);
  background:var(--b);
  color:#fff;
  font-size: calc(2 * var(--s) + 5px);
  padding:var(--p);
}
<div class="box"></div>

您可能会注意到,我正在考虑语法,其中是默认值,也称为回退值。var(--c,value)value

从相同的规范中,我们可以读到:

可以使用 var() 函数将自定义属性的值替换为另一个属性的值。var() 的语法是:

var() = var( <custom-property-name> [, <declaration-value> ]? )

函数的第一个参数是要替换的自定义属性的名称。函数的第二个参数(如果提供)是回退值,当引用的定制属性无效时,该值用作替换值。

后来:

要在属性的值中替换 var():

  1. 如果函数的第一个参数命名的自定义属性受动画污染,并且该函数正在动画属性或其长手之一中使用,请将该自定义属性视为具有此算法其余部分的初始值。var()var()
  2. 如果函数的第一个参数命名的自定义属性的值不是初始值,请将函数替换为相应自定义属性的值。var()var()
  3. 否则,如果函数具有回退值作为其第二个参数,请将该函数替换为回退值。如果回退中有任何引用,也请替换它们。var()var()var()
  4. 否则,包含函数的属性在计算值时无效。var()

如果我们不设置自定义属性,或者将其设置为 OR 它包含无效值,则将使用回退值。如果我们想将自定义属性重置为其默认值,则使用 可能会有所帮助。initialinitial

相关

如何在CSS变量(又名自定义属性)中存储继承值?

箱体模型的 CSS 自定义属性(变量)

评论

0赞 Temani Afif 8/7/2018
@akalata是的,代码需要jQuery版本3.x。我添加了更多细节和jQuery的另一种选择;)
0赞 connexo 9/7/2018
这在 IE 11 中会如何表现?
2赞 Temani Afif 9/7/2018
@connexo像任何好的和现代的功能一样。它不受支持,也无法 caniuse.com/#feat=css-variables
0赞 connexo 9/7/2018
Ofc 我知道这一点,并且由于 IE 11 仍然非常相关,因此我在您答案的介绍部分错过了那条信息。
3赞 LebCit 7/20/2019
这个答案是一个关于使用CSS变量将伪元素与JavaScript关联和修改的深入教程。非常感谢您抽出宝贵时间分享这一非常宝贵的技术。
5赞 Orlandster 9/13/2018 #19

我总是添加我自己的utils函数,看起来像这样。

function setPseudoElContent(selector, value) {    
    document.styleSheets[0].addRule(selector, 'content: "' + value + '";');
}

setPseudoElContent('.class::after', 'Hello World!');

或使用 ES6 功能:

const setPseudoElContent = (selector, value) => {    
    document.styleSheets[0].addRule(selector, `content: "${value}";`);
}

setPseudoElContent('.class::after', 'Hello World!');
1赞 Riccardo Volpe 9/17/2018 #20

我利用 :root 中定义的变量来修改(同样适用于 )伪元素,特别是在以下使用 JavaScript/jQuery 生成随机颜色的演示中更改由 定义的样式的值和另一个 () 的值:CSS:after:beforebackground-coloranchor.sliding-middle-out:hover:aftercontentanchor#reference

[HTML全文]

<a href="#" id="changeColor" class="sliding-middle-out" title="Generate a random color">Change link color</a>
<span id="log"></span>
<h6>
  <a href="https://stackoverflow.com/a/52360188/2149425" id="reference" class="sliding-middle-out" title="Stack Overflow topic">Reference</a>
</h6>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/davidmerfield/randomColor/master/randomColor.js"></script>

CSS的

:root {
    --anchorsFg: #0DAFA4;
}
a, a:visited, a:focus, a:active {
    text-decoration: none;
    color: var(--anchorsFg);
    outline: 0;
    font-style: italic;

    -webkit-transition: color 250ms ease-in-out;
    -moz-transition: color 250ms ease-in-out;
    -ms-transition: color 250ms ease-in-out;
    -o-transition: color 250ms ease-in-out;
    transition: color 250ms ease-in-out;
}
.sliding-middle-out {
    display: inline-block;
    position: relative;
    padding-bottom: 1px;
}
.sliding-middle-out:after {
    content: '';
    display: block;
    margin: auto;
    height: 1px;
    width: 0px;
    background-color: transparent;

    -webkit-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    -moz-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    -ms-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    -o-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
}
.sliding-middle-out:hover:after {
    width: 100%;
    background-color: var(--anchorsFg);
    outline: 0;
}
#reference {
  margin-top: 20px;
}
.sliding-middle-out:before {
  content: attr(data-content);
  display: attr(data-display);
}

JS/j查询

var anchorsFg = randomColor();
$( ".sliding-middle-out" ).hover(function(){
    $( ":root" ).css({"--anchorsFg" : anchorsFg});
});

$( "#reference" ).hover(
 function(){
    $(this).attr("data-content", "Hello World!").attr("data-display", "block").html("");
 },
 function(){
    $(this).attr("data-content", "Reference").attr("data-display", "inline").html("");
 }
);

评论

0赞 BananaAcid 2/3/2019
对 except in 的支持非常稀缺。您可以检查 caniuse.com。 css-variables 支持更好,但仍然没有那么广泛,因为它的支持是相当新的。(另请在 caniuse.com 检查对它的支持)attr()content:root
1赞 BananaAcid 2/3/2019 #21

我创建了一个jQuery插件来添加css伪规则,例如用于特定元素。.css()

用法:

$('body')
  .css({
    backgroundColor: 'white'
  })
  .cssPseudo('after', {
    content: 'attr(title) ", you should try to hover the picture, then click it."',
    position: 'absolute',
    top: 20, left: 20  
  })
  .cssPseudo('hover:after', {
    content: '"Now hover the picture, then click it!"'
  });

-1赞 Coding_snakeZ 11/12/2019 #22

我为你准备了一些不同的东西,既简单又有效。

    <style> 
    .case-after:after { // set your properties here like eg: 
        color:#3fd309 !important; 
     } 
     .case-before:before { // set your properties here like eg: 
        color:#151715 !important; 
     }
 </style>
  // case for after
    $('#button-id').on('click', function() {
        $(".target-div").toggleClass('case-after');
    });

     // case for before
    $('#button-id').on('click', function() {
        $(".target-div").toggleClass('case-before');
    });
2赞 Sumit 3/20/2021 #23

下面的解决方案讲述了如何使用 javascript attr 属性更新伪元素。

在 HTML 中添加一个属性,您可以使用 javascript 和 setAttribute 对其进行操作。

<div 
 id="inputBoxParent" 
 count="0">
      ...
</div>

使用 JS 更新

inputBoxParent.setAttribute('count', value.length)

CSS - 在伪元素中将内容添加为 attr(attributeName)

.input-box-container::after{
  content: attr(count);
}

大功告成!!

const inputBoxParent = document.getElementById("inputBoxParent");
const handleOnChange = (value) => {
  inputBoxParent.setAttribute('count', value.length)
}
.input-box-container {
  position: relative;
  width: 200px;
}
.input-box-container::after{
  position: absolute;
  bottom: 8px;
  right: 10px;
  height: 10px;
  width: 20px;
  content: attr(count);
}
<h4> Type some text inside the box and click outside to see resule i.e. pseudo element content change</h4>
<div 
  id="inputBoxParent" 
  class="input-box-container" 
  count="0">
  <input 
    type="text" 
    id="inputBox" 
    placeholder="type some thing" 
    onchange="handleOnChange(this.value)"
    onkeyup="handleOnChange(this.value)"
 />
</div>

评论

0赞 Michael 9/1/2022
如果一开始就没有属性怎么办?也就是说,如何仅使用 Javascript 构建整个 CSS?如果我阅读内容,它似乎是一个空字符串,但这是一个谎言,因为我的元素没有附加选择器。如果我尝试写入(分配)任何其他值,当我读回它时,它会返回空字符串!content::before
0赞 s3c 8/3/2021 #24

我第一次在给出自己的答案之前没有阅读所有给出的答案,所以我希望这不会咬我......

就我而言,这是附加到 和元素的图标所必需的,它们的工作方式与 和元素略有不同,因为它们没有类。不过添加了破碎的造型。adivbutton<i class="icon-class"></i>icon-classclass="icon-class"

取而代之的是,我为它们添加了一个属性,其中包含应该包含的值,然后这个相当简单的 JavaScript 处理了其余的工作。data-iconelement::before { content: "HERE" }

    {
        const fakeIcons = document.querySelectorAll('[data-icon]')

        for (const iconElement of fakeIcons) {

            const fakeClass = 'fake-' + Array.from(Array(20), () => Math.floor(Math.random() * 36).toString(36)).join('')
            const beforeContent = iconElement.getAttribute('data-icon')

            iconElement.classList.add(fakeClass)

            const style = document.createElement('style')
            style.type = 'text/css'
            style.innerHTML = `

                .${fakeClass}::before {
                    content: "${beforeContent}" !important;
                }

            `
            document.getElementsByTagName('head')[0].appendChild(style)
        }
    }

代码说明:

  • 选择具有指定属性 (data-icon)
  • 循环遍历它们
  • 随机生成一个以 开头的类名,后跟一个随机字母数字字符串fake-
  • Get 属性的值data-icon
  • 将随机生成的类添加到元素中
  • 为伪元素创建样式,将内容设置为先前获取的值::before
  • 在 HTML 元素的末尾添加样式<head>
-1赞 Alex Stephens 10/5/2021 #25

只需在 Inherit 样式之前之后设置伪样式,然后使用 javascript 设置父样式即可。

所以,例如我想改变:before的颜色样式,然后我设置:

.my-style::before{
color: inherit;
}

然后我只需使用 javascript 更改 .my-style 元素上的颜色样式

document.querySelector(".my-style").style.color = red;

工作完成,超级简单

评论

0赞 Alex Stephens 2/28/2022
嗯,一个完全可以接受的简单答案,无缘无故地投了反对票,没有评论。这个网站正在慢慢退化吗???
0赞 s3c 9/22/2022
如果您希望“之前”的文本为红色,但正文为黑色,会发生什么?
-1赞 Pana 2/15/2023 #26

如果你可以用innerHTML编写。这对我的用例很有帮助。

#setNotValidStyle(input) {
  input.style.border = "2px solid #d50000"
  input.style.borderRadius = "3px"
  input.innerHTML = ""
  input.innerHTML = `
    <style id="after">
      .${this.className}:after {
        content: "x";
        font-family: sans-serif;
        position: absolute;
        color: #d50000;
        padding-left: 8px;
       }
     </style>
   `
   return input
}
-1赞 Somen Das 4/9/2023 #27
function getRuleWithSelector(selector) {
  var numSheets = document.styleSheets.length,
    numRules,
    sheetIndex,
    ruleIndex;
  // Search through the style sheets.
  for (sheetIndex = 0; sheetIndex < numSheets; sheetIndex += 1) {
    numRules = document.styleSheets[sheetIndex].cssRules.length;
    for (ruleIndex = 0; ruleIndex < numRules; ruleIndex += 1) {
      if (document.styleSheets[sheetIndex].cssRules[ruleIndex].selectorText == selector) {
        return document.styleSheets[sheetIndex].cssRules[ruleIndex];
      }
    }
  }
  // If we get this far, then the rule doesn't exist.
  // So the return value is undefined.
}

使用此函数选择 css 元素,例如查询选择器,然后只需更改其样式属性,例如

getRuleWithSelector('.navmenu ul li::after').style.top="15%" 

但要正确使用这个函数,你的代码必须在你的 DOM 中导入 CSS 样式表,就像这样的语法

<link rel="stylesheet" href="css/custom.css">

而且它必须来自你的服务器,如果样式表来自另一个服务器,它应该会抛出一个安全错误。

请参阅此帖子文档.styleSheets 不会检测所有样式表,但在大多数情况下它会起作用。

1赞 HamzaElkotb 5/25/2023 #28

在 Vanilla JS 中,你可以做这样的事情: 1- 与其直接编辑 ::before ::after,不如使用 CSS 变量!

在 CSS 中:

:root{
   --bg: red;
}

我们的要素:

div::after{
   background: var(--bg) 
}

在 JS 中,将其更改为这样:

let r = document.querySelector(':root');
r.style.setProperty('--bg', `blue`)