114

This selects all <B> tags directly preceded by <A> tags:

A+B {
    /* styling */
}

What is the selector for all <A> tags directly followed by <B> tags?

Here's sample HTML fitting my question:

<a>some text</a>
<b>some text</b>
Trojan
  • 2,256
  • 28
  • 40
Mostafa Farghaly
  • 1,407
  • 2
  • 10
  • 15
  • 3
    Pease give us a DOM example how `A` and `B` are related. – Gumbo Jul 15 '09 at 16:38
  • 5
    They are related in that they are siblings, and B is followed by A. The OP wants to select all `b`s which are followed by `a`s, similar to the `a+b` where you can select all `b`s that are preceded directly by `a`. – Anthony Apr 07 '12 at 02:38
  • 2.5 years later, is there any update to this answer? I'm also looking to target a followed by b. – chovy Feb 09 '18 at 16:49

5 Answers5

59

Do you mean to style A given that it has a B element directly inside or followed? Like this:

<A>
    <B>
    </B>
</A>

// OR

<A>
</A>
<B>
</B>

You can't do such a thing in CSS (yet). Eric Meyer states that this kind of selector has been discussed quite a few times on the CSS mailing list, and isn’t doable. Dave Hyatt, one of the core WebKit developers, comments with a good explanation of why it can’t be done.

Check out: Shaun Inman's blog post and the comment by Eric Meyer.
David Hyatt weighs in, too.

Nick Presta
  • 28,134
  • 6
  • 57
  • 76
35

You can’t in css.

Edit: To be a bit more helpful, if you use for example jQuery (a JavaScript library), you can use .prev().

bdesham
  • 15,430
  • 13
  • 79
  • 123
jeroen
  • 91,079
  • 21
  • 114
  • 132
20

You can ONLY do the converse: This selects all tags directly preceded by tags.

This is logically equivalent to your request.

I often use this to style a row of many checkboxes with labels

CSS:

label+input {
    margin-left: 4px;
}

DOM:

<input id="a" name="a" type="checkbox"/><label for="a">...</label>
<input id="b" name="b" type="checkbox"/><label for="b">...</label>
<input id="c" name="c" type="checkbox"/><label for="c">...</label>
Marco Marsala
  • 2,332
  • 5
  • 25
  • 39
  • 3
    I think you meant to type "input+label" in the CSS so that the margin-left is applied to the label. – CAK2 Sep 10 '19 at 04:30
  • 4
    @CAK2 - I think he meant it right. By doing `label+input` the margin is applied to all `input` elements **starting from the second one**. It is a creative way to create space among them but not at the beginning or at then end of the row. In this case, it is equivalent to `input:not(:first-child)`. – David Mar 12 '20 at 21:18
16

You can now use the :has() css selector (caniuse):

    .first:has(+ .second) {
        background: #ff0000;
    }

That can be read: select all elements with class ".first" that are followed by element of class ".second"

    <div class="first">Foo</div>
    <div class="second">Bar</div>
fluminis
  • 3,575
  • 4
  • 34
  • 47
8

Although it's not very handy, nowadays you could achieve this behavior by reversing the order of your elements both when you generate the HTML and by applying the CSS rules: display: flex and flex-direction: column-reverse

ul {
  display: flex;
  flex-direction: column-reverse;
}

.b ~ .a {
  color: red;
}
<ul>
    <li class="a">A 3</li>
    <li class="c">C 2</li>
    <li class="c">C 1</li>
    <li class="b">B 1</li>
    <li class="a">A 2</li>
    <li class="a">A 1</li>
</ul>

Also, if you have 2 or more inline elements, you could achieve it by applying float: right, as they will be displayed in reverse order:

ul {
  float: left;
  list-style-type: none;
}

li {
  float: right;
}

li:not(:first-child) {
  margin-right: 20px;
}

.b ~ .a {
  color: red;
}
<ul>
    <li class="a">A 3</li>
    <li class="c">C 2</li>
    <li class="c">C 1</li>
    <li class="b">B 1</li>
    <li class="a">A 2</li>
    <li class="a">A 1</li>
</ul>
Mihai Matei
  • 24,166
  • 5
  • 32
  • 50
  • 2
    This hack is likely to hurt accessibility, because the order of the elements in the DOM should be logical. People who navigate with keyboard and people who use screen readers will navigate elements in the DOM order, not taking into account the flexblox tweak. – neiya Jul 07 '22 at 08:46