After days — and several attempts — of scratching my head and trying to figure out how to have sliding backgrounds, ala Dave Shea’s A List Apart article with CSS only, I think I’ve cracked it. Here’s a quick look at how you can set up sliding CSS backgrounds using -webkit CSS properties.

Quick caveat about compatibility

This CSS will only work in WebKit nightlies or, at the time of writing, Safari 4 Developer Preview.

Some of the current browsers may have some aspects of the CSS used in this example but not all. Hopefully we’ll see more and more browsers picking up some of these properties and behaviours.

On with the example

Probably the best way to present this example is by using a list — in our case a navigation list — but I’m sure a creative person could make it work in other situations. The jist of the process is to have 3 layers of elements and a creative use of positioning them.

Setting up the containers

The parent container (ul) should have the background state for the list (how about a nice blue background: -webkit-gradient(linear, left top, left bottom, from(rgba(137,174,195,1)), to(rgba(147,185,207,1)), color-stop(0.25,rgba(140,177,199,1)));). Using relative positioning and overflow: hidden; height: 1.5em; we can then position the list items (li) out of view (position: relative; top: 2em;). Unfortunately this also pushes the links inside the lis out of view so we need to position them back into view with position: relative; top: -2em;. So now we’ve got a navigation list with a blue background.

Now we need to add a background to the li that is currently out of view (let’s go with neutral grey gradient background: -webkit-gradient(linear, left top, left bottom, from(rgba(200,200,200,1)), to(rgba(50,50,50,1)), color-stop(0.95,rgba(100,100,100,1)));). This is what will slide into view as the visitor hovers over the link.

Get sliding already

Finally, we need to add the CSS that’s going to do the sliding. All of the example code I’ve given so far, with the exception of -webkit-gradient — which can be replaced with background colours or images — will work across all the browsers out today. The follow bits are where we dip into strictly WebKit territory.

First we’ll need to slide the li back into view with top: 0; -webkit-transition: top 0.3s ease-in-out;. It’s a little spotty though and I noticed some odd flickering when testing the code this far. So, I made sure the link stays where it is in the list by adding the same CSS from the li.

Bob’s your uncle

And that’s that. We’ve now got a navigation list, where when a link is hovered a new background slides in from the bottom. Obviously numerous parts of this example can be changed — sliding direction, colours, heights, container/elements, timing, etc.

Check out the working example (only works in WebKit nightlies and Safari 4 Developer Preview as of this writing) I threw together for you.

Here’s the complete HTML I used in my example:

<!DOCTYPE html>
<html lang="en-us">
<head>
	<meta charset="utf-8" />
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	<title>CSS Sliding Background Images</title>
	<link rel="stylesheet" href="sliding-bg.css" type="text/css" media="screen" charset="utf-8" />
</head>
<body>
	<div id="container">
		<div id="main">
			<ul id="navigation" class="horizontal">
				<li id="home"><a href="#">Home</a></li>
				<li id="projects" class="active"><a href="#">Projects</a></li>
				<li id="blog"><a href="/mike/">Blog</a></li>
				<li id="twitter"><a href="http://twitter.com/mstickel">Twitter</a></li>
			</ul>
		</div> <!-- /main -->
	</div> <!-- /container -->
</body>
</html>

And the full CSS:

/* General page stuff */
html { background: #e5e5e5; min-height: 100%; }
body { background: #fff; font: 12px/18px "MyriadPro-Regular", "Lucida Grande", "Lucida Sans Unicode", Helvetica, sans-serif; margin: 20px auto; width: 900px; }

/* utility classes */
ul.horizontal			{ float: left; list-style: none inside; position: relative; width: 100%; *height: 1%; }
ul.horizontal li	{ float: left; margin: 0; }

/* Navigation specific */
ul#navigation			{
	background: -webkit-gradient(linear, left top, left bottom, from(rgba(137,174,195,1)), to(rgba(147,185,207,1)), color-stop(0.25,rgba(140,177,199,1)));
	border-left: 1px solid #fff;
	margin: 0;
	overflow: hidden;
	min-height: 1em;
	padding: 0;
	position: relative;
	width: 400px;
}
ul#navigation li	{
	background: -webkit-gradient(linear, left top, left bottom, from(rgba(200,200,200,1)), to(rgba(50,50,50,1)), color-stop(0.95,rgba(100,100,100,1)));
	border-right: 1px solid #fff; width: 24.75%;
	position: relative;
	top: 2em;
}
ul#navigation a		{
	border-right: 1px solid #fff; width: 24.75%;
	color: #000;
	display: block;
	height: 1em;
	padding: 0.4em 0 0.7em;
	text-align: center;
	text-decoration: none;
	width: 100%;
	position: relative;
	top: -2em;
}
ul#navigation li:hover {
	top: 0;
	-webkit-transition: top 0.3s ease-in-out;
}
ul#navigation a:hover {
	top: 0;
	-webkit-transition: top 0.3s ease-in-out;
	color: #fff;
}
ul#navigation li.active a { background: url(bg.png) no-repeat bottom left; }
ul#navigation li.active a:hover { color: #000; }

Leave a Reply