Five Useful CSS/jQuery Coding Techniques For More Dynamic Websites

Advertisement

Interactivity can transform a dull static website into a dynamic tool that not only delights users but conveys information more effectively. In this post, we’ll walk through five different coding techniques that can be easily implemented on any website to provide a richer user experience.

The techniques will allow you to better display difficult content, help users find information more effectively and provide meaningful UI cues without overwhelming the user.

  1. On-page text search1
  2. Drag controls for oversized content2
  3. Subtle hover effects3
  4. Comment count bars4
  5. Full-page slider5

1. On-Page Text Search

On-page text search6

Websites often have search boxes to allow users to find content from their archives. But what if you want to find content on the given page? Information Architects7 has had on-page text search that provides a great user experience. Let’s recreate this using jQuery.

Mark-Up and Interaction

First let’s build an input box for the search:

<input type="text" id="text-search" />

Next we’ll need jQuery to attach a listener to track changes to the input box:

$(function() {
    $('#text-search').bind('keyup change', function(ev) {
        // pull in the new value
        var searchTerm = $(this).val();
    )};
});

Here we bound our function to both the keyup and change events. This ensures that our operation fires regardless of whether the user types or pastes the text.

Now, let’s turn to Highlight8, a useful and lightweight jQuery plug-in that handles text highlighting. After including the plug-in source, let’s add a highlight() call to our JavaScript:

$(function() {
    $('#text-search').bind('keyup change', function(ev) {
        // pull in the new value
        var searchTerm = $(this).val();

        // disable highlighting if empty
        if ( searchTerm ) {
            // highlight the new term
            $('body').highlight( searchTerm );
        }
    });
});

In addition to highlighting the given text, we’ve also added a check to make sure the search term isn’t empty (which causes an infinite loop).

This snippet highlights the search query throughout the page, but we can also limit the scope to a given id:

$('#myId').highlight( searchTerm );

Or we can search only within a certain element:

$('p').highlight( searchTerm );

This text highlighting by default is case insensitive. If you’d prefer case-sensitive highlighting, remove the .toUpperCase() on both lines 21 and 41 of the Highlight plug-in.

Styling the Highlighted Text

Now that the JavaScript is attached, we’ll need to style our highlighted items. The Highlight plug-in wraps the highlighted terms in <span class="highlight"></span>, which we can style with CSS.

First, let’s change the background color and then add rounded corners and a drop-shadow for all browsers except IE:

.highlight {
    background-color: #fff34d;
    -moz-border-radius: 5px; /* FF1+ */
    -webkit-border-radius: 5px; /* Saf3-4 */
    border-radius: 5px; /* Opera 10.5, IE 9, Saf5, Chrome */
    -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.7); /* FF3.5+ */
    -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.7); /* Saf3.0+, Chrome */
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.7); /* Opera 10.5+, IE 9.0 */
}

Although the highlighting is now visible, it still appears a bit tight around the text and could use some padding. But we’ll have to be careful not to adjust the layout of text. These spans are inline elements, and if we simply add padding, the text will shift around on the page. So, let’s include padding with a negative margin to compensate:

.highlight {
    padding:1px 4px;
    margin:0 -4px;
}

Finishing the Interaction

Last but not least, let’s make sure to remove the highlighted text whenever the user edits text in the input box:

$(function() {
    $('#text-search').bind('keyup change', function(ev) {
        // pull in the new value
        var searchTerm = $(this).val();
    
        // remove any old highlighted terms
        $('body').removeHighlight();
    
        // disable highlighting if empty
        if ( searchTerm ) {
            // highlight the new term
            $('body').highlight( searchTerm );
        }
    });
});

Here we added a call to remove any text highlighting, which is performed outside of the empty field check. This ensures that the highlight is also removed if the user clears the field.

Although removeHighlight() works well in most browsers, it will crash IE6. This is due to an IE6 bug9 with node.normalize().

We can get the Highlight plug-in working in IE6 by rewriting this function. Simply replace lines 45-53 of highlight.js with the following:

jQuery.fn.removeHighlight = function() {
 function newNormalize(node) {
    for (var i = 0, children = node.childNodes, nodeCount = children.length; i < nodeCount; i++) {
        var child = children[i];
        if (child.nodeType == 1) {
            newNormalize(child);
            continue;
        }
        if (child.nodeType != 3) { continue; }
        var next = child.nextSibling;
        if (next == null || next.nodeType != 3) { continue; }
        var combined_text = child.nodeValue + next.nodeValue;
        new_node = node.ownerDocument.createTextNode(combined_text);
        node.insertBefore(new_node, child);
        node.removeChild(child);
        node.removeChild(next);
        i--;
        nodeCount--;
    }
 }
 
 return this.find("span.highlight").each(function() {
    var thisParent = this.parentNode;
    thisParent.replaceChild(this.firstChild, this);
    newNormalize(thisParent);
 }).end();
};

This new function replaces the standard Javascript normalize() with a custom function that works in all browsers.

Download the complete example.10

2. Drag Controls For Oversized Content

Drag controls for oversized content11

When layout constraints bump up against the need for large images, finding a quality solution can be difficult. Mospromstroy12 uses a creative technique to handle this situation: a "drag and drop" control bar that allows users to pan through images.

We can accomplish something similar using jQuery UI's draggable13 behavior.

Mark-Up and CSS

First let's set up some mark-up for the content and controls:

<div id="full-sized-area">
    <div id="full-sized-content">
    Your content here
    </div>
</div>

<div id="drag-controls-area">
    <div id="drag-controls"></div>
</div>

Next, let's apply some basic CSS:

