Today’s project is a fun one. We’re going to build a standard CSS image slider with a twist: the visible image area will be divided into four distinct sections, each with a hidden message that is revealed when the user hovers over it.
The ultimate effect is pretty awesome and I think you’re going to like it a lot. Along the way we’ll play with some animations, transitions, positioning contexts and a lot more. Let’s dive in and get started!
Sneak Peek
If you’d like to sneak a look at the finished product before we build it, check out the link below.
Demo: Click here to launch the live demo.
Props to “How Do You Roll”
My inspiration for today’s tutorial comes from the sushi place where I plan on eating dinner tonight. I stopped by their website for directions and instantly wanted to see if I could replicate the effect on the home page. The restaurant is called How Do You Roll, feel free to go check out their awesome site.
HTML
Let’s get this project started! As always, the first thing we want to do is outline our basic HTML structure. This slider is comprised of one big image area that’s split into four vertical columns. Consequently, we require one wrapper div with a “slider” class and four inner divs, each with a “panel” class.
<div class="slider"> <div class="panel"></div> <div class="panel"></div> <div class="panel"></div> <div class="panel"></div> </div> |
This is our basic structure, but we need to flesh it out a little with some content. I want each panel to serve as both a source of information and a link. So the user should be able to hover, see what the panel is all about, and click to proceed to a different page. To accomplish this, we’ll toss in an h2 and a paragraph and wrap the whole dang thing in an anchor. It seems like a weird way to use an anchor, but it’s perfectly valid in HTML5.
<a href="#"> <div class="panel"> <h2>One</h2> <p>Lorem ipsum dolor sit amet...</p> </div> </a> |
Now that we have an overall structure and the individual panel formation figured out, we put it all together and we have all the HTML that we’ll need for this project.
<div class="slider"> <a href="#"> <div class="panel"> <h2>One</h2> <p>Lorem ipsum dolor sit amet...</p> </div> </a> <a href="#"> <div class="panel"> <h2>Two</h2> <p>Lorem ipsum dolor sit amet...</p> </div> </a> <a href="#"> <div class="panel"> <h2>Three</h2> <p>Lorem ipsum dolor sit amet...</p> </div> </a> <a href="#"> <div class="panel"> <h2>Four</h2> <p>Lorem ipsum dolor sit amet...</p> </div> </a> </div> |
Starter Styles
To kick off our CSS, let’s get some of the generic stuff out of the way. First I threw in a little universal reset to get us all on the same page. Replace this with a better reset or normalization technique if you’re using this in a real project.
I also added a background texture and reset the link styles for the slider, just for good measure.
* {margin: 0; padding: 0;} body { background: #eee url(subtlenet2.png); /*http://subtlepatterns.com/?p=1341*/ } .slider a { text-decoration: none; color: fff; } |
Slider CSS
Now it’s time to style the slider div. Basically, we want to set a specific size for it, then give it a background image that is the same size. Then we’ll add some margins to center it, some border-radius to round the corners and a box-shadow to set it apart from the background a bit.
The big thing that you might miss in this chunk is the overflow:auto line. This is important because we want our panels to take on the rounded corner effect that we’re applying to the parent slider div.
.slider { height: 400px; width: 800px; background: url(http://lorempixum.com/800/400/sports/8); border-radius: 20px; overflow: hidden; margin: 50px auto; -webkit-box-shadow: 2px 2px 8px rgba(0,0,0,0.5); box-shadow: 2px 2px 8px rgba(0,0,0,0.5); } |
Progress Check
At this point, you should have a big image with rounded corners and a drop shadow along with a bunch of ugly, messy text, which we’ll fix in the next step!
Panel CSS
Our slider container is looking sharp, now it’s time to put the panels in order. Given that our container is 800px by 400px, each panel needs to be set at 200px by 400px, meaning that each panel will occupy the full height and one quarter of the width. From there we just need to float them to the left and they’ll line up just like we want.
The interesting part here is that I’ve set the color and background to transparent, which makes the panels invisible. This is because we only want them to show up on hover. The default state should indeed be hidden.
The final step here is to add the CSS for a transition so that the panels fade into place when the user hovers. Notice that I actually declared two separate transitions separated by a comma (one for the color and one for the background-color).
.panel { width: 200px; height: 400px; background: transparent; color: transparent; float: left; overflow: hidden; -webkit-transition: color 0.5s ease, background-color 0.5s ease; -moz-transition: color 0.5s ease, background-color 0.5s ease; -o-transition: color 0.5s ease, background-color 0.5s ease; -ms-transition: color 0.5s ease, background-color 0.5s ease; transition: color 0.5s ease, background-color 0.5s ease; } |
Panel Typography
Next, it’s time to get the typography in order. Admittedly, I didn’t do this with the panels set to invisible but instead gave the elements a color, styled them and then reverted them back to hidden.
Make sure you style both the paragraph and the h2. I made the header big, bold and moved down from the top quite a bit. Both the header and the paragraph also get a set width of 150px, which makes it easy to center them in the space despite the left alignment.
.panel h2 { font: bold 35px/1.5 Helvetica, Verdana, sans-serif; width: 150px; margin: 55px auto 0 auto; } .panel p { font: 200 11px/1.5 Helvetica, Verdana, sans-serif; width: 150px; margin: 0 auto; } |
Panel Hover
When the user hovers over one of our panels, I want it to become visible again. I do this by giving the background and text a color. I set the background to black, with a little transparency to let the underlying image show through, and the paragraph to white.
.panel:hover { background: #000; /*for old browsers*/ background: rgba(0,0,0,0.8); color: #fff; } |
Progress Check
You should now have fully functioning panels! If this is all you were looking to achieve, you can stop here, no further work necessary. Even without the next step, it’s still a great effect.
Animate The Background
This last step is completely optional, and mind you it won’t work at all on older browsers, but the original inspiration for this piece had an image slider in the background. We have a static image back there and we’re now going to go back and animate it.
To do this, we need to go back to the slider declaration block and add a few things. For starters, turn your single background into four background images, with the last being the same as the first so everything loops nicely.
Next, make sure that you set the background images to have no repeat and copy the position values shown below, which will line up the images in one long horizontal row.
.slider { height: 400px; width: 800px; background: url(http://lorempixum.com/800/400/sports/8), url(http://lorempixum.com/800/400/sports/2), url(http://lorempixum.com/800/400/sports/3), url(http://lorempixum.com/800/400/sports/8); background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0px; background-repeat: no-repeat; border-radius: 20px; overflow: hidden; margin: 50px auto; -webkit-animation: slider 15s infinite; -moz-animation: slider 15s infinite; -ms-animation: slider 15s infinite; -o-animation: slider 15s infinite; animation: slider 15s infinite; -webkit-box-shadow: 2px 2px 8px rgba(0,0,0,0.5); box-shadow: 2px 2px 8px rgba(0,0,0,0.5); } |
As you can see, I also threw in the animation CSS. First we name our animation (slider), then set the duration and number of iterations. To finish off the entire project, we need to define how that animation will work with keyframes. The code for this is confusing so let’s outline each step.
- Step One: First background image visible
- Step Two: Move everything to the left 800px, second background image visible
- Step Three: Move everything to the left 800px, third background image visible
- Step Four: Move everything to the left 800px, fourth background image visible (which is the same as the first image)
To split this up, we need to start at 0% and end at 100%, which leaves two steps in between. The easy solution is to make steps two and three at 33% and 66%. The math isn’t perfect, but it’s close enough. Notice how the images move over each time, bringing the next background into view.
- 0%: background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0;
- 33% background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0;
- 66%: background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0;
- 100%: background-position: -3200px 0px, -1600px 0px, -800px 0px, 0px 0;
Now, this alone is going to make the slideshow constantly move, which we don’t want. What we want instead is for each slide to stay still for a few seconds before advancing. This is accomplished by adding in a few redundant steps so that the slides don’t advance until 10% before the next step.
- 0%: background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0;
- 23%: background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0;
- 33% background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0;
- 56% background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0;
- 66%: background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0;
- 90%: background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0;
- 100%: background-position: -3200px 0px, -1600px 0px, -800px 0px, 0px 0;
Now that we’ve got the processed outlined, we can make it happen with CSS. This requires a ton of code for the various browsers but it’s the only way we can pull it off so we’ll just have to live with it.
@keyframes "slider" { 0% { background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0; } 23% { background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0; } 33% { background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0; } 56% { background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0; } 66% { background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0; } 90% { background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0; } 100% { background-position: -3200px 0px, -1600px 0px, -800px 0px, 0px 0; } } @-moz-keyframes slider { 0% { background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0; } 20% { background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0; } 33% { background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0; } 56% { background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0; } 66% { background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0; } 90% { background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0; } 100% { background-position: -3200px 0px, -1600px 0px, -800px 0px, 0px 0; } } @-webkit-keyframes "slider" { 0% { background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0; } 20% { background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0; } 33% { background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0; } 56% { background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0; } 66% { background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0; } 90% { background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0; } 100% { background-position: -3200px 0px, -1600px 0px, -800px 0px, 0px 0; } } @-ms-keyframes "slider" { 0% { background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0; } 20% { background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0; } 33% { background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0; } 56% { background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0; } 66% { background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0; } 90% { background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0; } 100% { background-position: -3200px 0px, -1600px 0px, -800px 0px, 0px 0; } } @-o-keyframes "slider" { 0% { background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0; } 20% { background-position: 0px 0px, 800px 0px, 1600px 0px, 3200px 0; } 33% { background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0; } 56% { background-position: -800px 0px, 0px 0px, 800px 0px, 1600px 0; } 66% { background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0; } 90% { background-position: -1600px 0px, -800px 0px, 0px 0px, 800px 0; } 100% { background-position: -3200px 0px, -1600px 0px, -800px 0px, 0px 0; } } |
See It In Action!
We’re all finished! Now it’s time to have one last look at the demo.
Demo: Click here to launch the live demo.
Conclusion
I hope you enjoyed building this fun little slider as much as I did. I love how it represents a slight tweak on an old idea. It’s quite practical and really allows you to take your sliders one step further.
Leave a comment below and let us know what you think. Have you seen a slider split up like this before? How would you make it better?