Sliding Background Effect on Link Hover

by kirupa   |   10 May 2013

A link's hover state is very similar to cardboard boxes. The fun things you can do with them are endless. One fun thing that you will learn about in this article is how to have a background color slide into view when you are hovering over a link.

Below, you can see an example of what I am talking about:

When you hover each link for Jerry, George, Kramer, and Elaine, notice what is happening. A light green background slides into view, and the same background slides out when move your mouse away. Pretty awesome, right? In the following sections, let's look at how this is done in English as well as CSS.

Onwards!

Overview of How This Works

First, before we dive into the implementation details, let's take a few steps back and talk in English about what is going on. To give away the ending, in a nutshell, the sliding effect you see is nothing more than a positioning trick involving a background color...and a whole lot of little CSS background shenanigans. Allow me to elaborate.

You start off with a link, and let's say our link looks as follows:

what your link looks like

Our link is pretty simple and has no background applied to it. Let's fix that by specifying a background. Don't worry about what the background looks like or what its colors are just yet. Let's just assume that this background is completely transparent:

just a background

Here is what you need to be aware of this background. This background's dimensions are the bounding box of your link. Any content around your link will not be affected by this background unless you make your link itself larger or do other weird things with it. More importantly, any part of your background that goes beyond this bounding box will not be visible. Keep that in mind when looking at the diagrams where I give you more details to help you understand what is going on.

Getting back to the show, when you hover over your element, the sliding effect is a result of a hidden part of your background coming into view. The way this is done is by making our background twice as large in the direction we want to slide in and shifting the background over. If I want my background to slide right when I hover similar to the example you saw earlier, I need to make my background twice as large and reposition it left:

background needs to be twice as wide 

When your link is just happily loitering around in its normal state, you see the background in its initial position as shown above. When you are hovering over your link, your background slides to the right revealing the half of it that was hidden earlier:

the hover state

By now, how this effect works should be getting clearer. All that is missing is the background itself, for we are still currently dealing with something that is transparent. The way you create something that looks like two colored rectangles arranged side by side like in our example is by using a gradient.

When you think of a gradient, you probably think of something like this:

stereotyping gradients is not nice

If that is the type of gradient that you thought of at first, then that's just...some form of discrimination or something. It's ok though - it's not your fault. I blame rap music and how they portray gradients in general. Anyway, there are gradients that don't display the full range of colors as they go from one color to another. You can arrange your gradient stops (or points) in an overlapping way to create something that looks as follows:

how gradients could look

That's exactly how we specify the gradient in our sliding link effect. The initial color you see on your link makes up one half of the gradient. The color you see when you hover over your link makes up the other half of the gradient:

the initial and final colors

Because you only ever see the background as it is contained by your link's bounding box, sliding the background between the initial/normal state and the hover state gives you this sliding background effect:

how everything ties in 

Now, because this section is an overview, I was deliberately vague on some details. In the next section, we'll remove some of the vagueness and (at the same time!) see how everything shown here gets translated into the CSS that your browser understands.

How this Effect Really Works

Understanding how this effect works is really the hard part. Once you have a good understanding of all that, the rest is pretty easy. In this section, we'll look at the actual implementation and see why things work the way they do.

First, let's get this example running on our machines. Go ahead and create a new HTML document and add the following HTML and CSS into it.

<!DOCTYPE html>
<html>
 
<head>
<meta content="en-us" http-equiv="Content-Language">
<meta charset="utf-8">
<meta content="stuff, to, help, search, engines, not" name="keywords">
<meta content="What this page is about." name="description">
<meta content="An Interesting Title Goes Here" name="title">
<title>An Interesting Title Goes Here</title>
<link href='http://fonts.googleapis.com/css?family=Roboto+Slab' rel='stylesheet' type='text/css'>
<style>
body {
	background-color: #EFEFEF;
	padding-top: 0px;
	margin-top: 0px;
	padding-left: 40px;
	padding-bottom: 25px;
}
h1 {
	font-family: 'Roboto Slab', serif;;
	font-size: 32px;
	font-weight: bold;
	color: #FF0066;
}
li {
	margin-bottom: 15px;
}
li a {
	font-family: 'Roboto Slab', serif;;
	font-size: 16px;
	color: #333;
	text-decoration: none;
	border-bottom: 1px #333 dotted;
	background-image: linear-gradient(to right,
									  #CCFF33,
									  #CCFF33 50%,
									  transparent 50%,
									  transparent);
	background-position: 100% 0;
	background-size: 200% 100%;
	transition: all .2s ease-in;
}
li a:hover {
	color: #006600;
	border-bottom: 1px #006600 dotted;
	background-position: 0 0;
}
</style>
</head>
 
