csssasscss-selectors

CSS/SCSS Adjacent sibling selector between certain types


Is there any way to accomplish all combinations of sibling selectors without having to write them all one by one?

Let's say I want font-size: 30px; in the second element, and any element can be an a, b or span.

I would normally write:

a + b, b + a, a + span, span + a, b + span, span + b {
  font-size: 30px;
}

But that's leads to n*(n-1) combinations!

I'm looking forward something like this:

{a,b,span} + {a,b,span} {
  font-size: 30px;
}

Though if there is no alternatively let me know if the best choice is to always make sure that the elements contained are always the types I want so I can use *:

* + * {...}

CSS solution if possible, or SCSS if it leads to a cleaner or the only unique possible solution.

Edit:

Some of you are suggesting nth-child. Whilst this is good for one or two formattings, that was not my aim (my fault, should've probably specified it better).

I meant to give result to a long div of text containing different formatting. I.e.:

<div class="text">
  <span>The weather</span> <i>is</is> <img src... /> <b>nice</b> <span>today</span>
</div>

So, what I thought at first was to change the ones I wanted to format to <div class="whatever"> so I could just focus div with certain class. But then again, something like { span, i, b } would be the most ideal.


Solution

  • In compliant browsers (sigh...), there's the option of using:

    :matches(a, b, span) + :matches(a, b, span):nth-child(2) {
      color: #f90;
    }
    

    To style the :nth-child(2) element that is an <a>, <b> or <span> element following a previous sibling element of the type <a>, <b> or <span>.

    The problem, of course, is that "in compliant browsers" part, and so far IE and Edge are both reluctant to join that particular party. Also, Webkit (Chrome, Opera and Android) are implementing a vendor-prefixed incorrect version using :-webkit-any(). On the plus side, though, as I write now, Safari, both desktop and iOS implement the :matches() pseudo-class correctly.

    So, if you don't require IE/Edge support you have the option of:

    :-webkit-any(a, b, span) + :-webkit-any(a, b, span):nth-child(2) {
      color: #f90;
    }
    :-moz-any(a, b, span) + :-moz-any(a, b, span):nth-child(2) {
      color: #f90;
    }
    :matches(a, b, span) + :matches(a, b, span):nth-child(2) {
      color: #f90;
    }
    

    a::before {
      content: 'link';
    }
    b::before {
      content: 'bold'
    }
    span::before {
      content: 'span';
    }
    em::before {
      content: 'em';
    }
    :-webkit-any(a,
    b,
    span) +:-webkit-any(a,
    b,
    span):nth-child(2) {
      color: #f90;
    }
    :-moz-any(a,
    b,
    span) +:-moz-any(a,
    b,
    span):nth-child(2) {
      color: #f90;
    }
    :matches(a,
    b,
    span) +:matches(a,
    b,
    span):nth-child(2) {
      color: #f90;
    }
    <div>
      <a href="#"></a> <span></span>
    </div>
    <div><span></span>
      <a href="#"></a>
    </div>
    <div><b></b>  <span></span>
    </div>
    <div><b></b>
      <a href="#"></a>
    </div>
    <div><b></b>  <em></em>
    </div>
    <div><em></em>
      <a href="#"></a>
    </div>

    JS Fiddle demo.

    References: