I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

web developer guide

my books

Book cover of Pro CSS3 AnimationPro CSS3 Animation, Apress, 2013

my projects

A Sass color keyword system for designers. Replaces CSS defaults with improved hues and more memorable, relevant color names.

CSSslidy: an auto-generated #RWD image slider. 3.8K of JS, no JQuery. Drop in images, add a line of CSS. Done.

tipster.ioAutomatically provides local tipping customs and percentages for services anywhere.

Born Iman Abdulmajid, 1955 First appearance: Vogue, 1976 Also known as: Iman Actress in: Star Trek VI Iman Abdulmajid
Born David Jones, 1947 First album: Space Oddity, 1967 Also known as: The Thin White Duke Actor in: The Prestige David Bowie

Hover Effect on Images From Different Directions Using Pure CSS

css / galleries

Estimated reading time: 3 minutes, 34 seconds

While I’ve demonstrated many “popup” caption techniques in the recent past, of late there’s been a UI trend in which moving your mouse over an element from different directions (from above, from below, etc) will cause an overlay transitioned in from the same vector. You can see the effect on the two images above: try moving your mouse upwards into the images of David Bowie (celebrating his 66th birthday this week) and Iman. You can also experiment with mouse movements from the left, right, and above.

We can achieve this effect using just and a little bit of clever markup; if you wanted to use the same technique on many elements at once, I would recommend automating the generation of extra DOM elements with , an approach I’ll cover in the weeks ahead.

To start with, the basic markup: to keep things simple, I’ll use just the example of Iman Abdulmajid above; the font is Raleway by Matt McInerney.

<div class="multi-hover">
<span>Born Iman Abdulmajid, 1955</span>
<span>First appearance: <cite>Vogue</cite>, 1976</span>
<span>Also known as: Iman</span>
<span>Actress in: <cite>Star Trek VI</cite></span>
<img src="iman-abdulmajid.jpg" alt="Iman Abdulmajid">

Naturally, the overlay span elements could contain any content you wished: here we’re using text, but UI elements or other images could also be possibilities.

Now we’re going to position the div relative, and the span elements within it absolute:

div.multi-hover { position: relative; }
div.multi-hover img { width: 100%; }
div.multi-hover span { position: absolute; width: 100%; height: 100%; text-align: center; box-sizing: border-box; font-size: 2em; transition: .3s linear; color: white; padding: 20%; }

Central images with span elements in place

(Note that you would need to add vendor prefixes on the transition code to support older versions of Firefox and other browsers).

Next, we want to move each span element so that it lies just within the inner edge of the containing div. We’ll do this by placing each span with percentages, measured off the div. At the same time, we’ll give each a different background color. We’ll do this using the nth-child selector:

div.multi-hover span:nth-child(1) { top: 0; left: 90%;
background: hsla(0,70%,50%,0.6);  } /* right */
div.multi-hover span:nth-child(2) { top: -90%; left: 0;
background: hsla(90,70%,50%,0.6); } /* top */
div.multi-hover span:nth-child(3) { top: 0; left: -90%;
background: hsla(180,70%,50%,0.6); } /* left */
div.multi-hover span:nth-child(4) { top: 90%; left: 0;
background: hsla(270,70%,50%,0.6); } /* bottom */

If you had enough space on your page, you’d see the arrangement of the spans and central image currently looks like the figure shown above.

Next, we need to “clip” the div such that only the inner edges of each span are over the image:

div.multi-hover { position: relative; overflow: hidden; }

Finally, we need to hide the span elements (using opacity) and make them reappear (and cover the complete div) after hover. We’ll use a variation of nth-child to do so:

div.multi-hover span:hover { opacity: 1; }
div.multi-hover span:nth-child(odd):hover { left: 0; }
div.multi-hover span:nth-child(even):hover { top: 0; }

A few observations:

  • Particularly swift mouse movements from outside the image into its interior may not trigger a transition, due to the fact that such motions pass over the invisible hover area of the span elements too quickly; this can be balanced by applying more inset to the span elements to provide them with larger “hit” areas, with the downside of adding the drawbacks discussed below.

  • A lower inset percentage (say ±70%) will provide more opportunities for capturing mouse motion, at the cost of two side effects: momentary dual transitions are more likely to be triggered (as the invisible overlap of the spans at the corners of the image is greater) and every animation will appear to start a little sooner.

  • As coded here, this technique has limited utility on mobile devices: it will not be obvious to users that they should swipe over the edges of the image to trigger the rollovers. An improved approach would be to increase the inset of the spans to ±40% within a media query for mobile devices, providing more opportunity for the transitions to occur on tap/press. I’ve also mentioned improved approaches to mobile in the related Smashing Magazine article (see below).

  • could be improved: for users with different needs, I would suggest placing the text of the span elements in a longer sentence for the alt value or longdesc of the image.

Play with this code on CodePen
comments powered by Disqus

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.