Changing width property of a :before css selector using JQuery

JavascriptJqueryCss

Javascript Problem Overview


I have a page that has an image in it and I styled it using :before CSS selectors.
The image is dynamic so it hasn't a fixed width; So I need to set :before rule's width dynamically.
I want do it in client side using JQuery.
Assume this:

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

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

How Can I only change the width property of class with :before selector (and not one without it) using JQuery?

Javascript Solutions


Solution 1 - Javascript

I don't think there's a jQuery-way to directly access the pseudoclass' rules, but you could always append a new style element to the document's head like:

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

See a live demo here

I also remember having seen a plugin that tackles this issue once but I couldn't find it on first googling unfortunately.

Solution 2 - Javascript

Pseudo elements are part of the shadow DOM and can not be modified (but can have their values queried).

However, sometimes you can get around that by using classes, for example.

jQuery
$('#element').addClass('some-class');
CSS
.some-class:before {
    /* change your properties here */
}

This may not be suitable for your query, but it does demonstrate you can achieve this pattern sometimes.

To get a pseudo element's value, try some code like...

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

Solution 3 - Javascript

Pseudo-elements are not part of the DOM, so they can't be manipulated using jQuery or Javascript.

But as pointed out in the accepted answer, you can use the JS to append a style block which ends of styling the pseudo-elements.

Solution 4 - Javascript

The answer should be Jain. You can not select an element via pseudo-selector, but you can add a new rule to your stylesheet with insertRule.

I made something that should work for you:

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/

To be super-cool (and to answer the question really) I rolled it out again and wrapped this in a jQuery-plugin (however, jquery is still not required!):

/*!
 * jquery.addrule.js 0.0.1 - https://gist.github.com/yckart/5563717/
 * Add css-rules to an existing stylesheet.
 *
 * @see http://stackoverflow.com/a/16507264/1250044
 *
 * 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));

The usage is quite simple:

$("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

Solution 5 - Javascript

You may try to inherit property from the base class:

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>

Solution 6 - Javascript

One option is to use an attribute on the image, and modify that using jQuery. Then take that value in CSS:

HTML (note I'm assuming .cloumn is a div but it could be anything):

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

And then in order to use that value in CSS:

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

This will grab the attribute value from .column, and apply it on the before.

Sources: CSS attr (note the examples with before), jQuery attr.

Solution 7 - Javascript

As Boltclock states in his answer to Selecting and manipulating CSS pseudo-elements such as ::before and ::after using jQuery

> Although they are rendered by browsers through CSS as if they were like other real DOM elements, pseudo-elements themselves are not part of the DOM, and thus you can't select and manipulate them with jQuery.

Might just be best to set the style with jQuery instead of using the pseudo CSS selector.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAriyanView Question on Stackoverflow
Solution 1 - Javascriptm90View Answer on Stackoverflow
Solution 2 - JavascriptalexView Answer on Stackoverflow
Solution 3 - JavascriptStarxView Answer on Stackoverflow
Solution 4 - JavascriptyckartView Answer on Stackoverflow
Solution 5 - JavascriptAlexander ShutauView Answer on Stackoverflow
Solution 6 - JavascriptSelfishView Answer on Stackoverflow
Solution 7 - JavascriptDean_WilsonView Answer on Stackoverflow