使用JQuery更改:before CSS选择器的宽度属性

87

我有一个页面包含一张图片,我使用:before CSS选择器为其添加样式。
这张图片是动态的,因此它没有固定的宽度;所以我需要动态设置:before规则的宽度。
我想在客户端使用jQuery来实现它。
假设如下:

.column:before{
    width: 300px;
    float: left;
    content: "";
    height: 430px;
}

.column{
    width: 500px;
    float: right;
    padding: 5px;
    overflow: hidden;
    text-align: justify;
}

如何使用JQuery仅更改具有:before选择器的类的宽度属性(而不是没有选择器的类)?


https://dev59.com/J2445IYBdhLWcg3wGWd7 - The GiG
你能告诉我们你想要实现的效果吗?也许有更好的方法来做你所尝试的事情。 - Starx
这不是重复的 @temani-afif - PHP Worm...
@PHPWorm... 这不是重复的吗? - Temani Afif
@TemaniAfif 在重复的问题中,它展示了如何改变内容,而不是 ::after 或 ::before 的宽度。此外,在那个问题的答案中无法改变 after 和 before 的宽度。 - PHP Worm...
@PHPWorm...请阅读所有的重复内容。我可以清楚地从您的评论中理解到,您没有费心阅读所有的答案。 - Temani Afif
7个回答

115

我认为没有一种jQuery的方法可以直接访问伪类规则,但是您可以始终将新的style元素附加到文档的头部,例如:

$('head').append('<style>.column:before{width:800px !important;}</style>');

可以在这里查看演示。

我还记得曾经看到过一个插件来解决这个问题,但不幸的是我第一次谷歌搜索时没有找到它。


2
值得注意的一件事是,尽管您的示例使用了“one”,以便不会出现多个<style>标签,但如果您需要在页面上多次执行此操作或需要切换状态,则需要在完成后进行清理。http://jsfiddle.net/xK6k4/2/是如何“清理”的示例实现。 - dev_row
1
这里有一种方法可以为每个迭代创建自己的类:http://jsfiddle.net/TB824/ - Heraldmonkey
这是我根据这个答案所做的事情:http://jsfiddle.net/p1yc5bsw/ 通过使用text()方法,您可以重复使用同一个元素,而无需每次销毁它。 - Tristan Shelton
1
这部分是感谢(因为这个解决方案很聪明),但我也想明确告诉任何查看的人,<style>标签可以有类。这从未发生在我身上。 - crowhill
只是想提醒一下。我也使用了append,但没有使用!important。在Firefox中可以工作,但在Chrome和Edge中无法工作。所以不要忘记使用!important - Andris
这个回答发布已经将近8年了,但在Stack Overflow上我仍然认为这是最好、最简单的一个。向你致敬! - Caladin00

63

伪元素是阴影DOM的一部分,无法修改(但可以查询其值)。

不过,有时可以通过使用类来绕过这个问题,例如:

jQuery

$('#element').addClass('some-class');

CSS

.some-class:before {
    /* change your properties here */
}

这可能不适合您的查询,但它确实演示了有时可以实现此模式。

要获取伪元素的值,请尝试以下代码...

var pseudoElementContent = window.getComputedStyle($('#element')[0], ':before')
  .getPropertyValue('content')

28

伪元素不是DOM的一部分,因此无法使用jQuery或Javascript进行操作。

但正如接受的答案所指出的那样,您可以使用JS来添加一个样式块,以结束对伪元素的样式设置。


我没有投票,但是可以通过JS对元素进行样式设置,以创建更多适用的样式规则(如已接受的答案所述),而样式设置无疑是一种操纵形式... - nnnnnn
@nnnnnn,好的,但它并不是通过自身进行操作,而是通过添加样式规则来进行操作,浏览器读取规则,从而进行操作。虽然这是一种奇怪的漏洞,但我同意样式设置也是一种操作形式。 - Starx

22
答案应该是Jain。你不能通过伪选择器选择元素,但可以使用insertRule在样式表中添加新规则。
我为您制作了一个可以解决问题的东西:
var addRule = function(sheet, selector, styles) {
    if (sheet.insertRule) return sheet.insertRule(selector + " {" + styles + "}", sheet.cssRules.length);
    if (sheet.addRule) return sheet.addRule(selector, styles);
};

