In this quick jQuery tutorial I’ll show you how to smooth scroll to an anchor after its link was pressed on a different page. Using jQuery this is quite straightforward
This is a feature I implemented on this very site. If you click on ‘About Me’ or ‘Contact Me’ on the above navbar, it will link to the top of my home page and then scroll (after an intentional brief pause as logo spins) to the respective section
PREREQUISITES
- To get me start I used a simple template from one of my previous tutorials on ‘Full background images with responsive centred elements‘. Follow that tutorial if you need elucidation on the HTML/CSS setup of the page I used to smooth scroll
- You’ll need both jQuery and jQuery UI for this to work. Copy and Paste into header:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
SETUP
We are going to create two webpages: The first will be the main scrollable page with full screen background images (main.html). The second (links.html) will just consist of five buttons which are linked to the various sections on the scrollable page.
SCROLLABLE PAGE (main.html)
When designing the scrollable page, include different id tags to the various sections you want to smooth scroll to. I did so in the form of the ids section-1, section-2, section-3 and so on
<div class="sections" id="section-1"> .... </div> <div class="sections" id="section-2"> .... </div> <div class="sections" id="section-3"> .... </div> ....
When the webpages URL includes the id of any of the sections, it will load the page having navigated to the location of the id. We want to counter this by moving the window to the top before the page fully loads then create a function which then smooth scrolls to designated anchor. Place this script within your pages <head> tags:
$('html').css({display: 'none'}); $(document).ready(function(){ var hashURL = location.hash; if(hashURL != "" && hashURL.length > 1){ $(window).scrollTop(0); $('html').css({display: 'block'}); smoothScrollTo(hashURL); } else { $('html').css({display: 'block'}); } });
$('html').css({display: 'none'})
hides the html page before it fully loads by setting the CSS display property to none. $(document).ready(function(){...})
waits for entire webpage to load (DOM, images, videos etc.) before running enclosed code. The variable hashURL stores the anchor part (if there is any) of a url by using location.hash property. We then check if the hashURL contains an anchor. If hashURL fails boolean test (is empty or has length of 1 meaning no anchor/link set in URL) the code in the else statement simply displays the html page. If the URL contains a link we move the webpage back to the top by setting scrollTop to 0, afterwhich we display the html page and call the smoothScrollTo() function to scroll to designated element:
function smoothScrollTo(anchor) { var duration= 5000; //time (milliseconds) it takes to reach anchor point var targetY = $(anchor).offset().top; $("html, body").animate({ "scrollTop" : targetY }, duration, 'easeInOutCubic'); }
The crux of the function is the animation done on scrollTop()
. scrollTop can set the viewports vertical position (in pixels) if its given a integer value. By placing it in the .animate()
method we ensure it vertically animates/scrolls a certain amount of pixels (value given by targetY variable). targetY
is retrieved by getting the given anchor element’s current coordinates (.offset()
) and by calling top
we extract the y-coordinate from these coordinates. As the doc states, the .animate() function can take 4 parameters, we will only use an additional 2; duration
(how long the animation should take) and easing
(the speed at which the animation progresses at different points within the animation). The reason for us downloading the jQuery UI suite was to broaden our repertoire of easing functions. Here I used the ‘easeInOutCubic’ function to create a nice easing effect. You may ask why we animate both the html and body elements in the smoothScrollTo() function. This is because we need to scroll on the webpages root element and different browsers set different elements as the root element. Chrome and Safari make <body> the root, whilst Firefox and IE make <html> the root. So we select both $(‘html, body’) for cross browser compatibility
LINKS PAGE (links.html)
This page is pretty straightforward. Just create 5 links which are linked to the different sections on the scrollable page:
<head> <style type="text/css"> body { margin: 20px auto; text-align: center; } a { position:relative; margin: 20px auto; font-family: 'Sans-serif', 'Palatino Linotype'; font-size: 1.2em; text-decoration:none; color: white; padding: 10px; height: 20%; width: 40%; border-radius: 10px; background-color: #081b36 !important; display: block; } a:hover { background-color: #0f3162 !important; } </style> </head> <body> <a href="main.html#section-1">Go to SECTION-1</a> <a href="main.html#section-2">Go to SECTION-2</a> <a href="main.html#section-3">Go to SECTION-3</a> <a href="main.html#section-4">Go to SECTION-4</a> <a href="main.html#section-5">Go to SECTION-5</a> </body>
NAVBAR ADDON
At this point we’ve fully implemented the smooth scroll feature. As a small extension I also included a navbar on the page. All the buttons link to a specific location on the page:
<nav> <a href="#section-1" class="same-page-scroll">Section 1</a> <a href="#section-2" class="same-page-scroll">Section 2</a> <a href="#section-3" class="same-page-scroll">Section 3</a> <a href="#section-4" class="same-page-scroll">Section 4</a> <a href="#section-5" class="same-page-scroll">Section 5</a> </nav>
and the CSS:
nav { position: fixed; z-index: 100; width: 100%; background-color: #76101e; text-align: left; font-family: Ubuntu, 'Sans-Serif', Times, Arial; font-size: 1.2em; padding: 15px; border-bottom: 5px solid #580c17; } nav a { padding: 15px 15px 15px 15px; text-decoration: none; color: #fdeef0; } nav a:hover { background-color: #580c17; }
To make each navbar link smooth scroll down to specified location just add this code just before closing your <body>:
<script type="text/javascript"> $('a[href^="#"]').bind('click', function(event){ var anchor = $(this).attr('href'); smoothScrollTo(anchor); return false; }); </script>
a[href^="#"]
is a CSS selector which selects every <a> element whose href attribute value begins with “#” (an anchor/ link). .bind()
overrides a specific event for an element (in this case the ‘click’ event) with your custom code. So when we click on any <a> element on the page with an anchor as the href, we retrieve this anchor by calling $(this).attr('href')
, then use the smoothScrollTo() function to smooth scroll to anchor point. To ensure the click events default actions are not called, return false
.
To get a better sense of how this all comes together view complete code on Github