66

I need to get :after and assign it to variable. It is possible?

querySelectorAll doesn't work.

alert(some_div_with_pseudo.querySelectorAll('::after')[0]) // undefined
Michael Benjamin
  • 307,417
  • 93
  • 525
  • 644
A. Petrov
  • 792
  • 1
  • 5
  • 6
  • 1
    You _cannot_, as the name 'pseudo' implies. These are not part of the actual DOM, they are, to javascript, style rules applied to an actual element. – somethinghere Aug 10 '16 at 13:50
  • 1
    JavaScript *absolutely* can read/write CSS pseudo `content`; see my answer below for a *write-mode* example. – John May 23 '19 at 15:15
  • 1
    This question is not a duplicate of the other question. You will note that the other question involves jQuery, and the selected answer doesn’t answer this one. – Manngo Nov 10 '20 at 19:35

5 Answers5

48

The short answer is that you can’t. It’s not there yet.

JavaScript has access to the DOM, which is built when the page is loaded from HTML, and modified further when JavaScript manipulates it.

A pseudo element is generated by CSS, rather than HTML or JavaScript. It is there purely to give CSS something to hang on to, but it all happens without JavaScript having any idea.

This is how it should be. In the overall scheme of things, the pages starts off as HTML. JavaScript can be used to modify its behaviour and to manipulate the content on one hand, and CSS can be used to control the presentation of the result:

HTML [→ JavaScript] → CSS → Result

You’ll see that CSS, complete with pseudo elements, comes at the end, so JavaScript doesn’t get a look in.

See also:

Edit

It seems that in modern JavaScript there is a workaround using window.getComputedStyle(element,pseudoElement):

var element = document.querySelector(' … ');
var styles = window.getComputedStyle(element,':after')
var content = styles['content'];
Manngo
  • 10,878
  • 7
  • 66
  • 88
  • 1
    The problem with getComputedStyle is that if you put the wrong literal, you will get the same result as if you didn't put the 2nd variable at all, e.g. getComputedStyle(element,':afterrrr')==getComputedStyle(element) so the function behaves wierdly. – Nathan B Jul 21 '21 at 10:55
  • Does anyone know how to get updated styles when the pseudo element is `:hover`ed or `:active`. It seems `getComputedStyle` only returns the original style of the pseudo element. `getComputedStyle` does, however, return the updated the style of ***regular*** elements when they're `:hover`ed or `:active` – Levi Uzodike Apr 28 '22 at 20:06
30

You should dos something like this:

window.getComputedStyle(
    document.querySelector('somedivId'), ':after'
);

Sample here: https://jsfiddle.net/cfwmqbvn/

Didier Aupest
  • 3,048
  • 2
  • 25
  • 35
  • 1
    It return style. I need element – A. Petrov Aug 10 '16 at 11:45
  • 24
    ":after" is a pseudo element, not an element. You can not return a dom node, it isn't one - all you can do it get the styles :) – MrBizle Aug 10 '16 at 13:37
  • @MrBizle Its a shadow dom element. – John Libes Mar 02 '20 at 17:58
  • @MrBizle how can I check if the pseudo element exist? – Kick Buttowski Aug 16 '21 at 02:02
  • Does anyone know how to get updated styles when the pseudo element is `:hover`ed or `:active`. It seems `getComputedStyle` only returns the original style of the pseudo element. `getComputedStyle` does, however, return the updated the style of regular elements when they're `:hover`ed or `:active` – Levi Uzodike Apr 28 '22 at 20:41
5

I use an arrow pointing in the direction that the content and sidebar will toggle to/from via a CSS pseudo-element. The code below is effectively a write mode however it is entirely possible to read CSS pseudo-element content as well.

Since there is a bit involved I'll also post the prerequisites (source: JAB Creations web platform JavaScript documentation, if anything missing look it up there) so those who wish to try it out can fairly quickly do so.

CSS

#menu a[href*='sidebar']::after {content: '\2192' !important;}

JavaScript Use

css_rule_set('#menu a[href*="sidebar"]::after','content','"\u2192"','important');

JavaScript Prerequisites

var sidebar = 20;


function id_(id)
{
 return (document.getElementById(id)) ? document.getElementById(id) : false;
}


function css_rule_set(selector,property,value,important)
{
 try
 {
  for (var i = 0; i<document.styleSheets.length; i++)
  {
   var ss = document.styleSheets[i];
   var r = ss.cssRules ? ss.cssRules : ss.rules;

   for (var j = 0; j<r.length; j++)
   {
    if (r[j].selectorText && r[j].selectorText==selector)
    {
     if (typeof important=='undefined') {r[j].style.setProperty(property,value);}
     else {r[j].style.setProperty(property,value,'important');}
     break;
    }
   }
  }
 }
 catch(e) {if (e.name !== 'SecurityError') {console.log('Developer: '+e);}}
}


function sidebar_toggle()
{
 if (id_('menu_mobile')) {id_('menu_mobile').checked = false;}

 if (getComputedStyle(id_('side')).getPropertyValue('display') == 'none')
 {
  css_rule_set('#menu a[href*="sidebar"]::after','content','"\u2192"','important');

  if (is_mobile())
  {
   css_rule_set('main','display','none','important');
   css_rule_set('#side','width','100%','important');
   css_rule_set('#side','display','block','important');
  }
  else
  {
   css_rule_set('main','width',(100 - sidebar)+'%');
   css_rule_set('#side','display','block');
  }
 }
 else
 {
  css_rule_set('#menu a[href*="sidebar"]::after','content','"\u2190"','important');

  if (is_mobile())
  {
   css_rule_set('main','display','block','important');
   css_rule_set('main','width','100%','important');
   css_rule_set('#side','display','none','important');
  }
  else
  {
   css_rule_set('main','width','100%','important');
   css_rule_set('#side','display','none');
  }
 }
John
  • 11,516
  • 11
  • 87
  • 151
  • This is a really interesting solution. If I'm understanding this correctly, you're getting looping through the styleSheet objects, looking within those for selectors that match your target (in the case of the pseudo element `'#menu a[href*="sidebar"]::after'` ) and then updating the individual declaration within that with the new value you provide? It isn't the usecase in this question, but this would only work if there is already an existing style declaration targeting the pseudo element right? – Brice Mar 04 '22 at 17:10
1

There is a way in JavaScript to access value of pseudo elements without any library. To get the value, you need to use the 'getComputedStyle' function. The second parameter is optional.

let elem = window.getComputedStyle(parent, ':before');
alert(elem.getPropertyValue('background'))

This will do alert the value of pseudo element.

SamiunNafis
  • 133
  • 2
  • 9
0

let elem = window.getComputedStyle(document.querySelector('#item'), ':after'); console.log(elem.getPropertyValue('content'))

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 08 '22 at 04:50