addRule(document.styleSheets[0], "body:before", "content: 'foo'");

http://fiddle.jshell.net/MDyxg/1/

为了变得超级酷(并且回答问题真的),我将其再次推出,并将其封装在一个jQuery插件中(不过,仍然不需要jquery!):

/*!
 * jquery.addrule.js 0.0.1 - https://gist.github.com/yckart/5563717/
 * Add css-rules to an existing stylesheet.
 *
 * @see https://dev59.com/dmkw5IYBdhLWcg3wNXz2#16507264
 *
 * Copyright (c) 2013 Yannick Albert (http://yckart.com)
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php).
 * 2013/05/12
 **/

(function ($) {

    window.addRule = function (selector, styles, sheet) {

        styles = (function (styles) {
            if (typeof styles === "string") return styles;
            var clone = "";
            for (var p in styles) {
                if (styles.hasOwnProperty(p)) {
                    var val = styles[p];
                    p = p.replace(/([A-Z])/g, "-$1").toLowerCase(); // convert to dash-case
                    clone += p + ":" + (p === "content" ? '"' + val + '"' : val) + "; ";
                }
            }
            return clone;
        }(styles));
        sheet = sheet || document.styleSheets[document.styleSheets.length - 1];

        if (sheet.insertRule) sheet.insertRule(selector + " {" + styles + "}", sheet.cssRules.length);
        else if (sheet.addRule) sheet.addRule(selector, styles);

        return this;

    };

    if ($) $.fn.addRule = function (styles, sheet) {
        addRule(this.selector, styles, sheet);
        return this;
    };

}(window.jQuery));

使用方法非常简单:

$("body:after").addRule({
    content: "foo",
    color: "red",
    fontSize: "32px"
});

// or without jquery
addRule("body:after", {
    content: "foo",
    color: "red",
    fontSize: "32px"
});

https://gist.github.com/yckart/5563717


非常酷。我稍微调整了一下(https://gist.github.com/corysimmons/10949352),使其适用于我的情况,但似乎在Firefox中无法工作。 - corysimmons
@CorySimmons 看起来很不错,我已经在我的代码片段中添加了一条评论 :) - yckart
把它变成一个仓库,我会和你一起工作。现在它在FF或旧版IE中无法工作,但是可以修复。 - corysimmons
这可能会在某些浏览器中引发跨域安全问题。例如,在Chrome中,sheet.cssRules将为空。 - MichaelKaeser
它可以工作。但是选择正确的样式表索引非常重要。我使用 console.log(document.styleSheets); 找到需要的那个。 - Vlad

5
一种选择是在图像上使用属性,并使用jQuery进行修改。然后在CSS中使用该值:
HTML(请注意,我假设 .column 是一个 div ,但它可以是任何内容):
<div class="column" bf-width=100 >
    <img src="..." />
</div>

jQuery:

// General use:
$('.column').attr('bf-width', 100);
// With your image, along the lines of:
$('.column').attr('bf-width', $('img').width());

然后为了在CSS中使用该值:

.column:before {
    content: attr(data-content) 'px';
    /* ... */
}

这将从.column中获取属性值,并应用于之前。
来源:CSS attr(注意带有before的示例),jQuery attr

1
这听起来很不错,但对我没有用。你提到的MDN参考说:“attr()函数可以与任何CSS属性一起使用,但除content以外的属性的支持是实验性的。” - Philipp Zedler
这是原始问题中最好的答案:https://dev59.com/J2445IYBdhLWcg3wGWd7#5734583 - Avatar

4
你可以尝试从基类继承属性:

您可以尝试从基类继承属性:

var width = 2;
var interval = setInterval(function () {
    var element = document.getElementById('box');
    width += 0.0625;
    element.style.width = width + 'em';
    if (width >= 7) clearInterval(interval);
}, 50);
.box {
    /* Set property */
    width:4em;
    height:2em;
    background-color:#d42;
    position:relative;
}
.box:after {
    /* Inherit property */
    width:inherit;
    content:"";
    height:1em;
    background-color:#2b4;
    position:absolute;
    top:100%;
}
<div id="box" class="box"></div>


3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接