#full-sized-area {
    position: relative;
    overflow: hidden;
    width: 800px;
    height: 400px;
}

#full-sized-content {
    position: absolute;
    top: 0;
    left: 0;
}

#drag-controls-area {
    position: relative;
    width: 300px;
    height: 50px;
}

#drag-controls {
    position: absolute;
    top: 0;
    left: 0;
    height: 48px;
    border: 1px solid white;
}

Here we applied an absolute position to both the #full-sized-content and #drag-controls, and we also hid any overflow from the large image. Additionally, we applied some arbitrary dimensions to the content and drag controls wrappers; make sure to adjust these as needed.

Building Interactivity With jQuery

Now, let's use jQuery UI to build the interaction. Begin by including jQuery UI14 with the draggable module.

Before attaching the controls, let's resize the drag control box to the right dimensions:

$(function() {
    var $fullArea = $('#full-sized-area');
    var $fullContent = $('#full-sized-content', $fullArea);
    
    // find what portion of the content is displayed
    var contentRatio = $fullArea.width() / $fullContent.width();
    
    // scale the controls box
    var $controlsArea = $('#drag-controls-area');
    var $controls = $('#drag-controls', $controlsArea);
    
    $controls.css('width', $controlsArea.width() * contentRatio);
});

Here, we've determined what portion of the content is visible in the content area and then scaled the width of the control box accordingly.

Next, let's attach the draggable behavior:

$(function() {
    var $fullArea = $('#full-sized-area');
    var $fullContent = $('#full-sized-content', $fullArea);
    
    // find what portion of the content is displayed
    var contentRatio = $fullArea.width() / $fullContent.width();
    
    // scale the controls box
    var $controlsArea = $('#drag-controls-area');
    var $controls = $('#drag-controls', $controlsArea);
    
    $controls.css('width', $controlsArea.width() * contentRatio);
    
    // determine the scale difference between the controls and content
    var scaleRatio = $controlsArea.width() / $fullContent.width();
    
    // attach the draggable behavior
    $controls.draggable({
        axis : 'x', // confine dragging to the x-axis
        containment : 'parent',
        drag : function(ev, ui) {
            // move the full sized content
            $fullContent.css('left', -1 * ui.position.left / scaleRatio );
        }
    });
});

Here, we've attached a draggable event and set a couple options. First, we set axis to restrict dragging to the x-axis, and then we set containment to confine dragging to the parent element (i.e. the controls wrapper).

Finally, we set up a drag listener to move the full-sized content according to how far the user has dragged the control. For this, we negatively positioned the content to the left by the drag amount multiplied by the ratio of the controls to the content.

Custom Cursors

The draggable content is working, but we still have room for improvement.

First let's add some more styling to the control box to make it more interactive. jQuery UI's draggable attaches two class names that we can use for this: ui-draggable and ui-draggable-dragging.

#drag-controls.ui-draggable {
    cursor: -moz-grab !important;
    cursor: -webkit-grab !important;
    cursor: e-resize;
}

#drag-controls.ui-draggable-dragging {
    cursor: -moz-grabbing !important;
    cursor: -webkit-grabbing !important;
    border-color: yellow;
}

In addition to applying a new border color to the active controls, this snippet also attaches a number of cursor properties, which use proprietary UI cursors15 available in Firefox and Safari, with a back-up for IE.

Because of the implementation of the cursor property, we had to "bootstrap" this together using !important. This ensures that the proprietary cursors are used if available, while allowing the default cursor to overwrite them in IE. Unfortunately, Chrome does not currently support -webkit-grab, so we leave it out of this implementation. If you'd prefer to use the back-up e-resize cursor in both Chrome and Safari, just remove the -webkit-grab and -webkit-grabbing properties.

Parallax Effect

Let's make the sliding animation more three-dimensional by adding a two-layer parallax effect16. To do so, we simply add a background to our full-sized content area and animate it at a slower rate.

Add the mark-up first:

<div id="full-sized-area">
    <div id="full-sized-background">
    Your background here
    </div>
    
    <div id="full-sized-content">
    Your content here
    </div>
</div>

<div id="drag-controls-area">
    <div id="drag-controls"></div>
</div>

And then some basic styling:

#full-sized-background {
    position: absolute;
    top: 0;
    left: 0;
}

Here, we use absolute positioning to lock the background in place. Note that we did not need to attach a z-index17, because we placed the background element before the content area in the mark-up.

Finally, let's add the background animation to our drag event:

$fullBackground = $('#full-sized-background');
    
    $controls.draggable({
        axis : 'x', // confine dragging to the x-axis
        containment : 'parent',
        drag : function(ev, ui) {
            // move the full sized content
            var newContentPosition = -1 * ui.position.left / scaleRatio;
            $fullContent.css('left', newContentPosition);
            
            // move the background
            $fullBackground.css('left', newContentPosition * .4);
        }
    });

Here, we simply used the new position that we calculated for the main content and applied 40% of that change to the background. Adjust this value to change the speed of the parallax.

Download the complete example.18

3. Subtle Hover Effects

Subtle mouse effects on Veerle's blog19

Veerle's blog20 uses subtle transitions to create a natural feel for mouse interactions. These can be easily accomplished using CSS3's transition property (and a jQuery back-up for unsupported browsers).

First, let's attach some CSS with the class subtle to all elements:

.subtle {
    background-color: #78776C;
    color: #BBBBAD;
}

.subtle:hover, .subtle:focus {
    background-color: #F6F7ED;
    color: #51514A;
}

Here, we've styled these elements with a background and text color and included a hover state using the pseudo-class21 :hover. Additionally, we included the :focus pseudo-class for active input and text-area elements.

