There are no tracking or monitoring cookies on this site. There are only cookies used for documentation examples related to cookies.
Close

Processing...
This may take a few seconds.

The previous adjacent sibling combinator (-)

Well, that's a heck of a mouthful, isn't it?

Sometimes you see the question "is there a previous adjacent combinator in CSS"? And the answer is always "no."

But what does that even mean?

The previous adjacent sibling, if you were to inspect the DOM in DevTools, would be the element immediately above the element that you are looking at. You have to have an element to look at, from which to view the one previous to it. "Sibling" just mean on the same DOM level, if you like. It's not a parent or child element.

In other words, it's the element behind the one you are looking at. It's not the parent element, and it's not a child element, and it's not the one immediately after the one you are looking at. The previous adjacent sibling is the element before.

"Combinator" is referring to the symbol used in CSS that is being used in combination with other things.

Example:

<div>                <--- This is the previous adjacent sibling...
Hi there.
</div>
<div> <--- ... if you are looking at this one. And this is the previous adjacent sibling...
<span>
Hello again.
</span>
<div>
<p> <--- ... if you are looking at this one.
<span>
Hi!
</span>
</p>

Ok - now that has been cleared up! (If it isn't clear by this point, look up any words above that you don't know, in a dictionary, and re-read it carefully.)

 

But I don't even know what the adjacent sibling combinator is in CSS yet!

Ah - that's the + symbol! In CSS, the adjacent sibling combinator, the "+" symbol, goes forward in the DOM to look at the next element.

If you wanted to style all div tags that immediately followed a p tag, but only if they did follow immediately after a p tag, you could do this:

p + div {
color: blue;
}

That would only affect the first div that appeared in the DOM immediately after any p tags, if any existed on the page.

If none existed on the page, then nothing would happen.

Ah! Ok, you can tell me about the amazing "previous" one now. I think I'm getting it, sort of.

With the previous adjacent sibling combinator, we can find the prior element to an element, if things match up.

It's the opposite of the "+" combinator in CSS. Unsurprisingly, it is the "-" symbol.

In ACSS, the previous adjacent sibling selector selects the previous adjacent sibling, if the selector matches.

It only works on target selectors. You cannot use it with event selectors. Why? Performance reasons. I know, I know, it's a cop-out. But hey, that's probably why no one has implemented it yet for CSS. At least it's partly here in ACSS, right? Why? Because it's useful for targeting elements in UI.

Example:

button:click {
fade-out: & - div 100ms
}

When any button on the page was clicked, that would fade out the div that immediately came before it in the DOM. "& - div" is where the magic happens. "&" refers to the element that received the event, and the "-" is the previous adjacent combinator, and so the "div" represents the div that immediately appears before the button, if it is there. If it isn't there, nothing will happen.

Another example:

button:click {
    #hamburger - div {
        background-color: blue;
    }
}

When any button was clicked, that would give the div a background of blue that immediately preceded the element with an id of "hamburger". It would only affect the div before the #hamburger element - nothing else.

A bit more on the technical side...

But what about a complex combination? What happens here:

button:click {
#hamburger - div > p {
}
}

That's a great question! Like CSS, this particular combinator works in a simple way. Internally, when the core has the #hamburger located, and the "-", it will take whatever is left and see if it matches to the element just before the #hamburger.

So it isn't like the closest parent combinator. You cannot move up and down the DOM with it. In that example, if the element before the #hamburger element matches to "div > p", then it matches.

The official spec for this combinator would look something like this:

"The previous-sibling combinator is made of the "minus sign" (-) character that separates two sequences of simple selectors. The elements represented by the two sequences share the same parent in the document tree and the element represented by the first sequence immediately follows the element represented by the second one."

 

That's great, dude. Why did you waste your time implementing it?

That's a great question. Why, indeed!

Basically, it's one less class or ID, or attribute, or state, etc. that you need to set in order to affect that particular preceding element.

You now don't have to write up any additional code in order to affect the element immediately before another one.

It's like the parent combinator. It's not a magic bullet that will solve all your problems. But it is one less reference that you have to set up with a class, id or attribute, etc.

The act of assigning state in the first place is a arbitrary workaround. It's not science that makes you do it, it's just what you have to do sometimes. But it's not as direct a method of just knocking on the door on the element and saying "hi, here I am and now I am going to affect you" (insert meme).

And ACSS is all about removing arbitrary computing instructions in order to make things more A to B.

You never had this particular combinator before, so you have always had to work around this. It may not make a massive different to your life, having it here, but at some point you may suddenly remember "oh yeah, I don't need to add a class or ID there, I can just use the 'previous adjacent sibling combinator', and that's all I need."

And then you try it, it works, and you go, "wow that was cool," grab yourself another coffee and pat yourself on the back for being ninja. Now you just need to remember that it's there...