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

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 JavaScript, 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.

Enjoy this piece? I invite you to follow me at to learn more.
Check out the CodePen demo for this article at