This CSS causes the style to change immediately on hover, but we can apply a smoother transition using CSS3:

.subtle {
    -webkit-transition: background-color 500ms ease-in; /* Saf3.2+, Chrome */
    -moz-transition: background-color 500ms ease-in; /* FF3.7+ */
    -o-transition: background-color 500ms ease-in; /* Opera 10.5+ */
    transition: background-color 500ms ease-in; /* futureproofing */
    background-color: #78776C;
    color: #BBBBAD;
}

.subtle:hover, .subtle:focus {
    background-color: #F6F7ED;
    color: #51514A;
}

Here, we've attached a CSS3 transition22 that works in all modern browsers except IE. The transition property consists of three different values. The first is the CSS property to animate, and the second is the duration of the animation—in our case, background-color and 500 milliseconds, respectively. The third value allows us to specify an easing function23, such as ease-in or linear.

jQuery Back-Up

Our subtle transitions now work across a variety of browsers, but let's include support for all users by leveraging a jQuery back-up technique24.

First we'll need to detect whether the user's browser supports transition:

// make sure to execute this on page load
$(function() {
    // determine if the browser supports transition
    var thisStyle = document.body.style,
    supportsTransition = thisStyle.WebkitTransition !== undefined ||
        thisStyle.MozTransition !== undefined ||
        thisStyle.OTransition !== undefined ||
        thisStyle.transition !== undefined;
});

Here, we check whether the body element can use any of the browser-specific transition properties that we defined above.

If the browser doesn't support transition, we can apply the animation using jQuery. However, jQuery's animate()4125 function does not natively support color-based animations. To accommodate our background-color animation, we'll have to include a small chunk of jQuery UI26: the effects core.

After including jQuery UI, we'll need to attach the animation to the hover and focus event listeners:

// make sure to execute this on page load
$(function() {
    // determine if the browser supports transition
    var thisStyle = document.body.style,
    supportsTransition = thisStyle.WebkitTransition !== undefined ||
        thisStyle.MozTransition !== undefined ||
        thisStyle.OTransition !== undefined ||
        thisStyle.transition !== undefined;

    // assign jQuery transition if the browser doesn't support
    if ( ! supportsTransition ) {
        var defaultCSS = {
            backgroundColor: '#78776C'
        },
        hoverCSS = {
            backgroundColor: '#F6F7ED'
        };

        // loop through each button
        $('.subtle').each(function() {
            var $subtle = $(this);
            
            // bind an event listener for mouseover and focus
            $subtle.bind('mouseenter focus', function() {
                $subtle.animate(hoverCSS, 500, 'swing' );
            });
            
            // bind the reverse for mouseout and blur
            $subtle.bind('mouseleave blur', function(ev) {
                if ( ev.type == 'mouseleave' && ev.target == document.activeElement ) return false;
                
                $subtle.animate(defaultCSS, 500, 'swing' );
            });
        });
    }
});

Here, we recreated the transition using jQuery's animate(). Notice how we used values that are to the CSS3 transition—500 specifies 500 milliseconds, and swing specifies an easing method that is close to ease-in.

While the mouse-over and focus event is fairly straightforward, notice the difference in the mouse-out and blur event. We added some code to end the function if the element is in focus. This retains the active state even if the user moves their mouse. jQuery's is()27 method does not support the :focus pseudo-class, so we have to rely on DOM's document.activeElement.

Download the complete example.28

4. Comment Count Bars

Most commented posts bar representation29

IT Expert Voice30 uses a nice method for displaying the "Most commented" posts in its sidebar. Let's recreate this using WordPress and a bit of CSS and jQuery (non-WordPress users can skip the first section).

Pulling Posts With WordPress

Let's start by pulling in the top-five most-commented posts:

<?php $most_commented = new WP_Query('orderby=comment_count&posts_per_page=5'); ?>

Here, we used WP_Query31 and a custom variable name so as not to disrupt any other post loops on the page.

Next, let's loop through the posts we've selected, outputting each as a list item:

<ul id="most-commented">

<?php $most_commented = new WP_Query('orderby=comment_count&posts_per_page=5'); ?>
	<?php while ($most_commented->have_posts()) : $most_commented->the_post(); ?>	

	<li>
	<a href="<?php the_permalink() ?>" rel="bookmark" title="<?php the_title_attribute(); ?>"><?php the_title(); ?></a>
	
	<span class="comment-bar"><span class="comment-count"><?php comments_number('0','1','%'); ?></span></span>
	</li>

<?php endwhile; ?>

</ul>

Here, we used a while() loop to run through each post. First, we output a link to the post using the_permalink()32 and the_title()33, and then we output the comment count using comments_number()34 and some additional mark-up for styling.

Basic CSS Styling

Let's style the basic layout of the comments list using CSS:

#most-commented li {
    list-style: none;
}

#most-commented a {
    display: block;
}

We've removed any list styling and defined the links as a block element so that they stay separate from our comment bar visualizations.

Let's set up some base styles for the comment bar and comment count:

#most-commented .comment-bar {
    display: inline-block;
    position: relative;
    height: 30px;
    width: 0;
    margin: 5px 0;
    padding-left: 20px;
    background-color: #999;
}

#most-commented .comment-count {
    display: inline-block;
    position: absolute;
    right: -20px;
    top: -5px;
    width: 34px;
    height: 34px;
    border-width: 3px;
    border-style: solid;
    border-color: #FFF;
    -moz-border-radius: 20px;
    -webkit-border-radius: 20px;
    border-radius: 20px;
    text-align: center;
    line-height: 34px;
    background-color: #6CAC1F;
    font-size: 13px;
    font-weight: bold;
    color: #FFF;
}

