协慌网

登录 贡献 社区

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

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

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

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

如何使用 jQuery 将'foo' 更改为'bar'?

答案

您还可以使用 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';
}

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

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


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

1)添加 / 删除预定的类

在这种方法中,您已经在 CSS 中创建了一个具有不同的类: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 必须预先编写,因此: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>

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

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

3)改变不同的 DOM 属性

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

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

您只能在运行时通过 CSSOM(想想window.getComputedStyle() )直接访问伪元素样式,而 jQuery 除了.css()之外没有公开它,这也是一种不支持伪元素的方法。

但是,您总能找到其他方法,例如:

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

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