
Have you ever started reading an article only to be distracted by wondering about how much more there is read? This not knowing is one of the reasons users often cite for abandoning a page, or even the whole website. The act of breaking off from reading to take a look at how much more content there is obviously disrupts the user experience, and it’s all too easy to lose your place and decide to give up on the content entirely.
Award-winning news site, The Daily Beast (www.thedailybeast.com), has developed an innovative sidebar that they call the ‘READ THIS.list’. The secret to its success is in the multiple functionalities it provides. First, it is a list of all the articles on the page, each one just a click away.
The sidebar indicates which article you are currently scrolled to but, most interestingly, it shows your progress through the article by way of a progress bar that fills from left to right as you scroll down. Simple really, and very intuitive for the user, with no instructions required to explain its use. In this tutorial you’ll learn how to emulate this feature and design your own menu for showing progress through a story.
Start with the HTML
This tutorial provides enough explanation for you to integrate the technique in your own projects, however, the progress bar element is HTML5 technology so do keep that in mind if you need to cater for older browsers. We’re declaring the HTML5 doctype, linking to the stylesheet, a copy of jQuery and the jQuery plug-in.
001 <!DOCTYPE html> 002 <html lang=”en”> 003 <head> 004 <meta charset=”utf-8”> 005 <title>2BR02B by Kurt Vonnegut</title> 006 <link href=”resources/style.css” rel=”stylesheet”> 007 <script src=”resources/jquery.js”></script> 008 <script src=”resources/scrollnavprogress. js”></script> 009 </head>
The progress bar values
Several variables are created when the page is loaded. ‘top’ for the current vertical scroll position, ‘sheight’ the total height of the page. Sections are given their own progress bar and offsets are worked out (using trial and error -4, -90, -160, -210). These offsets determine when each progress bar starts incrementing.
001 $(document).ready(function () {
002 $(window).scroll(function () {
003 var top = $(this).scrollTop(),
004 sheight = $(document).height(),
005 scrll = (top / sheight);
006 $(“#progress_bar1”).attr(‘value’,
((scrll)*300)-4);
007 $(“#progress_bar2”).attr(‘value’,
((scrll)*300)-90);
008 $(“#progress_bar3”).attr(‘value’,
((scrll)*300)-160);
009 $(“#progress_bar4”).attr(‘value’,
((scrll)*300)-210);
010 });
011 });
Set maximum values
The max parameter for each progress bar is adjusted so that each bar is just filled as the end of its section scrolls out of the top of the viewport. A more sophisticated solution could be developed that dynamically creates the menu based on headings and their position within the document.
001 <div id=”main”> 002 <div id=”sidebar”> 003 <div class=”menu”> 004 <a href=”#top”><img src=”resources/phone.png” alt=””></a> 005 <progress id=”progress_bar1” value=”0” max=”84”></progress> <a href=”#partone”><h4 class=”caption”>Part One</h4></a> <p class=”subtitle”>Everything was... </p> 006 <progress id=”progress_bar2” value=”0” max=”67”></progress><a href=”#parttwo”><h4 class=”caption”>Part Two</h4></a><p class=”subtitle”>The painter thumbed his nose</p>
Content anchoring
Moving from the latest HTML5 functionality back to possibly the oldest, simplest and arguably the most important HTML code, anchor tags are added here to enable the menu to provide one click access to any of the story sections. Code in the plug-in enables the animated scrolling to these sections.
001 <div id=”content”> 002 <a name=”partone”> </a> <p>Everything was ...</p> 003 <a name=”parttwo”> <hr style=”width: 100%;”></a> 004 <a name=”partthree”> <hr style=”width: 100%;”></a> 005 <a name=”partfour”> <hr style=”width: 100%;”></a> 006 </div>
This is the end
After the footer, a plug-in function is executed that determines the positioning of the sidebar. In this tutorial, once the header scrolled away, the sidebar menu is fixed at 10px below the page top until the last 250px of the page is reached, when it is unlocked and free to scroll again.
001 <script>
002 (function($) {
003 $.lockfixed(“#sidebar .menu”,{offset:
{top: 10, bottom: 250}});
004 })(jQuery);
005 </script>
The CSS
The purpose of the technique is to make your content easy to digest, but it’s important to consider how your styling decisions will impact on usability too. Take time to experiment a little with your CSS and keep reviewing your layouts to see if improvements can be made.
001 @import url(http://fonts.googleapis.com/
css?family=Rokkitt:400,700);
002 body {
003 padding: 50px;
004 background-color: #eef4ee;
005 font-family: ‘Rokkitt’, serif;
006 }
007 h1,h2,h3,h5,h6 {
008 color: #da0933;
009 margin: 0 0 20px;
010 line-height: 1.1;
011 font-weight: 700;
012 }
013
Shorthand properties syntax
The paragraph margins here are an example of a shorthand properties tag. 1 and 4 value syntax is easy to guess (1 value = all values equal, 4 values = each value as specified), but what’s the rule for 2 and 3 value syntaxes? Where 2 values are provided the first value represents the top and bottom, the second value represents the right and left edges. With 3 values, the first value is the top, second value right and left, and third value, the bottom.
001 p {
002 margin: 0 0 20px;
003 color: #777;
004 font-size: 22px;
005 font-weight: 400;
006 }
Start at the top
The #head is where you’ll often put your primary navigation, but in this case it just holds the heading and a little divider. This content will then disappear when you scroll up, so any content that you want to be ‘persistent’ will need to go into the sidebar.
001 h1 {
002 font-size: 60px;
003 }
004 a {
005 color: #da0933;
006 text-decoration: none;
007 }
008 #head {
009 width: 100%;
010 border-bottom: 1px solid #CED5E5;
011 }
Should I stay or should I go?
The #main <div> is going so it is given a position: relative; but the #sidebar is staying and has a position: absolute; property. While it is given a top value of ‘0’, there is some code at the bottom of the HTML where offsets are added so the content scrolls up to the offset point and stays there until the bottom offset point comes in to effect.
001 #main {
002 position: relative;
003 }
004 #sidebar {
005 width: 280px;
006 position: absolute;
007 left: 0;
008 top: 0;
009 }
Moving on up
You could remove the width property for the content and still achieve a relatively accurate responsive layout. However, if responsiveness is important to you, you will need to work on binding the start and stop points of the progress bars to actual element position in the DOM, rather than using fixed calculation based on observed positions during the page design.
001 #content {
002 margin-left: 250px;
003 top: 0;
004 border-left: 1px solid #CED5E5;
005 width: 600px;
006 padding: 10px;
007 }
Bottoms up
Ensure the height enables the display of all your footer content and adjust the bottom offset specified at the bottom of the HTML to suit. Too large an offset in relation to the footer height and the sidebar will move off the page prematurely at the page bottom. Too small and the footer will crash into the sidebar.
001 #footer {
002 height: 180px;
003 border-top: 1px solid #CED5E5;
004 padding: 10px;
005 font-size: 18px;
006 }
Fit for purpose
When determining the width of your sidebar menu, consider how much space you will need to create meaningful navigation labels for your content. You don’t want to find yourself with too little space, but equally you shouldn’t steal too much space from the main content area – the content comes first after all.
001 .menu {
002 margin: 15px 5px 0 0;
003 padding: 2px;
004 position: static;
005 top: auto;
006 width: 235px;
Navigation labels
The large negative top margin of the .caption positions this content on top of the progress bars. If you change the progress bar height or the size of the .caption or .subtitle text, you may need to adjust this top margin and the bottom .subtitle margin to position the text on the progress bar as you wish. Make sure the text colours you choose work well with the filled and unfilled bar colours.
001 .caption {
002 text-transform: uppercase;
003 margin: -55px 0 0 5px;
004 font-size: 22px;
005 }
006 .subtitle {
007 margin: 0 0 25px 5px;
008 font-size: 17px;
009 color: #eee;
010 }
Style the progress
The default appearances (which are difference in each browser) are stripped away to give us a reasonable starting point to work with. It is worth drawing attention to a difference between Mozilla and WebKit browsers here. With Mozilla, the background to the progress bar isn’t prefixed, it’s specified as part of the simple ‘progress’ property and the ‘slidey-bit’ is prefixed and known as the progress-bar.
001 progress {
002 -webkit-appearance: none;
003 -moz-appearance: none;
004 appearance: none;
005 border: 0;
006 height: 60px;
007 width: 229px;
008 background-color: #aeceaf;
009 }
Bars and values
In WebKit browsers both elements are prefixed, the progress-bar is the background element though and this time the ‘slidey-bit’ is known as the progress-value. Don’t worry, it’s not unusual for your values to become confused when there are number of bars involved!
001 progress::-moz-progress-bar {
002 background-color: #000;
003 }
004 progress::-webkit-progress-bar {
005 background-color: #aeceaf;
006 }
007 progress::-webkit-progress-value {
008 background-color: #000;
009 }
Border box fix
The border box fix is used to improve consistency across the browsers. Paul Irish (bit.ly/1bOCe3b) and Chris Coyier (bit.ly/1l1q1Lq) both offer detailed explanations of this issue, which are definitely worth a read. The fix ensures that the formatting of elements is handled consistently on the page by adding borders and padding inside them rather than adding to their size.
001 div {
002 -webkit-box-sizing: border-box;
003 -moz-box-sizing: border-box;
004 box-sizing: border-box;
005 }
Prevent a crash
To avoid having the footer crash into the locked sidebar, it is unlocked if the offset value specified in the bottom of the HTML is reached and will scroll neatly up the page. You’ll need to adjust the offset in conjunction with the #footer height to achieve a pixel-perfect result.