Most of this styling is arbitrary, so feel free to attach a background image or otherwise tweak it to fit your theme. The main thing is to align the comment count to the right of the comment bar so that we can adjust the width of the bar at will.

Pay attention to the total width of the comment count, in our case 40px (34px wide plus 3px for the left and right borders). We're using half of that value to position the comment count: 20px of negative positioning so that the count hangs on the right, and 20px of left padding so that the comment bar reaches the center of the comment count.

Tying It All Together With jQuery

Finally, let's use jQuery to set the widths of the individual bars. We'll start by looping through the comments after the page loads:

$(function() {
    $('#most-commented li').each(function(i) {
        var $this = $(this);
        var thisCount = ~~$this.find('.comment-count').text();
    });
});

We loop through all of the <li> elements, pulling out the comment count from the mark-up. Notice that we've used the primitive data type35 ~~ to convert the text to an integer. This is significantly faster36 than alternatives such as parseInt().

Let's set up some key variables in the first iteration of our loop:

$(function() {
    // define global variables
    var maxWidth, maxCount;
    
    $('#most-commented li').each(function(i) {
        var $this = $(this);
        var thisCount = ~~$this.find('.comment-count').text();
        
        // set up some variables if the first iteration
        if ( i == 0 ) {
            maxWidth = $this.width() - 40;
            maxCount = thisCount;
        }
    });
});

Here, we started by defining variables outside of the each() loop. This allows us to use these values in every iteration.

Next, we subtracted 40 pixels from the width of the list item to define a maximum width for the comment bar. The 40 pixels compensate for the left-padding and negative position that we applied above.

We also set maxCount to the first value. Because we initially pulled the posts according to their number of comments, we can be sure that the first item will have the highest count.

Finally, let's calculate the width of each bar and animate the transition:

$(function() {
    // define global variables
    var maxWidth, maxCount;
    
    $('#most-commented li').each(function(i) {
        var $this = $(this);
        var thisCount = ~~$this.find('.comment-count').text();
        
        // set up some variables if the first iteration
        if ( i == 0 ) {
            maxWidth = $this.width() - 40;
            maxCount = thisCount;
        }
        
        // calculate the width based on the count ratio
        var thisWidth = (thisCount / maxCount) * maxWidth;
        
        // apply the width to the bar
        $this.find('.comment-bar').animate({
            width : thisWidth
        }, 200, 'swing');
    });
});

If you'd rather style the elements without any animation, simply replace the animate() with a static css().

Download the complete example.37

5. Full-Page Slider

Full page slider on JaxVineyards.com38

Sliding animation is an interactive way to show related content. But JAX Vineyards39 takes the standard sliding gallery to the next level by animating across the entire page. Let's create a similar effect using jQuery.

Mark-Up and CSS

Start by adding the mark-up:

<div id="full-slider-wrapper">
    <div id="full-slider">
        
        <div class="slide-panel active">
        Panel 1 content here
        </div>
        
        <div class="slide-panel">
        Panel 2 content here
        </div>
        
        <div class="slide-panel">
        Panel 3 content here
        </div>
    </div>
</div>

We set up the basic mark-up and wrappers that we need for the animation. Make sure that the full-slider-wrapper is not contained in any element that is narrower than the browser window—we'll need the full width of the browser to pull off the effect.

Now, let's add some basic CSS to handle overflow and to position the panels:

html {
    min-width: 800px;
}

#full-slider-wrapper {
    overflow: hidden;
}

#full-slider {
    position: relative;
    width: 800px;
    height: 600px;
    margin: 0 auto;
}

#full-slider .slide-panel {
    position: absolute;
    top: 0;
    left: 0;
    width: 800px;
    height: 600px;
    visibility: hidden;
}

#full-slider .slide-panel.active {
    visibility: visible;
}

We defined absolute positioning and set up some arbitrary dimensions for the panels and wrapper. Feel free to tweak these dimensions to your content.

We also attached overflow: hidden to our wrapper element, which will prevent scroll bars from appearing when we animate the panels. Because we hid the overflow, we also had to assign a min-width to the html document. This ensures that the content will get scroll bars if the browser window is too small.

Finally, we used the active class that we established in the mark-up to show the first panel.

jQuery Animation

Let's build the interaction using jQuery. We'll start by defining some variables and then create a function to handle the sliding animation in both directions:

$(function() {
    var $slider = $('#full-slider');
    var $sliderPanels = $slider.children('.slide-panel');
    
    function slidePanel( newPanel, direction ) {
        // define the offset of the slider obj, vis a vis the document
        var offsetLeft = $slider.offset().left;
       
        // offset required to hide the content off to the left / right
        var hideLeft = -1 * ( offsetLeft + $slider.width() );
        var hideRight = $(window).width() - offsetLeft;
        
        // change the current / next positions based on the direction of the animation
        if ( direction == 'left' ) {
            currPos = hideLeft;
            nextPos = hideRight;
        }
        else {
            currPos = hideRight;
            nextPos = hideLeft;
        }
        
        // slide out the current panel, then remove the active class
        $slider.children('.slide-panel.active').animate({
            left: currPos
        }, 500, function() {
            $(this).removeClass('active');
        });
        
        // slide in the next panel after adding the active class
        $( $sliderPanels[newPanel] ).css('left', nextPos).addClass('active').animate({
            left: 0
        }, 500 );
    }
});

Here our slidePanel() function accepts two arguments: the index of the panel that we want to slide into view, and the direction of the slide (i.e. left or right).

