Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a selector like *+* safe to use?

I recently came across this CSS selector while trying to find a way to easily space out major blog elements such as paragraphs and images. An example of its use would be something like this:

.post *+* {margin-top: 15px;}
/* or... */
.post > *+* {margin-top: 15px;}
/* if you don't want the margin to apply to nested elements */

At first glance, it seemed pretty useful. So my question is: What downsides are there to using these selectors?

Specifically:

  1. What's the browser support like for this?

  2. Are there any cases you wouldn't want an even margin spacing between elements in an article and if not, is it easier to declare this first and then overwrite or simply declare each element individually?

  3. Does this have performance issues since you're selecting everything twice?

like image 994
webdesserts Avatar asked Feb 14 '12 20:02

webdesserts


2 Answers

  1. What's the browser support like for this?

    Basically, IE7+ and any other modern browser.

    There may be corner cases for each browser depending on what elements are actually being selected or queried with the sibling combinator +, but I wouldn't worry about those as much as the fact that the margin is being applied to just about any element that's a sibling for no practical reason.

  2. Are there any cases you wouldn't want an even margin spacing between elements in an article and if not, is it easier to declare this first and then overwrite or simply declare each element individually?

    It does seem pretty useful at first glance, but if you think about it, it'll probably be a much better idea to be more specific about what to apply the margin to. This is one rule that I can imagine will be overridden many, many times throughout the rest of the stylesheet by other specific selectors, making it quite redundant and even undesired in many cases. I can't think of any real-world use for a rule like your example.

    Bear in mind that, in this specific case, vertical margins will collapse, so you only need to define vertical margins for a set of elements without having to resort to applying margin-top exclusively to all of an element's following siblings.

  3. Does this have performance issues since you're selecting everything twice?

    Actually, it's not selecting everything twice. The browser only looks at each element once, then determines whether each element follows another one under the same parent element. It doesn't care what kind of element it follows, as long as it follows another. It doesn't go around selecting every element again then compare to see if they're siblings of each other.

    Now, people say that using the universal selector * in conjunction with just about any combinator causes rendering performance catastrophes, so people say that this kind of stuff should be avoided at all costs. But this stuff is hardly important at all (honestly, a selector like * + * is only a few microseconds slower than p + p), so you really don't need to worry about it. Consider the utility of the CSS rule itself first, then decide whether you really need the rule based on that.


Now with all that said (it's getting pretty late here), I would probably have rewritten the example like this, based on what I said above regarding collapsing margins:

.post > * { margin: 15px 0; }

It's probably only worth replacing the * with p if you know that the only children you want to space out are paragraphs:

.post > p { margin: 15px 0; }

Or any paragraphs within .post for that matter (e.g. within blockquotes):

.post p { margin: 15px 0; }

(* being used with the descendant selector is fair game, I'll admit; the child combinator, on the other hand, is limited to only one level of nesting, so for anyone obsessing about performance, this won't hurt at all.)

like image 184
BoltClock Avatar answered Nov 11 '22 07:11

BoltClock


It's called the "Sibling Selector".

According to SitePoint, it's supported in all recent browsers and in IE8+. IE7 has a few limitations explained on the SitePoint page, but will mostly work as well.

It's defined in the CSS2 spec.

About the performance: a lot of CSS is overriding other selectors. That's part of the cascading nature of it. Also, performance varies so much between render engines that it's not practical to worry about performance when it comes to CSS.

like image 37
Brigand Avatar answered Nov 11 '22 07:11

Brigand