开发者问题收集

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

2011-02-18
901403

是否有任何方法可以使用 jQuery 选择/操作 CSS 伪元素,例如 ::before::after (以及带有一个分号的旧版本)?

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

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

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

3个回答

您还可以使用数据属性将内容传递给伪元素,然后使用 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';
}
Nick Kline
2011-04-20

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

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


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

1) 添加/删除预定的类

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

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

然后,您可以使用 jQuery(或原生 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 必须预先编写,因此 :before:after 的内容不是完全动态的

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

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

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>

我们可以将 document.querySelector('p') 替换为 $('p')[0] 使用 jQuery 时,代码会稍微短一些。

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

3) 更改不同的 DOM 属性

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

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

JS:

$('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 中的 attr 只能应用于内容字符串,而不能应用于 URL 或 RGB 颜色
Blazemonger
2014-02-11

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

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

不过,您总是可以找到其他解决方法,例如:

  • 将样式应用于一个或多个任意类的伪元素,然后在类之间切换(请参阅 seucolega 的答案 举个简单的例子)——这是惯用的方式,因为它使用简单的选择器(伪元素不是)来区分元素和元素状态,这是它们的预期使用方式

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

BoltClock
2011-02-18