More Noticeable HTML Bookmarks

I have always been interested in elegant yet helpful techniques that in some way extend or rewrite native browser functionality and therefore help making websites a bit more better than they could be. The last time I shared a technique for mobile-friendly and responsive tooltip, which indirectly extends functionality of title attribute in HTML. This time: thoughts and a piece of code for, as titled, more noticeable HTML bookmarks with jQuery.

Actually, it's nothing new, nothing that you could not do or think of on your own. Just sharing thoughts and code of what I have come up with while working on UX purposes.

More Noticeable HTML Bookmarks

The Problem

Let's say you have an anchor that links to a particular location (which is actually location of the respective HTML element) on the same or other page of your website. Fine if the element is surrounded with a huge amount of the famous white space, fine if it is in the user-focus area and therefore easily noticeable. But, what if, in the worst case, it is a tiny little object squeezed among larger ones? Actually, I have a pure example here...

There is a small newsletter form in the footer of this website and I would like to encourage you subscribing to my newsletter if you haven't yet. If I bookmarked it in the old way I am pretty sure you would hardly notice the form in a second or two. In web design this is a huge amount of time which means a lot when it comes to engaging users to your product.

How It Works

When a page is loaded or an anchor is clicked, the script looks up for an element in HTML by id whose name has been provided via fragment identifier on page-load or href attribute value of an anchor when clicked. If the element exists, the browser then just smoothly scrolls to the location of the element and shakes it horizontally if it has an attribute/value data-bookmark="nudge" defined.

So, it's not only the shake that helps to notice the target, but also, the animated scroll itself makes easier to understand where you are on the page, whether you are being thrown to the top or bottom. I think your users would thank you for that.

Code

Here's a piece of JavaScript code, which is responsible for doing what mentioned above except the nudging.

$( document ).ready( function()
{
    function notice( selector )
    {
        var el = $( selector );
 
        if( el.length < 1 )
            return false;
 
        $( 'html, body' ).animate( { scrollTop: el.offset().top }, 500, function()
        {
            if( el.attr( 'data-bookmark' ) == 'nudge' )
                el.nudge();
 
            if( window.location.hash != selector )
                window.location.hash = selector;
        });
    }
 
    $( 'a[href*="#"]' ).click( function( e )
    {
        var current_url = window.location.toString().replace( /#(.+)/i, '' ).replace(/\/+$/, '' ),
            new_url     = $( this ).attr( 'href' ).replace( /#(.+)/i, '' ).replace(/\/+$/, '' );
 
        if( new_url == '' || new_url == current_url )
            e.preventDefault();
 
        notice( $( this ).attr( 'href' ).replace( /(.+)#/i, '#' ) );
    });
 
    if( window.location.hash != '' )
        notice( window.location.hash );
});

Now that we have the the first part done, still there is one unknown – a function called nudge. The way I applied it may automatically mean it is a native method of jQuery. Unfortunately not, but why not to extend the library so that we can use this function in a vary of situations later?

No matter how your element is positioned, the function adapts and keeps it in a default state when shake is complete.

jQuery.fn.extend(
{
    nudge: function()
    {
        this.each( function()
        {
            if( $( this ).is( ':animated' ) )
                return false;
 
            var obj      = $( this ),
                pos      = obj.css( 'position' ),
                left     = obj.css( 'left' ),
                left_int = parseInt( left ) || 0;
 
            if( left_int != 0 && left.search( '%' ) > -1 )
                left_int = obj.parent().width() * left_int / 100;
 
            if( pos == 'static' )
                obj.css( 'position', 'relative' );
 
            setTimeout( function()
            {
                obj.stop( true, true )
                   .css( 'left', left_int + 'px' )
                   .animate( { 'left': left_int - 5  + 'px' }, 50 )
                   .animate( { 'left': left_int + 10 + 'px' }, 100 )
                   .animate( { 'left': left_int - 10 + 'px' }, 100 )
                   .animate( { 'left': left_int + 10 + 'px' }, 100 )
                   .animate( { 'left': left_int - 10 + 'px' }, 100 )
                   .animate( { 'left': left_int + 5  + 'px' }, 50, function()
                   {
                       obj.css( { 'position': pos, 'left': left } );
                   });
            }, 500 );
        });
    }
});

Finally, let's just write some typical HTML code, for example:

<a href="#newsletter">Subscribe to newsletter!</a>
 
<!-- here goes some "stranger" code -->
 
<form id="newsletter" data-bookmark="nudge">
  <!-- ... -->
</form>

I recommend using data-bookmark="nudge" wisely and nudge only what is really necessary. Do not shake huge elements. This may look and feel inadequate and lame.

Demo

See the demo.

How To Implement it

Just put both JavaScript's in existing JS file or create a new one and include in HTML. See the example above and modify your HTML if necessary. That's it, couldn't be more simple.

Post Scriptum

Because I defined nudging function as an extension/method of jQuery, next time I am going to fully justify my behavior by putting it in more use. What about shaking user login form when wrong username/password entered? Yes, that's Apple-inspired.

&