A tutorial about how to create an overlay effect to show some more details of an item or image. The effect is CSS-only and uses a combination of the :checked pseudo-class with the sibling combinator.

In this tutorial we’ll create a little overlay effect with CSS using a combination of the :checked pseudo-class with sibling combinators. The idea is to make an image or element clickable and transition to an overlay-like state that will show us some annotation boxes.

The theme preview images used in this tutorial are by talented Ana Segota and you can purchase her themes and templates here.

The beautiful arrow icons are by Alessio Atzeni and you can find them here.

Please note: the result of this tutorial will only work as intended in browsers that support the respective CSS properties.

The Markup

Our structure will consist of a part for some title and description, and a preview part. The preview part will have the overlay effect. The idea is to add a checkbox, an image and a division for the annotations, containing spans. The trick is to actually put the checkbox on top of the other elements, so that it remains clickable. It needs to stay first in the structure though because we want to be able “to reach” its siblings, the image and the annotations division:

<div class="ao-item"> <div class="ao-details"> <h2>Some title</h2> <p>Some description</p> </div> <div class="ao-preview"> <input type="checkbox" id="ao-toggle" class="ao-toggle" name="ao-toggle" /> <img src="images/image01.jpg" alt="image01" /> <div class="ao-annotations"> <span>Full Localisation Support</span> <span>Custom Image Widget</span> <span>Blog and Contact Widgets</span> <span>Easy Theme Options</span> <span>4 Footer Widget Columns</span> </div> </div> </div>

There can be any number of spans. We will position each one individually.

Let’s take a look at the CSS.

The CSS

Note that we will exclude vendor prefixes. You will of course find them in the files.

The division with the class ao-item will have a width of 80% because we want the whole thing to be fluid:

.ao-item { width: 80%; margin: 0 auto; padding: 35px 0; position: relative; clear: both; }

The two inner divisions will be floating, so let’s clear some floats with this great technique:

.ao-item:before, .ao-item:after { content:""; display:table; } .ao-item:after { clear:both; } .ao-item { zoom:1; /* For IE 6/7 (trigger hasLayout) */ } /* from CSSTricks: http://css-tricks.com/pseudo-element-roundup/ */

Let’s style the details part with the title and the description. We’ll make it float right and give it a width of 40%. We’ll also add a left padding which will not cause us any trouble because we’ve applied box-sizing: border-box to all our elements in the normalize.css file. So this will ensure that the division is really 40% wide and the padding is “inside” of that and not added to it:

.ao-details { float: right; width: 40%; padding-left: 20px; }

Then we’ll add some styling to the text elements:

