Why doesn't getComputedStyle work with pseudo

2020-02-01 03:57发布

问题:

The function window.getComputedStyle is supposed to be able to get the computed style of pseudo classes like :hover, according to the documentation.

It's also explained as an answer in another question

But as the last comment says in that question, in fact it doesn't work at all, it just returns the normal style, not the :hover style. You can see for yourself in this jsfiddle. The alert returns the red color, not the green one.

The documentation on developer.mozilla.org also has an example, but that doesn't work either - see here.

In this question the answerer states in a comment that it won't work at all, but without giving an explanation.

Could it be that the stylesheet has to be fully rendered before the function returns the correct value? I've tried setting some delays, but nothing seems to work.

I've tried the latest Firefox, Chrome and IE browsers. Does anybody know why this function is not working as expected?

回答1:

var style = window.getComputedStyle(element[, pseudoElt]);

where pseudoElt is "a string specifying the pseudo-element to match". A pseudo-element is something like ::before or ::after, those are elements which are generated by CSS styles. :hover, :visited or other similar effects are pseuodo-classes. They won't create new elements but apply specialized class styles to the element.

It's not possible to get the computed style of a pseudo-class, at least not with getComputedStyle. You can however traverse through the CSS rules and try to find a fitting selector, but I won't recommend you to do this, since some browsers won't follow the DOM-Level-2-Style rules and you would have to check which rule will affect your specific element:

/* Style */
p a:hover{ color:yellow; background:black;}
p > a:hover{ color:green; background:white;}
p > a+a:hover{ color:fuchsia; background:blue;}
// JS
var i,j, sel = /a:hover/;
for(i = 0; i < document.styleSheets.length; ++i){
    for(j = 0; j < document.styleSheets[i].cssRules.length; ++j){    
        if(sel.test(document.styleSheets[i].cssRules[j].selectorText)){
            console.log(
                document.styleSheets[i].cssRules[j].selectorText,
                document.styleSheets[i].cssRules[j].style.cssText
            );
        }
    }
}
Result:
p a:hover color: yellow; background: none repeat scroll 0% 0% black; 
p > a:hover color: green; background: none repeat scroll 0% 0% white;
p > a + a:hover color: fuchsia; background: none repeat scroll 0% 0% blue;

See also:

  • MDN: getComputedStyle examples
  • W3C: CSS2: 5.10 Pseudo-elements and pseudo-classes
  • SO: Setting CSS pseudo-class rules from JavaScript


回答2:

Note that there is a way to do this at least for Chrome with the remote debugging port turned on. Basically you need to use a WebSocket, connect to the remote debugger url, then issue the following commands:

send  { id: 1, method: "Inspector.enable" }
send  { id: 2, method: "DOM.enable" }
send  { id: 3, method: "CSS.enable" }
send  { id: 4, method: "DOM.getDocument" }
send  { id: 5, method: "DOM.querySelector", params: { nodeId: 1, selector: <<whatever you want>> } }
nodeId = response.result.nodeId
send  { id: 6, method: "CSS.forcePseudoState", params: { nodeId:, forcedPseudoClasses: [ "hover" <<or whatever>> ] } }

Then you can use the regular getComputedStyle, or the CSS.getComputedStyleForNode debugger API.