Although this function looks complicated, the concepts are fairly simple. We determined the amount of offset necessary to hide the panels on the left and right sides. To calculate these values, we used jQuery's offset()40 and the slider and window widths. These offsets represent the left position values needed to hide the content on either side.

Next, we have a switch based on the direction of the animation, which uses the two values we defined previously.

Finally, we trigger the animation using jQuery's animate()4125. We slide the active panel out of view and then remove the active class once the animation completes. Then we set the new panel's left position off the screen, attach the active class to make it visible and slide it into place.

Building the Controls

Our function now handles the animation, but we still have to build controls to leverage it.

Append navigation elements to the slider object that we defined previously:

var $navWrap = $('<div id="full-slider-nav"></div>').appendTo( $slider );
    var $navLeft = $('<div id="full-slider-nav-left"></div>').appendTo( $navWrap );
    var $navRight = $('<div id="full-slider-nav-right"></div>').appendTo( $navWrap );

We could have included this navigation in the initial mark-up, but we're appending it with JavaScript for two reasons: it ensures that the navigation won't appear until the JavaScript is loaded, and it keeps the navigation from being displayed on the off chance that JavaScript isn't enabled.

Let's style the navigation:

#full-slider-nav {
    position: absolute;
    top: 0;
    right: 0;
}

#full-slider-nav-left, #full-slider-nav-right {
    display: inline-block;
    height: 0;
    width: 0;
    margin-left: 15px;
    border: 20px solid transparent;
    cursor: pointer;
}

#full-slider-nav-left {
    border-right-color: #BBB;
}

#full-slider-nav-left:hover {
    border-right-color: #999;
}

#full-slider-nav-right {
    border-left-color: #BBB;
}

#full-slider-nav-right:hover {
    border-left-color: #999;
}

Here we absolute position the navigation to the top right. We also use a CSS triangle trick42 to quickly style the controls.

Let's attach our new slider navigation to the slidePanel() function that we defined previously:

var $navWrap = $('<div id="full-slider-nav"></div>').appendTo( $slider );
    var $navLeft = $('<div id="full-slider-nav-left"></div>').appendTo( $navWrap );
    var $navRight = $('<div id="full-slider-nav-right"></div>').appendTo( $navWrap );
    
    var currPanel = 0;
    
    $navLeft.click(function() {
        currPanel--;
        
        // check if the new panel value is too small
        if ( currPanel < 0 ) currPanel = $sliderPanels.length - 1;
        
        slidePanel(currPanel, 'right');
    });
    
    $navRight.click(function() {
        currPanel++;
        
        // check if the new panel value is too big
        if ( currPanel >= $sliderPanels.length ) currPanel = 0;
        
        slidePanel(currPanel, 'left');
    });

This snippet assigns click events to the left and right navigation. In each, we change the value of currPanel according to the direction. If this new value falls outside of the available panels, we loop to the other end of our set. Finally, we trigger the slidePanel() function with the new panel and appropriate direction.

In our example, we built controls only for left and right navigation, but you could easily tweak this to have buttons for each panel. Simply pass the correct panel index to slidePanel.

Let's bring all the jQuery code together:

$(function() {
    function slidePanel( newPanel, direction ) {
        // define the offset of the slider obj, vis a vis the document
        var offsetLeft = $slider.offset().left;
       
        // offset required to hide the content off to the left / right
        var hideLeft = -1 * ( offsetLeft + $slider.width() );
        var hideRight = $(window).width() - offsetLeft;
        
        // change the current / next positions based on the direction of the animation
        if ( direction == 'left' ) {
            currPos = hideLeft;
            nextPos = hideRight;
        }
        else {
            currPos = hideRight;
            nextPos = hideLeft;
        }
        
        // slide out the current panel, then remove the active class
        $slider.children('.slide-panel.active').animate({
            left: currPos
        }, 500, function() {
            $(this).removeClass('active');
        });
        
        // slide in the next panel after adding the active class
        $( $sliderPanels[newPanel] ).css('left', nextPos).addClass('active').animate({
            left: 0
        }, 500 );
    }
    
    var $slider = $('#full-slider');
    var $sliderPanels = $slider.children('.slide-panel');
    
    var $navWrap = $('<div id="full-slider-nav"></div>').appendTo( $slider );
    var $navLeft = $('<div id="full-slider-nav-left"></div>').appendTo( $navWrap );
    var $navRight = $('<div id="full-slider-nav-right"></div>').appendTo( $navWrap );
    
    var currPanel = 0;
    
    $navLeft.click(function() {
        currPanel--;
        
        // check if the new panel value is too small
        if ( currPanel < 0 ) currPanel = $sliderPanels.length - 1;
        
        slidePanel(currPanel, 'right');
    });
    
    $navRight.click(function() {
        currPanel++;
        
        // check if the new panel value is too big
        if ( currPanel >= $sliderPanels.length ) currPanel = 0;
        
        slidePanel(currPanel, 'left');
    });
});

Download the complete example.43

Final Thoughts

In this post we walked through a variety of methods for adding dynamic functionality to your websites. These techniques can be easily adapted to work with almost any site. The majority of these techniques rely on jQuery to provide interaction, but there are plenty of other approaches, both with and without jQuery. Please post any alternate solutions in the comments below, or fork the example files on github.

Furthermore, these five methods represent only a small portion of interactive techniques. Please post any links to other dynamic techniques and functionality in the comments below.

Related Posts

You may be interested in the following related posts:

(al)
[twcount]

