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.
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.
Nice!
Is this technique available when using the CSS 2 spec? Or is It 3 only?
I tested it in Safari, Opera, Firefox, and IE 7 and it seemed to be working in all of them. Must be CSS 2.1 =)
Nice. This could be very helpful. Great job Chris – good find!
Hi Chris, css-tricks.com is really helpful, I came here once by mistake but I can not complain, I liked this last trick. peace for all css-trickers
Can you please tell me what font was used for the word “image” in your demo?
Its good to see some CSS again and deviate from the whole JavaScript scene for a bit. Nice job by the way!
@Noddy: I think it’s Agenda-SemiBold, but at that size, it pretty much looks like Trebuchet MS (all caps, letterspacing 1px)
The adjacent sibling selector doesn’t work in IE6 …still a good use of the selector though.
A nice and simple example of the adjacent sibling selector. Good one.
Really helpful…but doesn’t work in IE6. The adjacent selector is CSS spec for long time already, but only modern browsers support this.
This is fan f’n tastic! This is exactly the solution to my problem of the different headers and paragraph combinations; H1 is big so you want it to have more margin-bottom than H3 for example, but more again when there’s a header nested under a header… and so on and so forth.
I identified this as a problem way back, and thought there was no solution. I love being proved wrong in these cases.
Yeah, only *modern* browser support – no IE6. You need to draw the line somewhere tho :) IE6 is what, seven years old? I’m at the point where I make sure my sites are accessible under IE6, but they don’t always have to be pixel perfect.
Great technique, I can actually use exactly that functionality in a current project! Just FYI, sitepoint CSS ref says Safari and Firefox have full support, IE6 has no support, and IE7 and Opera have buggy support (although from reading it, it seems safe for most purposes in IE7 and Opera).