Question

I'd like to be able to use the ::outside pseudoelement, but apparently none of the major browsers support it (based on my testing today).

Is there some kind of JS polyfill that enables this selector? Or is there a good technique for simulating this?

Was it helpful?

Solution

You are correct: no browser in existence has implemented any of the new features in the ancient CSS3 Generated and Replaced Content module, so you won't be able to try the proposed pseudo-elements. In fact, they're planning to rewrite the module itself, so the current working draft should be considered abandoned, and unfortunately there's no telling the fate of these proposed features.

Anyway, I'm not aware of any JS polyfills available for these pseudo-elements either, so you're out of luck on writing selectors using ::outside in your CSS.

The closest you can get is to wrap actual elements around the elements for which you want to style with a container... this is cheaply accomplished with, for example, jQuery's .wrap() or .wrapAll().

So, instead of doing this:

p::outside {
    display: block;
    border: 3px solid #00f;
}

You'd do this:

$('p').wrap('<div class="outside-p" />');
/* 
 * Notice that you can't select only .outside-p that contains p:only-child,
 * so you'll have to come up with esoteric class names.
 */
.outside-p {
    border: 3px solid #00f;
}

jsFiddle preview

There are some caveats to this, however:

  • This is largely dependent on the DOM; you won't be able to wrap certain elements around others depending on the circumstances. Even if you can, those wrapper elements may end up interfering with the behavior or even the styling of the actual parent elements.

    For example, it prevents you from using the child selector in cases like this:

    article > p
    

    Where you intend to jQuery.wrap() those p elements, as then those wrapper elements will break the parent-child relationship between article and p.

  • The spec states that ::outside pseudo-elements, like ::before and ::after, are supposed to inherit styles from the elements that generate them. If you use JavaScript/jQuery to add wrappers, those wrappers will inherit styles from their parent elements and not the ones they're wrapping. This has never been a problem when polyfilling ::before and ::after, as they're intended to be inserted as child elements anyway, following inheritance rules normally.

OTHER TIPS

I finally added this snippet to my page:

  $('ol > li').each(function(){
        var $this = $(this);
        var $content = $($this.contents());
        $content.wrapAll('<p class="liwrap"/>');
  });

This adds a p inside the li, which avoids the problem of breaking child selectors, and requiring esoteric names for classes (because there is no parent selector). It also avoids the problems of not inheriting styles, because the ::outside can be replaced with a ::before.

To achieve the right visual effect, however, requires a negative margin to raise the inner p to the level of the generated content.

It looks like you are using jQuery, and in which case, I would suggest a small modification to your code

$('ol > li').wrapInner("<p class='liwrap' />");

It's a little cleaner and simpler to follow, without so many variables or function calls.

Edit: As awe rightly points out, this is an optimisation of Marcins solution which...

adds a p inside the li, which avoids the problem of breaking child selectors

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top