<body>
 
<h1>best of wikipedia</h1>
<ul>
	<li><a href="http://en.wikipedia.org/wiki/Jerry_Seinfeld" target="_blank">
	Jerry Seinfeld</a></li>
	<li><a href="http://en.wikipedia.org/wiki/George_Costanza" target="_blank">
	George Costanza</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Cosmo_Kramer" target="_blank">
	Cosmo Kramer</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Elaine_Benes" target="_blank">
	Elaine Benes</a></li>
</ul>
<script src="//www.kirupa.com/prefixfree.min.js"></script>
</body>
</html>

If you save and preview your document, you should see an identical replica of the example you saw earlier. Now, while all of these lines of HTML and CSS are important, some of them are more important than others for understanding how this effect works.

Let's skip the less important (and boring) parts of our markup and focus on the two style rules that actually matter:

li a {
	font-family: 'Roboto Slab', serif;;
	font-size: 16px;
	color: #333;
	text-decoration: none;
	border-bottom: 1px #333 dotted;
	background-image: linear-gradient(to right,
									  #CCFF33,
									  #CCFF33 50%,
									  transparent 50%,
									  transparent);
	background-position: 100% 0;
	background-size: 200% 100%;
	transition: all .2s ease-in;
}
li a:hover {
	color: #006600;
	border-bottom: 1px #006600 dotted;
	background-position: 0 0;
}

Take a few moments and look at the contents of these two style rules. Try to map what you see to what you learned about this effect in the previous section. One of the nice things about the CSS properties is that they are somewhat descriptive of what they do. That helps in trying to understand what is going on.

Once you are ready, let's move on and look through this CSS together.

Setting up the Background Color

As you can imagine, getting your background color setup is where a bulk of the action happens. The lines responsible for setting up our gradient background and its related properties are highlighted below:

