🤯 50% Off! 700+ courses, assessments, and books

Eric’s Universal Child Selector

    Alex Walker

    A couple of weeks ago Eric Meyer published a little revelation on mimicking the Universal Child Selector. Although I read it at the time, it probably took a week to sink in to the point where it was of real use to me. I thought I’d look at that here.

    In case, you’re not familiar with the child selector, here’s the exec summary.

    Although it sounds like some weird ‘sci-fi cloning experiment’, the ‘child selector’ is actually a nifty idea that allows you to set rules that will only be applied when a given element is directly inside a specified other.

    In practice, where:

    ‘div#box p {…}’ effects every P anywhere inside a DIV called ‘#box’

    ‘div#box>p {…}’ effects only the P’s one level inside the DIV called ‘#box’.

    Now, this would be pretty handy, if it wasn’t for the fact Internet Explorer completely and utterly ignores it. As a consequence, the child selector has generally only been of limited usefulness — most often used as a hack/filter which allows you to target styles specifically to non-IE browsers.

    That was the state of play until a few weeks ago when Eric pointed out you can get a rough equivalent of the child selector by using a combination of rules that IE does recognize.

    Let’s look at a typical situation where it comes in handy.

    Take a typical two-column layout like this.

    To begin with, I (like many others) usually prefer to get all browsers ‘marching in-step’ by over-riding all their ‘factory-set’ margins and paddings. Using the universal selector (‘*’), that’s fairly effortless.

    body * {margin:0 padding:0}

    Of course, now all my content wll be squashed uncomfortably against the edges of my major structural DIV’s. However, solving that issue with the obvious solution — i.e. giving them ‘padding’ — requires the extra complexity of box model hacks and other nasties which I prefer to leave out. Instead if I can add ‘margin’ to the items inside my DIVs, I can duck those issues completely. Something like this might do the trick for all our main DIVs.

    #content *, #nav *, #links * {margin:3px 10px 8px 10px}

    This works beautifully. At least, it does until we need to place more complex markup inside our DIVs and we start to run into ‘runaway margins’. Since our universal selector has added margin to everything, each table cell, row, list item, definition list and wrapper DIV adds it’s own margin to that of the elements surrounding it, stacking up the margins and giving us a generally sucky result.

    Eric’s simple solution gives us an antidote by turning the universal selector on itself, like this:

    #nav * * {margin:0}

    As you can see in the example, by setting a more specific rule for ‘anything that’s two levels or more inside #nav‘, we’re able to counteract our first rule on all items below the first level (‘#links’ is unfixed for the sake of the demo). Nifty.

    So, are there any side effects? Not really, although the true child selector works without having any effect at all on the elements below it — Eric’s solution means that you’re forcibly setting those elements, killing any inherited styles from higher levels of the hierachy. Not much you can do about that.

    Even so, this looks pretty handy to me.