0

How can I check in javascript (with jQuery) if the 'content' property is set on a before or after pseudo element? In chrome, window.getComputedStyle(elem, '::before').getPropertyValue('content') returns an empty string both when 'content' is set to an empty string and when content is not set.

I have thought of one solution: set other properties such as width and height and check if the computed style is affected; I would, however, like to minimize the number of calls to getComputedStyle.

Thanks

chris.va.rao
  • 373
  • 1
  • 10
  • 1
    If the pseudo element was positioned absolutely, it would have no effect on the width/height of the 'parent'. What is it you are trying to do and why? – Paulie_D Sep 16 '14 at 14:52
  • I am writing a script which creates a stylesheet based on the computed style of some elements. I want to skip css rules for before/after pseudo elements if the content attribute was not set. – chris.va.rao Sep 16 '14 at 14:57
  • Like to show how content is set in your css? – Martin Ernst Sep 16 '14 at 15:10

4 Answers4

1

Simply add an if truthy clause to test that it has some value.

E.G:

var before = window.getComputedStyle(elem, ':before').getPropertyValue('content');
if(before && before!=="none"){//<-- (IE / FF fix) check it doesn't equal 'none'
    //content: is defined but it could still be an empty string
    alert("Before="+before);
} else {
    //there is no :before content: defined at all
}

Here's the demo. Try changing the css :before content to test it.

Also, you can reduce the code still further by using
getComputedStyle(elem, ':before').content
instead of
window.getComputedStyle(elem, ':before').getPropertyValue('content').

Moob
  • 14,420
  • 1
  • 34
  • 47
  • @torazaburo. Yes, and if you test the fiddle you'll see it *does* distinguish between these. – Moob Sep 16 '14 at 16:05
  • @torazaburo Are you trying the demo fiddle? Here's a version with 3 tests (content, empty content and no content): http://jsfiddle.net/Le1tLbda/7/ – Moob Sep 16 '14 at 16:33
  • Strange, this solution worked even though it failed the first time I tried it. There must have been a bug in my code that I failed to notice at the time. – chris.va.rao Sep 16 '14 at 16:45
  • Ah, here is the peculiarity that confused me: http://jsfiddle.net/hrmvs98d/ When the content is an empty string, quotes will be added to the computed content property, but when content is set to a non-empty string, quotes will not be added to the computed content property. – chris.va.rao Sep 16 '14 at 16:52
  • This method fails in FF and IE when `content` is **not set** or set to **none** (without quotes!). Both return string 'none' in both cases. See my answer below. – Martin Ernst Sep 16 '14 at 20:51
  • @MartinErnst Thanks. I've updated my answer accordingly. – Moob Sep 17 '14 at 09:09
0

Chrome and Opera have a bug with getComputedStyle() for PseudoElements:

When the style of #elem::before is set to {display: none;} or {content: none} or when the content is just not set, both return the computed style of #elem.

But in practise it's no problem: A PseudoElement with display: none ore no content will not be displayed, so you must set content to show it.

In css content must be quoted:

div::before { content: "something"}   or { content: "" } // empty string.

When you now retrieve .getComputedStyle(...).content you get not an empty string but a string with two quotes in it. That way you can distinguish your both cases.

Take care when using the content value in javascript, it must be doublequoted.

As in CSS3 specified content can explicitely set to "nothing":

#elem::before { content: none } // without quotes!

In this case FF and IE returns none, Chrome and Opera really nothing.

JSFidlle here to test all cases.

Martin Ernst
  • 3,199
  • 1
  • 12
  • 12
  • can you provide a link to the bugtracker or something that supports this claim? – Woodrow Barlow Sep 16 '14 at 16:31
  • @Woodrow Barlow. Sorry, I can't. I'm working on a jQuery plugin that will enable the control of PseudoElements with javascript. My answer reflects my experience I made with this topic (and it's **not all** experience, targeting Safari is horrible!). – Martin Ernst Sep 16 '14 at 16:52
0

I suggest using window.getMatchedCSSRules, then looking through the rules:

function hasBeforeContentProperty(elt) {
    return [].some.call(
        window.getMatchedCSSRules(elt, '::before'),
        function(rule) {
            return /content/.test(rule.cssText);
        }
    );
}

This needs some bullet-proofing and sanity testing, but the concept is find the rules applicable to the ::before pseudo-element, then examine their cssText property to see if a content is specified, whether as empty string or otherwise. Note that you need to do the textual scan of rule.cssText instead of looking at rule.style.content, since the latter will always be the empty string even if rule does not specify content.

-1

You need to use a real DOM element instead of a pseudo one. You can't modify pseudo elements through JavaScript, is not a DOM element

Victor Sitnic
  • 380
  • 2
  • 6
  • I am creating stylesheets based on the computed style of the passed in elements and placing clones of the elements in an iframe where the computed styles are applied. I need only to generate additional stylesheets. – chris.va.rao Sep 16 '14 at 15:03