.ao-details h2 { color: #498EA5; margin-top: 0; text-shadow: 1px 1px 1px rgba(255,255,255,0.5); padding-bottom: 10px; box-shadow: 0 1px 0 #DFDEDC, 0 2px 0 rgba(255,255,255,0.5); } .ao-details p { color: #999; text-shadow: 1px 1px 1px rgba(255,255,255,0.8); line-height: 22px; } .ao-details p a{ font-weight: bold; color: #498EA5; } .ao-details p a:hover{ color: #2A3344; }

The preview division will be a bit bigger and floating left:

.ao-preview { width: 60%; float: left; position: relative; }

Now we’ll style the image. In order to make it responsive, we’ll give it a max-width of 100%. This will ensure that it will be contained in the parent division. The image will have a transition. The idea is to scale it down a bit, once we click on the associated checkbox:

.ao-item img { margin: 0 auto; max-width: 100%; display: block; opacity: 0.8; box-shadow: 1px 1px 10px rgba(0,0,0,0.2); transition: all 0.3s ease-in-out; }

The annotations division is our overlay and we’ll place it absolutely. We’ll make it invisible by setting the opacity to 0. It will also have a transition: we want it to scale it up and make it become opaque once we click on the checkbox.

.ao-annotations { width: 100%; height: 100%; position: absolute; top: 0px; left: 0px; background: rgba(33,62,68,0.3); box-shadow: 1px 1px 3px rgba(0,0,0,0.05); opacity: 0; z-index: 5; transform: scale(0.8); transition: all 0.3s ease-in-out; }

The annotation spans will be of absolute position (we’ll set each of the tops and lefts) and we’ll give them a min-width of 140 pixel since the width is in percentage. The transition effect will be to scale down and appear (opacity: 1):

.ao-annotations span { display: block; position: absolute; padding: 10px 25px; width: 33%; min-width: 140px; text-align: center; background: rgba(255,255,255,1); color: rgba(20,40,47,0.9); font-size: 16px; font-style: italic; text-shadow: 1px 1px 1px rgba(255,255,255,0.9); box-shadow: 0px 1px 4px rgba(0,0,0,0.2); opacity: 0; transform: scale(1.3); transition: all 0.3s ease-in-out; }

Each annotation span is going to have a little arrow and we’ll add it using the pseudo-class :after.

.ao-annotations span:after { position: absolute; background: transparent url(../images/arrow.png) no-repeat center center; width: 32px; height: 33px; top: 50%; left: 100%; margin: -16px 0 0 -16px; content: ''; }

Two of our spans will have the arrow on the left side:

.ao-annotations span:nth-child(3):after, .ao-annotations span:nth-child(4):after { left: auto; right: 100%; margin: -16px -16px 0 0; background-image: url(../images/arrow_left.png); }

Now we’ll set the positions for each one of the spans. We’ll use percentages again so that the positioning still makes sense, when we resize things:

.ao-annotations span:nth-child(1) { top: 5%; left: 5%; } .ao-annotations span:nth-child(2) { top: 20%; left: -13%; } .ao-annotations span:nth-child(3) { top: 37%; right: 2%; } .ao-annotations span:nth-child(4) { top: 53%; right: -8%; } .ao-annotations span:nth-child(5) { bottom: 18%; left: -4%; }

Let’s take care of that checkbox now. The trick is to put it on top of all the other elements and set its height and width to 100% meaning that it will occupy all the division, so that we can click anywhere to trigger the effect. It will be “hidden” since we set the opacity to 0. But it’s still there, so we can click on it. The z-index needs to be higher than the one of the other elements, so, just to make sure, we’ll set it very high:

input.ao-toggle { width: 100%; height: 100%; position: absolute; top: 0px; left: 0px; margin: 0; padding: 0; opacity: 0; z-index: 100; border: none; cursor: pointer; }

And now we will define what happens to the siblings when we click on the checkbox. The image will scale down, change its box-shadow and become opaque:

input.ao-toggle:checked + img { box-shadow: 1px 1px 6px rgba(0,0,0,0.2); opacity: 1; transform: scale(0.8); }

Since we can’t use img:hover anymore (remember, the checkbox is on top of everything else), we’ll use the hover on the checkbox input to trigger the hover effect of the image:

input.ao-toggle:hover + img{ opacity: 1; }

The overlay with the class ao-annoations and its spans will scale to 1 and become opaque:

input.ao-toggle:checked ~ .ao-annotations, input.ao-toggle:checked ~ .ao-annotations span{ opacity: 1; transform: scale(1); }

To add a little cherry on top, we’ll make each span appear with a delay:

input.ao-toggle:checked ~ .ao-annotations span:nth-child(1) { transition-delay: 0.3s; } input.ao-toggle:checked ~ .ao-annotations span:nth-child(2) { transition-delay: 0.4s; } input.ao-toggle:checked ~ .ao-annotations span:nth-child(3) { transition-delay: 0.5s; } input.ao-toggle:checked ~ .ao-annotations span:nth-child(4) { transition-delay: 0.6s; } input.ao-toggle:checked ~ .ao-annotations span:nth-child(5) { transition-delay: 0.7s; }

Last, but not least, we’ll add a media query to remove the float for the main divisions and decrease the font size for the annotation spans:

@media screen and (max-width: 730px){ .ao-item .ao-details, .ao-preview { float: none; width: 100%; padding: 0; text-align: left; } .ao-annotations span { font-size: 11px; } }

And that’s it! I hope you enjoyed this tutorial and find it inspiring!