Footnotes

  1. 1 #on-page-text-search
  2. 2 #drag-controls
  3. 3 #subtle-hover-effects
  4. 4 #comment-count-bars
  5. 5 #full-page-slider
  6. 6 http://informationarchitects.ch/articles/
  7. 7 http://informationarchitects.ch/articles/
  8. 8 http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
  9. 9 http://stackoverflow.com/questions/2023255/node-normalize-crashes-in-ie6
  10. 10 http://gist.github.com/563055
  11. 11 http://www.mospromstroy.com/
  12. 12 http://www.mospromstroy.com/
  13. 13 http://jqueryui.com/demos/draggable/
  14. 14 http://jqueryui.com/download
  15. 15 http://www.gtalbot.org/DHTMLSection/Cursors.html
  16. 16 http://en.wikipedia.org/wiki/Parallax
  17. 17 http://tjkdesign.com/articles/z-index/teach_yourself_how_elements_stack.asp
  18. 18 http://gist.github.com/563087
  19. 19 http://veerle.duoh.com/
  20. 20 http://veerle.duoh.com/
  21. 21 http://phosphorus.co/archives/the-mysterious-pseudo-class-in-css/
  22. 22 http://net.tutsplus.com/tutorials/html-css-techniques/css-fundametals-css-3-transitions/
  23. 23 http://james.padolsey.com/demos/jquery/easing/
  24. 24 http://jonraasch.com/blog/graceful-degradation-with-css3#transition-backup
  25. 25 http://api.jquery.com/animate/
  26. 26 http://jqueryui.com/
  27. 27 http://api.jquery.com/is/
  28. 28 http://gist.github.com/563097
  29. 29 http://itexpertvoice.com/
  30. 30 http://itexpertvoice.com/
  31. 31 http://codex.wordpress.org/Function_Reference/WP_Query
  32. 32 http://codex.wordpress.org/Function_Reference/the_permalink
  33. 33 http://codex.wordpress.org/Function_Reference/the_title
  34. 34 http://codex.wordpress.org/Function_Reference/comments_number
  35. 35 http://samuli.hakoniemi.net/10-small-things-you-may-not-know-about-javascript/
  36. 36 http://jsperf.com/integer-conversion
  37. 37 http://gist.github.com/563093
  38. 38 http://jaxvineyards.com/
  39. 39 http://jaxvineyards.com/
  40. 40 http://api.jquery.com/offset/
  41. 41 http://api.jquery.com/animate/
  42. 42 http://www.dinnermint.org/css/creating-triangles-in-css/
  43. 43 http://gist.github.com/563040
  44. 44 http://www.smashingmagazine.com/2008/08/11/5-useful-coding-solutions-for-designers-and-developers/
  45. 45 http://www.smashingmagazine.com/2009/11/23/6-useful-coding-solutions-for-designers-and-developers/

↑ Back to topShare on Twitter

Jon Raasch is a front-end web developer / UI designer with endless love for jQuery, CSS3 and performance tuning. Follow him on Twitter or read his blog.

