12

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?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Marcin
  • 48,559
  • 18
  • 128
  • 201
  • 1
    `::outside`? I have never heard of this selector. Do you have a link to some sort of documentation that explains it? – animuson May 02 '12 at 18:35
  • 1
    @animuson http://www.w3.org/TR/css3-content/#wrapping – Marcin May 02 '12 at 18:37
  • 1
    @animuson: All new pseudo-elements as of CSS3 have been moved into their respective modules, so `::outside` has *never* appeared in Selectors. – BoltClock May 03 '12 at 03:57
  • @Marcin: You should add an explanation of what the `::outside` pseudo-element is meant to do. I assume it's meant to be a wrapper element as requested on the [CSSWG GitHub issue tracker](https://github.com/w3c/csswg-drafts/issues/588). – Sebastian Zartner Oct 18 '16 at 09:00
  • @SebastianZartner It's part of the css3-content proposal. – Marcin Oct 18 '16 at 15:29
  • Actually, I see that it's been removed from the current draft. – Marcin Oct 18 '16 at 15:30
  • 2
    Indeed, it has. css3-content now redirects to css-content-3 with the latest draft, which was, for almost a year now, only available at drafts.csswg.org. @Sebastian Zartner: You can still find the older draft here: http://www.w3.org/TR/2003/WD-css3-content-20030514/ – BoltClock Oct 18 '16 at 15:42

3 Answers3

18

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.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • See my answer, which I think fixes a couple of issues with wrapping around the target of an `::outside`. – Marcin May 03 '12 at 11:10
  • 4
    How come it's low priority? Wouldn't it make writing really clean HTML a breeze? I hate how sometimes you just have to wrap elements in divs to achieve a desired styling effect. – Cameron Martin Aug 19 '14 at 03:21
  • @Cameron Martin: Apparently, people care more about animations, flexbox, and all that jazz. – BoltClock Mar 05 '15 at 14:44
  • 1
    Worth noting that the rewrite you predicted has happened, and this appears to no longer exist. – Marcin Oct 18 '16 at 15:30
2

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.

Marcin
  • 48,559
  • 18
  • 128
  • 201
2

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

SEoF
  • 1,092
  • 14
  • 26
  • 1
    Just to clarify: This is an improvement to the solution in [Marcins answer](http://stackoverflow.com/a/10429936/109392). See his answer for more details on how this solves the original issue. – awe Feb 06 '14 at 07:34