Change the style of :before and :after pseudo-elements? [duplicate]

It's not possible to directly access pseudo-elements with Javascript as they're not part of the DOM. You can read their style using the optional second argument - which most, although not all, browsers in current use support - in .getComputedStyle() but you can't directly change their style.

However, you could change their style indirectly by adding in a new style element containing new rules. For example:

http://jsfiddle.net/sjFML/

The initial CSS assigns the :before pseudo-element with a green background, which is turned to black by inserting a new style element.

HTML:

<div id="theDiv"></div>

CSS:

#theDiv {
    height: 100px;
    background: red;
}

#theDiv:before {
    content:' ';
    display: block;
    width: 50px;
    height: 50px;
    background: green;
}

Javascript:

var styleElem = document.head.appendChild(document.createElement("style"));

styleElem.innerHTML = "#theDiv:before {background: black;}";

There is also solution with CSS Variables (aka custom properties):

var style = document.querySelector('.foo').style;
style.setProperty('--background', 'url(http://placekitten.com/200/300)');
.foo::before {
  background: var(--background);
  content: '';
  display: block;
  width: 200px;
  height: 300px;
}
<div class="foo"></div>

For browser support see Can I use and here is link to Ponyfill (same as Polyfill, but you need to call a function)

Ponyfill work with CSS in link and style CSS, but if you use code below, you can set the variable like with setProperty (it will run only in browsers that don't support CSS Variables like IE11)

var style = document.querySelector('.foo').style;
style.setProperty('--background', 'url(http://placekitten.com/200/300)');
cssVars({
  variables: {'--background': 'url(http://placekitten.com/200/300)'}
});
.foo::before {
  background: var(--background);
  content: '';
  display: block;
  width: 200px;
  height: 300px;
}
<div class="foo"></div>
<script src="https://unpkg.com/css-vars-ponyfill@2/dist/css-vars-ponyfill.min.js"></script>

Unfortunately the cssVar ponyfill is global like setting var on :root. If you need to support IE11 or other old browser you can try to search for better polyfill or library.


It is possible to change the value of the ::after element but not directly. Gotta be sneaky. Works on all browsers.

Let's say you have an element:

<div class="thing1">hi here</class>

And you got an ::after css style for it:

.thing1::after {
    content:"I am what comes ::after a thing :)";
    display: inline-block;
    background-color: #4455ff;
    padding:3px;
    border: 1px solid #000000;    }

And you want to change the content and the background color of the ::after pseudo-element using javascript. To do this, make a second CSS rule with the changes you want applied and have both the current class name and add a totally new class name to it. So let's say I want to change the content and the background color a bit and leave the rest of the stuff, the same:

.thing1.extra_stuff::after {
  content:"Some parts of me, changed!";
  background-color: #8888cc;    }

Now, you can just fire off an onclick javascript event that will apply those two new rules to the element, by adding the second class name, to the element :) yay

function change_the_after_attribute(thing_button) {
    thing_button.className="thing1 extra_stuff";    }

https://jsfiddle.net/bt8n26a5/


fun side notes:

You can use thing_button.classList.add("extra_stuff"); and thing_button.classList.remove("extra_stuff"); to make the function applicable to many different elements with many different class names, and to be able to remove your changes, as well!

Use a variable instead of the "extra_stuff" string to change what you're adding more dynamically.