Fine Use for the Adjacent Sibling (“+”) Selector

Avatar of Chris Coyier
Chris Coyier on (Updated on )

UGURUS offers elite coaching and mentorship for agency owners looking to grow. Start with the free Agency Accelerator today.

My friend Richard came to me with an interesting problem yesterday. He was using some API of some kind that was returning to him a big list of companies. Each company had text, and most (but not all) also had an image. He wanted to use the image if they had one, but if he was showing the image he didn’t want to show the text also. The solution had to be to output both the image and text and then attempt to hide the text if possible.

VIEW DEMO

Here is an example of what the output HTML might look like:

<img src="images/image-110.png" alt="image" />
<span>Text</span>

<br /><br />
		
<img src="images/image-110.png" alt="image" />
<span>Text</span>
		
<br /><br />
		
<span>Text</span>

Here you can see the first two “groups” have both and image and text, while the last one only has text. This is an ideal scenario for the adjacent sibling selector! Every CSS nerds dream! What we really need to do here is target only the spans which immediately follow an image. We can do that, and solve the problem, like so:

img {
	vertical-align: middle;
	z-index: 9999;
	position: relative;
}
span {
	z-index: 1;
}
img+span {
	margin-left: -110px;
}

The plain English of the adjacent sibling selector statement is “Look for spans which immediately follow images and kick them over to the left.” The span sitting there all by itself is unaffected, but the top two are kicked to the left. The negative left margin does the kicking, and is able to tuck the text underneath the image thanks to the high z-index value. The relative positioning is actually needed here to jumpstart the z-index into actually working.

I went with the negative margin solution because, with images turned off, this method still provides accessible data. However, if the text being hidden is too large to fit behind the image (or the image is transparent), this would be a problem. You could also consider a “visibility: hidden;” or “display: none” instead of the negative left margin, which would absolutely work, but be less accessible.

VIEW DEMO