5

I understood:

You can't modify pseudo elements through JavaScript since they are not part of the DOM

I also knew we could add properties in pseudo-element by appending style -- more.

However, the appending solution could only add value. adding doesn't mean the ability of changing dynamically. I also need to the ability of replacing the property value.

Therefore, I tried to use attr() to change background image dynamically. However, currently attr only supports content property - more.

So what else I can try here?

In order to adding more context of the question, basically, I want to dynamically update avatar image in chat. The avatar image is setted in pseudo-element(before and after). Here is the code-pen of Chat UI -- http://codepen.io/clintioo/pen/HAkjq

Thank you very much!

Community
  • 1
  • 1
Haoyu Chen
  • 1,760
  • 1
  • 22
  • 32
  • Is not better define a tag with an img inside or a background? The technique you are using is mandatory to write base64 images in your CSS, it is all except dynamic. You need to override the css for new avatars. I think that is better to forget that technique for this purpose and put this variable content outside the css. – Marcos Pérez Gude Dec 15 '15 at 17:38
  • Possible duplicate of [Selecting and manipulating CSS pseudo-elements such as ::before and ::after using jQuery](http://stackoverflow.com/questions/5041494/selecting-and-manipulating-css-pseudo-elements-such-as-before-and-after-usin) – Asons Dec 15 '15 at 17:39
  • Check [this answer](http://stackoverflow.com/a/21709814/2827823) in the above dupe question, it has a part that shows exactly how to manipulate a pseudo element's properties. – Asons Dec 15 '15 at 17:42

4 Answers4

2

Here is the part in the "duplicate" that shows how to get, add and change CSS pseudo-element property dynamically using Javascript.

Stack snippet

/*  on page load  */
window.addEventListener('load', function() {

  /*  get button and add click event to it  */
  var btn = document.querySelector('button');
  btn.addEventListener("click", function(){

    /*  get first <p> element  */
    var el1 = document.querySelector('p.first');

    /*  get second <p> element  */
    var el2 = document.querySelector('p.second');

    /*  get first <p> pseudo's "content" property value  */
    var str = window.getComputedStyle(el1,':before').getPropertyValue('content');

    /*  get first <p> pseudo's "color" property value  */
    var col = window.getComputedStyle(el1,':before').getPropertyValue('color');

    /*  dynamically add a rule to the stylesheet so the second <p>
        will get the same "content"/"color" value as the first  */
    document.styleSheets[0].addRule('p.second:before', 'content: ' + str + ' ; color: ' + col + ';');

    /*  dynamically add a rule to the stylesheet that override the
        first <p> "color" to green  */
    document.styleSheets[0].addRule('p.first:before', 'color: green;');
  
  });
  
});
p.first:before {
    content:"foo";
    color: red;
}

button {
  display: block;
  width: 220px;
  margin-top: 50px;
}
<p class="first">This is a paragraph</p>
<p class="second">This is another paragraph</p>

<button>Change/Add pseudo properties</button>
Asons
  • 84,923
  • 12
  • 110
  • 165
2

As said in other answers, there is a way to inject styles that will afect your pseudo element.

A somewhat simpler workaround for your specific case could be to just inherit the background from the base element (since you are not using it)

function changebkg ()  {
 target1 = document.getElementById('test');
 target1.style.backgroundImage = "url(http://placekitten.com/1000/750)";
}
#test {
  font-size: 40px;
  position: relative;
  display: inline-block;
  color: black;
  background-size: 0px;
  background-color: lightblue;
}

#test:after {
  content: "";
  position: absolute;
  left: 200px;
  top: 20px;
  width: 200px;
  height: 200px;
  background-image: inherit;
  border: solid 1px;
  background-size: contain;
}
<div id="test" onclick="changebkg();">click me</div>
vals
  • 61,425
  • 11
  • 89
  • 138
0

As you have just learned, attr() isn't supported anywhere else but the content property at the moment. If your requirement is to set other CSS properties dynamically, then I'm afraid you can't do much of that within CSS alone. The closest you can get is to generate static CSS dynamically through a script, as shown in a number of answers to the first question you link to.

In the specific case of user avatars, I don't see why you aren't just marking those up using img elements instead, which would obviate this issue entirely.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
0

You can create a css file and then inject it into the DOM.

var avatar_css_for_avatar = document.createElement('style');
avatar_css_for_avatar.type = 'text/css';
avatar_css_for_avatar.innerHTML = '.user-avatar-id:before { background-image: url(url_of_image); }';
document.getElementsByTagName('head')[0].appendChild(avatar_css_for_avatar);

document.getElementById('someElementId').className = 'user-avatar-id';
James
  • 679
  • 1
  • 8
  • 22
  • It's funny to see how to make this things, but it's really neccesary or we are testing performance and capabilities of browsers? I think that this doesn't offers nothing good to final users. I don't talk only of your answer, I talk about the entire question – Marcos Pérez Gude Dec 15 '15 at 17:41
  • Well, for starters, it's a bad idea to represent images without an img element, who ever indexes pages, like Google will not see the image itself, it will not appear, why? because it does not follow global conventions, it is important even if you're gonna print a document, because this pseudo-elements or even background-image will not be printed. And neither question nor answer are related to browser performance / capabilities, it is a matter of conventions and how things work around them. – James Dec 15 '15 at 17:55