Yet another featured content slider? Not exactly. Today I was surfing BinPress and I noticed how this site handles its components. Each package is a box within a row inside a grid. The grid itself is paginated so that users can easily navigate through the featured items. In this article I'd like to present a similar implementation with jQuery and CSS.
A grid can be built by using an unordered list where each item is a row:
<div id="nav"></div> <div id="featured"> <div id="featured-wrapper"> <ul class="featured-list"> <li> <div class="featured"> </div> <div class="featured"> </div> </li> <!-- other items --> </ul> <!-- other featured lists --> </div> </div>
The inner wrapper will be relatively positioned so it can slide. Its height won't be set, while its width will be calculated by multiplying the width of a single list by the total number of the lists.
The main wrapper will feature the declaration overflow: hidden
so that we can be sure that only one list will be shown at time. All featured lists will be left-floated.
We'll create the navigation links with jQuery. The link bounded to the current list will have a special active
class:
#featured { width: 600px; margin: 2em auto; overflow: hidden; } #featured-wrapper { position: relative; } ul.featured-list { width: 600px; float: left; margin: 0; padding: 0; list-style: none; } ul.featured-list li { overflow: hidden; padding-bottom: 1em; border-bottom: 1px solid #c0c0c0; margin-bottom: 1.2em; } ul.featured-list li div.featured { width: 260px; height: 10em; padding: 5px 10px; margin-right: 10px; border: 1px solid #ccc; border-radius: 8px; background: #f5f5f5; float: left; } ul.featured-list li div.featured:last-child { margin-left: 24px; margin-right: 0; } ul.featured-list li div.featured h3 { font-size: 1.3em; font-family: Impact, sans-serif; text-transform: uppercase; margin-bottom: 0.3em; } #nav { width: 600px; margin: 2em auto 0 auto; text-align: center; } #nav a { display: inline-block; width: 2em; height: 2em; line-height: 2; text-align: center; background: #333; text-decoration: none; color: #fff; margin-right: 0.5em; } #nav a.active { background: #f90; }
With jQuery we have to:
- set the total width for the inner wrapper
- create the pagination links
- associate an action to each pagination link which will make the inner wrapper slide and at the same time it will add the
active
class to the current link
Here's the code:
var FeaturedSlider = new function() { var slider = document.getElementById('featured'), lists = $('ul.featured-list', slider), wrapper = $('#featured-wrapper', slider); var setWrapper = function() { wrapper.css('width', lists.eq(0).width() * lists.length); }; var createNav = function() { var len = lists.length, i; for (i = 0; i < len; i++) { var first = (i == 0) ? ' class="active"' : ''; $('#nav').append('<a href="#"' + first + ' data-rel="' + i + '">' + (i + 1) + '</a>'); } }; var navigate = function() { $('a', '#nav').click(function(e) { e.preventDefault(); var a = $(this); if (a.hasClass('active')) { return; } var rel = a.attr('data-rel'); wrapper.animate({ left: -lists.eq(rel).position().left }, 1000, function() { a.addClass('active').siblings().removeClass('active'); }); }); }; this.init = function() { setWrapper(); createNav(); navigate(); }; }(); FeaturedSlider.init();
To associate each pagination link to its corresponding featured list, we simply set a custom data
attribute containing an index that will be later used with the jQuery's eq()
method.
If a link has already a CSS class, then our event handler will simply return without doing any further action. You can see the demo below.