How to determine if an HTML element has a pseudo element?

Is there a way to determine if a given HTML element has a pseudo element ( ::before / ::after ) applied to it without calling

 window.getComputedStyle(element, ":before/:after"); 

EDITED : NO answer

The problem with getComputedStyle is in performance. I need to check every element on the page whether it has a pseudo-element or not - why performance is very important. I tried to access cssRules from document.styleSheets to find the selector with :: before or :: after at the end, delete it and find the elements matched with the rest of the selector, but this solution has its problems:

  • styleSheets from another domain are not available
  • there may be thousands of cssRules to test (again performance)

I also tried to compare the sizes and offsets of elements with and without pseudo-elements, but nothing worked. Even if there is no exact method, I would be happy to find a way to reduce the number of elements in order to check at least 30%.


When I'm sure the element has a pseudo-element, I can finally call getComputedStyle to examine the style of the pseudo-element and change it. This part works great.


EDITED . I have no control over the original page. Page styles can be dynamically loaded from different domains. Suppose my code is as a content script or library, for which , for example , you need to change all the foreground pseudo-elements to a certain color, calculated based on the other CSS properties of this pseudo-element.

So, the main problem is that the changes are based on other CSS properties, and you cannot set the same style for all pseudo-elements without actually getting the calculated pseudo-element style and calculating the changes.

For example, you have a youtube.com page and you need to find all the pseudo-elements and

  • If this pseudo-element has a background image, then scale the element
  • If this pseudo-element has only text, change its color to red
  • etc...
+5
source share
2 answers

What exactly causes problems with your existing solution?

This method of passing through elements:

 var allElements = document.getElementsByTagName("*"); for (var i = allElements.length; i--;) { //var usedStyle = window.getComputedStyle(allElements[i], ":before/:after"); ... } 

makes about thousand elements in 1 ms.

And the call to getComputedStyle should not be too slow, since it retrieves the data that was already calculated at the time of the call (on the rendered document).

So, all this will really work fast enough. Yes, this is an O(N) task in principle, but it starts once, right?

+1
source

I think getComputedStyle() is the only reliable way to find out if an element is attached to it with a pseudo-element.

But since there is no way to edit it from the DOM method, this means that you will need to add a new rule in the document.

So, a simple solution, if, as indicated in the last editor, you will apply the same rules in all pseudo-elements, use the * wildcard selector:

*:before,*:after{ /*your rules*/ }

 var style = document.createElement('style'); style.innerHTML = `*:before,*:after{ color: green !important; }`; setTimeout(function() { document.head.appendChild(style); }, 1500); 
 div:before { content: 'hello'; color: blue; } div:after { content: 'world'; color: red; } 
 <div></div> 
+2
source

Source: https://habr.com/ru/post/1258678/


All Articles