Grow your CSS skills. Land your dream job.

Descendent Attribute Selectors and Performance

  • # May 20, 2013 at 1:31 am

    Consider the following selector:

    body[data-xyz="abc"] #abc{}

    As we know css selectors are evaluated RTL, so first it will select the #abc node and then it will walk up the tree until it reaches the body.

    My question is as it walks up the tree what does it do at each node?

    Does it:
    1) Check whether that node is a body element and only if it is whether it has a data-xyz attribute
    or
    2) Check that node to see if it has a data-xyz attribute and only if it does whether it is a body element

    I would assume it is (1 ) because that is more efficient, though if so it slightly confuses me as to how thats fits with RTL evaluation, or is an attribute selector considered bound with the element tag as a single unit?

    TIA
    Rob

    # May 20, 2013 at 1:39 am

    Ooops, pressed post to soon, I forgot to add:

    Whatever the answer to the above is, how would that change if i substituted a class selector for the attribute selector?

    body.xyz-abc #abc{}

    # May 20, 2013 at 5:21 am

    body.xyz-abc #abc{}
    body[data-xyz="abc"] #abc{}

    >Does it: 1) Check whether that node is a body element and only if it is whether it has a data-xyz attribute or 2) Check that node to see if it has a data-xyz attribute and only if it does whether it is a body element

    It checks to see if there is an element with an ID of #abc (which is why there should be only one per page).

    Thus…you could stop there.

    If, however, you choose to carry on, it check to see if the selected element is in a body with the relative attribute be it a data attribute or a class.

    It works the same way regardless of what attribute you have on the body.

    Note however that

    body.xyz-abc #abc{}

    is not the same as

    body .xyz-abc #abc{}

    Whatever you do, the simple `#abc` is enough. Anything else is bloat.

    # May 20, 2013 at 7:05 am

    I believe he wants to style `#abc` different based on whether or not the body element has `data-xyz=”abc”`.

    If you run this test: http://jsperf.com/id-class-and-tag you can conclude it checks for tag first, then id/class (other way around it wouldn’t be that much slower). I can imagine it’s the same with attribute selectors. This doesn’t offend the RTL rule as that only applies to combined selectors (descendant, child and sibling combinators).

    I don’t think you’d notice any difference either way since the rightmost selector is an id one, making the whole selector very fast.

    # May 21, 2013 at 10:14 am

    Thanks – I used jsPerf to test a few things out (should have done this first I guess).

    Tested checking ‘body[data-xyz="abc"] #abc{}’ from a depth of 500 nodes and again at 50 nodes.

    There was little difference in performance which confirms that it must check the element first on each node.

    Using just a straight access on the ‘#abc’ node for comparison, checking the attribute on the body was 70% slower.

    So you can draw from this that walking the DOM tree is very fast and the ‘slowness’ is really just a factor of needing to access two nodes instead of one.

    Oh and curiously using an attribute on the body was faster than a class on the body although the difference was trivial about 1%.

    Rob

Viewing 5 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic.

*May or may not contain any actual "CSS" or "Tricks".