Advertising
  1. 1

    Nice post. Thanks

    0
  2. 2

    Hi
    Nice article but I am not sure what to see in the “Subtle Hover Effects” example you gave. I must have missed something there.
    Even the 1st example did not work as expected.

    0
  3. 3

    I LIKE!!

    Nice article!

    0
  4. 4

    Too bad. The page was changed shortly before the article was published?…

    1
  5. 5

    Wow, that full page slider is sick! I need to try that out, nice post.

    0
  6. 6

    I want mootools.

    0
  7. 7

    Nice article but really bit complicated if just read the code and comment only.

    0
  8. 8

    Nice post!
    I liked the Full-Page Slider idea!

    -1
  9. 9

    Hi mike do you mean slick or sick ;)

    0
  10. 10

    Great! I’ll be using these on my current portfolio redesign. Thanks!

    -2
  11. 11

    Dang… every time I am close to finishing my site, I see something I need to incorporate…

    -1
  12. 12

    So much great content in a single post, Thanks.
    Easily could have been 5 separate posts
    A lot to take in but will book mark & chip away at it

    Cheers

    -1
  13. 13

    I find this effect incredibly annoying. Printing is ridiculous and the navigation makes you hunt for want you want. Gimmicky.

    -1
  14. 14

    I like most of the idea’s, but the first one (in-page search) is a bit too much. Every browser does that (and every iOS device will when iOS4.2 is released). It’s only one cmd+f (or ctrl+f) away!

    0
  15. 15

    Expected to see techniques for creating dynamic pages, not just creating more interactive pages. Fun though, nice to see what people are using.

    0
  16. 16

    I agree – the full page slider was way too much. There may be a way to use that effect in a way that doesn’t make the user seasick, but I haven’t seen it yet.

    -1
  17. 17

    Yet another set of ideas I’m going to have to go back and implement on my site. Thanks for the tips.

    0
  18. 18

    This interaction is not just for searching on one single page (what browsers indeed do), but search on whole websites.

    -3
  19. 19

    Nice post. I hope that all developers still have awareness for the non-javascript version. I really liked the ‘Drag Controls For Oversized Content’, but when you look at the page without javascript … the navigation is broken. Not good for (some) users and -more important- not good for SEO.

    0
  20. 20

    I think you may be overestimating the number of users who don’t have Javascript enabled. But regardless this has no impact whatsoever on SEO, since the content still exists in the markup (the Javascript only builds the animation). Javascript only becomes an SEO issue when it is used to load content, for example using Ajax.

    If you really need to support non-Javascript users, you could remove the overflow: hidden; from #full-sized-area, and apply it instead with Javascript. This way it would default to scrollbars for the random oddballs who don’t have Javascript enabled.

    0
  21. 21

    I enjoyed the effect. I think on small brochure-type or portfolio sites it can be a fun way to spice up the presentation.

    0
  22. 22

    Man I really love the full-page slider. I’m definitely going to use that. Thanks for the article!

    -Matthew Stephens

    0
  23. 23

    That JAX website is beautiful, and I love the effect, but the homepage is a 2.1 MB download. Crippling for anyone on bad-broadband/non-broadband.

    0
  24. 24

    This is an absolutely brilliant article. Wow I can’t thank you enough for this one! :)

    0
  25. 25

    Agreed. Nice examples as well.

    0
  26. 26

    very useful cheers

    0
  27. 27

    Even simpler implementation of On-Page Text Search:
    ctrl + f

    0
  28. 28

    Great Article. I dont like the latest posts very much, too much theoretically stuff. Now i am happy – thanks :)

    Greetings from Germany.

    0
  29. 29

    Amazin examples! I will study some of them.

    0
  30. 30

    Are you sure?
    ’cause it says “what if you want to find content on the given page?”

    Recreating native functionality is a Bad Idea, as you’ll likely always get something wrong.

    -2
  31. 31

    no no.. the subtlehover effect is still there….http://veerle.duoh.com/….loved it!! thanks for sharing SM

    0
  32. 32

    very useful coding

    0
  33. 33

    Thanks, I really like the subtle hover effects – I’m going to use that on my site!

    0
  34. 34

    Would it is good to follow/create effects on css3, when the main browser(<IE9) is not following it? page sliding effect should go with fading effect. it gives pain to eyes.

    0
  35. 35

    Full Page slider does not look good since most of the PC’s cant render the animation fluidly. Choppy animations NEVER look good. Simple page switch would be better in that case, or utilizing some type of Fade In/Out (those require a lot less juice).

    0
  36. 36

    It surely has impact on SEO when the links to detailpages only exist in the javascript version.

    0
  37. 37

    Wow, this is very helpful

    0
  38. 38

    Always works :)

    0
  39. 39

    My bad; I thought the links to detailpages were added with javascript and therefore would have bad influence on SEO. This is not the case so forget the SEO issue. Still I would suggest a server side functionality on the #slider .arrow_left and #slider_arrow_right ( or like you suggested add the overflow:hidden with javascript and show the #slider with javascript )

    0
  40. 40

    Yes, I am sure. :-)

    -3
  41. 41

    Scoobiscus Magazines

    September 22, 2010 12:03 am

    Thank you a lot, very useful article! =]

    0
  42. 42

    Why the hell are people still implementing scrolling effects… changing the “left” property rather the “scrollLeft” one?
    Tray to tab a bit on the Full Page slider and than click the arrow buttons… it screws up!
    Can’t we use “sematic javascript” ;-)?

    0
  43. 43

    Thanks for this article! Very useful.
    I will consider to use some of this items in future projects.

    Thanks!

    0
  44. 44

    I agree with Ricardo, sounds like a current page search. Pointless over-engineering if so, and inconsistent behaviour, especially as users are used to search boxes trawling entire sites.

    1
  45. 45

    Thanks for Full Page sliding tutorial !

    0
  46. 46

    Can you explain how?

    0
  47. 47

    Tutorials like these are priceless!

    0
  48. 48

    He means sick. It is sick.

    0
  49. 49

    It’s clearly not a site-wide search unless the site is only 1 page. There’s no way to achieve that without a database or text file of search terms or a similar method. That’s obviously not mentioned.

    IMO it’s too much effect that will likely confuse the user. The externally linked example website does not use the method described, however. It just has a typical site-wide search form.

    0
  50. 50

    Great post. Nice to see a post by Jon too, I’ve found his articles really helpful and I’ve used the simple slideshow technique on a few of my sites. I really like the slider but it would only work in certain situations. Goes into a good depth of detail on here too, rather than just linking to other posts and tutorials. Great work. Thanks.

    0
  51. 51

    Wait I thought you were talking about the “Drag Controls for Oversized Content”, not the “Full Page Slider”?

    For the full page slider I’d agree with what you suggest with hard links for the navigation, however THAT might introduce an SEO issue with duplicate content (provided that the current content was still on the page).

    In any case I wouldn’t get overly hung up with Javascript-disabled users, it’s a very small percentage of most websites’ traffic.

    0
  52. 52

    Yikes that is quite bloated, but I wouldn’t “throw the baby out with the bath-water” here. Slideshows are typically on the heavier side, but you can certainly build something much lighter weight than 2 MB using this same technique.

    0
  53. 53

    I think you may have missed something. For the CSS3 effect we built a jQuery backup that works in all browsers (IE8 and lower for example).

    0
  54. 54

    Glad you like my articles :-), stay tuned to Smashing Mag and my personal blog for more.

    0
  55. 55

    You’re sure? Do you know how to read code?

    0
  56. 56

    I agree that this would be interesting for a WP site.

    I suppose you could use jQuery to apply the class of “active” to the first post that the Loop returns. Performance wouldn’t be great if the Loop returned a lot of long posts with detailed and varying content, but if your posts were sort of uniform and not too large in size, it seems like it might work.

    I’m going to look into it and see if it would work for a WP site I’m starting on that uses custom post types. If I come up with anything, I’ll post it.

    0
  57. 57

    Great article !!
    I’m curious to try out the in page text search.
    I’ll let you know how did it go.

    0
  58. 58

    thanks for sharing guys..
    JQuery has been applied in most of my projects these days.
    It always good to see some advanced work which out of the box.

    0
  59. 59

    I can’t see the “subtle hover effects” in the example…

    0
  60. 60

    super sick.

    -1
  61. 61

    It just doesnt seem to work in the fox (v3 here)

    0
  62. 62

    nice one.. thanks ^_^

    0
  63. 63

    Nothing to reply me?
    Then please delete my comment at least.

    0
  64. 64

    just what I was thinking.

    Nice article, just the first one does seem to be a case of doing something that doesn’t need to be done.

    0
  65. 65

    Useful, thanks.
    But the fifth one won’t work in the latest Opera browser.

    0
  66. 66

    nice post, thx

    0
  67. 67

    Fantastic article
    I’m trying the Drag Controls For Oversized Content
    Thank you

    0
  68. 68

    Very nice tips and tricks.
    BUT regarding the “subtle hover”-effect: You didn’t even use the stop()-command in your jQuery-script. That’s baaaaad behaviour, because now it stacks every hover-animation… :/

    Also, when I open the example in firefox 3.6, and I hover the FIRST time over the elements, they change without a delay – but after that, the animation plays like it should.
    Not a 100% finished script, I would say.

    0
  69. 69

    How about just Ctrl+f for page search? I have the search box always showing for in page search, so I think the first one is pretty stupid.

    1
  70. 70

    Yeah FF3 doesn’t support transition so it doesn’t work on Veerle’s blog. However the version we built here has a jQuery backup that works in all browsers.

    0
  71. 71

    Thanks for the information. Looking forward to use these advanced CSS effects, specially the mouse hover ease.

    0
  72. 72

    In any case I always try to make all content and features available for all users. Javascript is just a way to make things prettier, easier usable etc. For the ‘Full Page Slider’ I’d use a different approach: save all slides (just slide HTML; nothing more) in seperate files and create seperate pages (using the slide HTML files). WIth AJAX load all other slides into the DOM and handle the click event to other pages with javascript. In this way non-javascript users ( and Google ) will be able to look at all pages, javascript users will get a nice user experience.

    ( btw I was talking about the ‘drag controls for oversized content’ indeed but just didn’t look close enought at markup; my bad. You were totally right that it wasn’t an issue for SEO here )

    -2
  73. 73

    Thanks for your info ;)

    0
  74. 74

    Would love to see more articles like this! Keep them coming!

    0
  75. 75

    артлебедев ру ;)

    0
  76. 76

    Nice post.
    Where’s the subtle effect on Veerle’s page?
    When I search in the markup for “subtle” it finds nothing.

    0
  77. 77

    What would we do without jQuery?… =)

    0
  78. 78

    For the Full Page Slider is there anyway to target one of the slides? i.e. myurl.com/#slide2. The Jax example handles this quite well—it would be a great feature so that you (or I in this case) could send a link that targets a specific slide rather than the default. Also I should mention that if you click either of the arrows quickly all of the slides disappear. Anyhow this is excellent and gets me a long way, thank you!

    0
  79. 79

    For the full page slider, the arrows are not displayed inline with each other in Internet Explorer. Is there anyway to fix this?

    0
  80. 80

    Thanks for the great article. Love to see such new, relevant design code snippets.

    0
  81. 81

    Just mouse over / click into the search box. Some of the other elements on the page have the hover effect as well.

    0
  82. 82

    Yes, like I said in the post: “In our example, we built controls only for left and right navigation, but you could easily tweak this to have buttons for each panel. Simply pass the correct panel index to slidePanel.”

    So on page load you’d just have to pull in the hash value, and then point that to the right panel when you call slidePanel().

    0
  83. 83

    The styling of the arrows is just a quick example for this post, feel free to edit this styling however you want.

    0
  84. 84

    Feel free to fork the gist on github with any changes you may have.

    0
  85. 85

    Is there a way to add a scroll-to-top to the nav like Jax does? In cases of tall portfolio pages, this seems like an important feature.

    0
  86. 86

    Hi, I loved the article, specially the subtle hover effect, but I could’t figure out how to use this effect for changing for example from a black and white image to one ar full color. I can’t make it work. Which settings should I change?
    Thanks for the article!

    2
  87. 87
  88. 88

    Hi Jon Raasch,

    Im a noob in programming and i really need that Full Page Slider for my portfolio and dont know how to target a specific slide with a text or image link. So can you please give the code like how it should be where it should be placed or something so that we get an idea? Please :)

    Thank you…

    0
  89. 89

    The full page slider just gave me a great idea for a site design. Very nice!

    0
  90. 90

    hey jon, the full slider is cool! can you explain how i am able to target a specific slide with a text link (including the an active status if possible)…

    i am a noob in javascript and jquery and tried the last 3 days to get it work…

    thank u very much!
    tobby

    1
  91. 91

    article 1 – > simply superb and thanks a ton lotttt to the author

    0
  92. 92

    Awesome post, thanks Jon! I’ve searched around for an IBM-esque full width slider for awhile now and this is the best I’ve found. Would be really nice if auto-played and had different nav though. I’m going to see what other nav i can come up with following your target slide instructions to Jeremy. Thanks again! :)

    0
  93. 93

    do you have any hard data on browsers without javascript?

    0
  94. 94

    Hey, I don’t think telling you this on your post TIP a very nice jQuery sldier: Coda-Slider 2.0 | DESIGNfromWITHIN is the right place but I couldn’t find a contact form in your somewhat cluttered theme (sorry). My readers used to tell me the same so I switched over to a new theme, you should check it out on this website. I’ve only gotten compliments ever since. Regards, Marvin Hirschberg

    0
  95. 95

    Thanks for share!

    0

↑ Back to top