li a {
	font-family: 'Roboto Slab', serif;;
	font-size: 16px;
	color: #333;
	text-decoration: none;
	border-bottom: 1px #333 dotted;
	background-image: linear-gradient(to right,
									  transparent,
									  transparent 50%,
									  #CCFF33 50%,
									  #CCFF33);
	background-position: 100% 0;
	background-size: 200% 100%;
	transition: all .2s ease-in;
}

Let's dive through each of these highlighted lines in more detail.

Specifying Our Gradient 

The first thing to look at is our gradient as defined by the background-image property:

background-image: linear-gradient(to right,
								  #CCFF33,
								  #CCFF33 50%,
								  transparent 50%,
								  transparent);

Explaining the full syntax for what goes into a gradient goes well beyond the scope of this article, but just to look at what we have here, the to right value specifies that this gradient's angle is rotated by 90 degrees. If I didn't specify this, our gradient will be moving vertically as opposed to the horizontal direction that we want.

The next four lines define our gradient stops. They are the 0%, 50%, 50%, and 100% stops respectively. For the first half of the gradient as defined by the 0% and the first 50% stops, the color is set to #CCFF33. That is the light green color you see in the background when you hover over a link. The second half of the gradient is defined by the second 50% and 100% stops, and for these I specify a color of transparent. This means our link's background will show whatever it is inheriting from its parents.

If you had to visualize what this gradient would look like, it would look as follows:

the gradient

Adjusting Our Background Position (Yikes!)

The next property we set defines the position of our background:

background-position: 100% 0;

In this background-position property, I am specifying that this background is offset by the full width of our link. In a world where things make sense, that's what it would seem like I am doing. Reality can be quite cruel at times...especially if the W3C spec for this situation has anything to do with this.

When you specify a percentage as the value for background-position, what that translates to is the percentage multiplied by the difference between the following two points:

  1. The size of the area your background is applying to (aka our link)
  2. The size of your background

Because our background is the same size as the area it is actually applying to, subtracting our link's width from our background's width would result in a value that is 0. The end result, then, is a position value that is 100% multiplied by 0. The end result of that calculation is a value of 0 for our background-position's horizontal property...despite us actually specifying 100%

At this point, this is where our background would find itself:

where our background finds itself 

If this all sounds kind of weird, that makes two of us. This isn't the last we've seen of this property though, so stay alert for parts II and III of it.

Note: Your Backgrounds Actually Tile/Repeat

Before we go further, I need to confess that this visualization of our background position is not fully accurate. Your background actually repeats by default. We've done nothing to prevent that in our markup, and that is actually intentional as you will eventually see. If we took the repeating into account, the earlier diagram would actually look as follows:

with tiling 

Just remember that your users will never see anything beyond the bounding area as defined by our link itself. All of the additional information I am providing is just to help with understanding what is going on. What your user really REALLY sees is just this:

for real real

We still have some more changes to make, so we aren't done yet. Don't worry if your link looks awful at this stage of things.

Setting Our Background Size

The last background-related property we set (for now) is the one that defines our background's size...the appropriately named background-size property:

background-size: 200% 100%;

The first value defines the horizontal size, and the second value defines the vertical size. Because we have a horizontally sliding effect, the horizontal size is set to 200% to indicate that the width is double the width of our link. The height is just kept at its normal value of 100%, for we aren't going to be doing anything with it.

The end result is that these lines of CSS ensure our link's background is twice the width it needs to be with a gradient color that is transparent in the normal state. This is exactly what we wanted:

what you see now 

Brace yourselves now for Part II of the background-position property making a reappearance...

If you are wondering how doubling the size of our background also ended up shifting the background to perfectly do what we wanted, here is a hint: blame the background-position property. Because our background is now twice the width of our link element's width, think back to the formula we talked about earlier. The background-position property is specifying a value that is -100% (element width - background width) multiplied by the specified value of 100%. The computed value for this property at this stage is -100%, and this means our entire background is shifted left by 100% of our element's width.

This shifting coupled with the doubling in size ensures we get what we want. Yay!

Background Color on Hover

In the previous section, you learned all about how your background color is defined when your link is in its normal and natural state. In this section, let's look at what happens to our background when you hover over the link.

All of what happens when you hover over your link is defined in the li a:hover style rule:

li a:hover {
	color: #006600;
	border-bottom: 1px #006600 dotted;
	background-position: -100% 0%;
}

The hover pseudoselector ensures that this style rule only becomes active when your mouse is hovering over our links. You can learn more about the various states and how you can style them in my Styling Links in CSS tutorial.

In this style rule, the line that affects our background position is the one containing our background-position declaration:

li a:hover {
	color: #006600;
	border-bottom: 1px #006600 dotted;
	background-position: 0% 0%;
}

When you hover your link, your background's horizontal position is set to 0%. The result of this is pretty simple. It just shifts our background image right to reach the 0% position that it never got to enjoy in its normal state:

the final result 

Despite all of the explanation and background (ha!) that I've provided, what you (and your visitors) actually see in the browser is not nearly as complex as what goes on behind the scenes. All your users see is the first half of the background gradient sliding in from the left. The second half of the gradient will reappear once they move the mouse away and have the link return to its normal state. Simple!

Meet the Transition

The last thing we are going to look at is something we skipped over earlier, and that is the transition declaration that you can find at the very bottom of your li a style rule:

li a {
	font-family: 'Roboto Slab', serif;;
	font-size: 16px;
	color: #333;
	text-decoration: none;
	border-bottom: 1px #333 dotted;
	background-image: linear-gradient(to right,
									  transparent,
									  transparent 50%,
									  #CCFF33 50%,
									  #CCFF33);
	background-position: 0 0;
	background-size: 200% 100%;
	transition: all .2s ease-in;
}

This transition declaration ensures that his hover effect is a slide as opposed to a boring jump where no animation happens. This is all made possible thanks to the all keyword which ensures that all of your various property changes between the normal state and your hover state are animated. This means your link foreground color and the border color are animated. This also means that the change you made to your background-position property is also animated.

Rounding out the rest of the values, your transition will run over a duration of .2 seconds with an ease-in easing function applied. All it took was just one line to get your transition to play...and to make this awesome effect actually awesome!

Further Reading

This effect is pretty heavy on your tribal knowledge of CSS techniques. As with all forms of tribal knowledge, trial, error, and experience are the only effective guides you have for becoming good at it. With that said, knowing what is in the following links will help:

Getting Help

If you have questions, need some assistance on this topic, or just want to chat - post in the comments below or drop by our friendly forums (where you have a lot more formatting options) and post your question. There are a lot of knowledgeable and witty people who would be happy to help you out

Share

Did you enjoy reading this and found it useful? If so, please share it with your friends:

If you didn't like it, I always like to hear how I can do better next time. Please feel free to contact me directly via e-mail, facebook, or twitter.

Kirupa Chinnathambi
I like to talk a lot - A WHOLE LOT. When I'm not talking, I've been known to write the occasional English word. You can learn more about me by going here.

Add Your Comment (or post on the Forums)

blog comments powered by Disqus

Awesome and high-performance web hosting!
BACK TO TOP
new books - yay!!!