By Raena Jackson Armitage

Thinking Laterally: Build a Side-scrolling Site Layout with CSS & jQuery

By Raena Jackson Armitage

Ever since I saw Tyler Finck’s, I’ve been looking everywhere for an excuse to try out a smooth-scrolling horizontal layout like his. It’s by no means a new trend, but it’s one that few of us have had the opportunity to use, and it’s still unusual enough that you really do notice when you see it.

A sideways style lends itself well to designs with a bit of an “arty” feel: brochure-style sites, galleries, portfolios, and perhaps even sites that make use of interesting info-graphics or charts. Successful horizontal layouts often use animation and graphics to highlight their sideways movement — a large number of these sites use colorful images and nice, big backgrounds that really show this off. Unusual also means unfamiliar, so a well-designed horizontal layout will also make good use of navigation elements such as menus, arrows, and buttons to overcome any usability hitches.

As far as what goes into one of these sites — well, it turns out that it’s actually pretty easy. Let’s take a look at how to build our own groovy, scrolly, sideways website using just a bit of simple CSS and jQuery.

Planning it out

First of all, we’ll need to figure out what’s happening in this site. Imagine that we’re building a simple brochureware site for a fictional brick-and-mortar store selling fashionable shoes. There’s very little information to convey here:

  • a small piece of introductory text
  • a newsletter signup
  • directions and contact info
  • a contact form

Fashion is a pretty groovy sort of business, so the unusual horizontal layout is a good fit for this sort of site. If you can imagine each of the four items as being a panel, then you might arrange each of them in a row. Only one panel would be visible at one time, just as if they were separate pages, meaning that our layout’s overall width needs to be a good deal wider than the browser window — our viewport. In the diagram below, our viewport is represented by a red square surrounding the first panel, and the overall width of our body element is represented by a blue one:

Panels, viewport, and the body element

This should be easy enough to code!

Adding markup and styles

To mark this up, we can use four little div elements inside a body. The markup for this might look something like the following example:

<body> <div id="home" class="panel"> ... </div> <div id="newsletter" class="panel"> ... </div> <div id="directions" class="panel"> ... </div> <div id="contact" class="panel"> ... </div> </div> </body> 

To achieve the effect of each panel being a standalone “page”, and also to give us some space to play with for our animation, we’ll need each of the panels to occupy at a lot more space than our viewport — let’s allow 960 pixels for the actual content, and an additional 1040 pixels for extra space, making each panel occupy a total of 2000 pixels in width. Here’s a little CSS to make this work for us:

body { width: 8000px; } .panel { width: 930px; float: left; padding-left: 30px; padding-right: 1040px; } 

You can see how this looks so far in demo 1, which also includes some content and shading. Unless you have a gratuitously wide monitor, you should only see one page at a time whilst you scroll from side to side. Groovy!

Adding navigation

This is all very well so far, but what about an easier way to move around the page? Let’s build a menu of four links:

<ul id="banner"> <li> <a href="#home">Home</a> </li> <li> <a href="#newsletter">Newsletter</a> </li> <li> <a href="#directions">Directions &amp; Opening Hours</a> </li> <li> <a href="#contact">Contact us</a> </li> </ul> 

Of course, the links’ targets match the divs’ IDs, so we know that clicking on each would let us leap straight to the relevant anchor on the page. However, as soon as we click one, our menu disappears — it’s back at the top left of the body element, where we can no longer see it. If we use a fixed position to attach the menu to the top of the page, we can even make sure it sticks around while we go zooming around. An item with fixed positioning is removed from the overall flow of the layout — we’ll need to add some more space at the top of those panels to leave room. While we’re at it, let’s make that menu look a little more like a menu:

.panel { ... margin-top: 45px; } ul#banner { position: fixed; line-height: 45px; margin: 0 30px; padding: 0; } ul#banner li { display: inline; } 

We’ve made space for the menu by setting a line-height of 45 pixels, and a matching top margin on the panels to make sure they stay well clear. You can see the result in demo 2, where you can click all four links and bounce between panels.

Smooth scrolling

Now that you have your content and menu in place, you can use a little bit of jQuery to smoothly animate around your nice long canvas. We’ll listen out for clicks on our menu links, and then replace the default behaviour with our own: instead of just jumping right to that part of the page, we’ll smoothly scroll over to the right element using jQuery’s animation methods. Here’s what that looks like:

$(document).ready(function() { $("#banner a").bind("click",function(event){ event.preventDefault(); var target = $(this).attr("href"); $("html, body").stop().animate({ scrollLeft: $(target).offset().left, scrollTop: $(target).offset().top }, 1200); }); }); 

Here’s how that breaks down: first, we prevent the default behaviour from occurring. Next, we set up a variable to hold the href value of our link. Thirdly, we perform a few actions with both the html and body elements:

  • stop makes sure that any currently playing animations stop right away — if someone’s clicking on several menu links, we won’t have to wait for all the scrolling actions to complete.
  • Next, to animate our scroll behaviour — we work out where we need to scroll by calculating how far away our target is, relative to the left and top of the document, and use scrollLeft and scrollTop to do so.
  • We set a duration of 1200 milliseconds (1.2 seconds) for the effect, which should leave plenty of time for admiring the scenery as it whizzes by.

That’s all you need! Demo 3 shows you how it all comes together.

But what about the pretty stuff?

Now that you have the bones in place, you can start adding some colour and liveliness to your sidescrolling design. I’m certainly no Tyler Finck, but even I can improve on the grey, boxy demos we’ve seen before. In demo 4, you’ll see that I’ve added a big background image that changes the feel of the site from panel to panel. I’ve also added some opacity to the background colour on the menu, and rearranged the markup somewhat to allow for a title in the menu there. Finally, I’ve rearranged this somewhat so that when JavaScript is off, the layout reverts to a regular vertical-scrolling one.

  • Use previous and next buttons on each panel, guiding your readers along a path
  • Add some more adventurous background images in those big, wide gaps between content areas
  • Why be restricted to horizontal scrolling? Use this technique to zoom all over a big, square canvas!
  • Use JavaScript to add more or less space between panels, based on the current viewport size
  • Roll this into a set of media queries — little screens can certainly skip the show

However you choose to use it, one thing’s for sure — while this has been a bit of a trend in web design for awhile, it’s still unusual enough that your site’s sure to stand out. I know I’ll be considering it for my next mini site!

And if you enjoyed reading this post, you’ll love Learnable; the place to learn fresh skills and techniques from the masters. Members get instant access to all of SitePoint’s ebooks and interactive online courses, like Learn CSS3.

Comments on this article are closed. Have a question about CSS3? Why not ask it on our forums?

  • TheHustle©

    I just recently built one.

    *apologies for the audio. Not every decision is in the hands of developers.

  • jakub.chodorowicz

    That’s quite useful, I was wondering how to do such effect. Thanks

  • Matthew Nuzum

    One step missing: making the back button do what it should. (i.e. take you to the screen you were on previously rather than the page you were on before the current site)

    • Chris F.A. Johnson

      Matthew, I agree.

      Also, there is no way to bookmark a page.

    • Silver Firefly

      I’m sure you can find a way of adding this function. This tutorial was for bare bones, rather than showing you how to do every single thing.

    • Indeed that is not there. You could use something like this:
      …to support it (check out the accordion demo; it’s pretty sweet)

    • Noah

      Actually pressing the back button on your browser should take you back to the site you were on previously. This side scrolling technique is just 1 big page with div’s created so large it gives the illusion that you’re scrolling through various pages.

  • dr john

    Your timing is perfect!
    Over the weekend I decided to try something very like this just to practice on, and here’s your helpful article! Saves me a bit of background research.

  • Ron Bigus

    Here is a Horizontal Scrolling Menu I recently added to our Company Website.

    Scroll down slightly to see the sliding links to my Community Videos.

    I adapted this from a marquee js file created by Arturs Sosins aka ar2rsawseen,

  • Oscar

    Some years ago (when I was just starting with JQuery) I wrote and share a similar script:
    Actually I like your code, thanks!

  • Wim Michiels

    The example (demo4.html) works fine in IE8 and in Google Chrome 10.0.648.11 but it doesn’t run smoothly in Mozilla Firefox 3.6.13 it moves jerkily.
    What can be the reason?

    • Nathair

      also using firefox 3.6.13 and moves smoothly here, so might be some add ons or extensions?

    • I’m not sure, Wim, but in my version of Firefox it doesn’t exhibit that behaviour. Could it be the addition of a background image?

      • jim

        Firefox 3.5.16: demo3 and demo4 both work fine from “page” links or scrolling wheel on my mouse

        Opera 10.63: selecting any position jumps back to initial (home) position then proceeds to selected position; scrolling wheel on mouse doesn’t work at all

        IE7: page loads slowly and navigation links are missing altogether!; scrolling wheel does not work either

        Safari 5.03: cannot tell; every since upgrade to 5.03 I cannot get the address text box to process any new URL; oh, I can enter or paste any URL into the box but clicking GO or pressing ENTER merely results in the original URL being re-loaded instead of loading the new URL!!

        And I guess that is why I use FF all the time and only “touch” the others to test my sites’ cross-browser appearance! :-)

      • jim

        P.S. Love the effect; cannot wait to find a client to try this out on! :-)

  • Silver Firefly

    This came just at the right time for me. I already had an idea of how to do this but your tutorial made things clearer. Thank you. Bookmarked and tweeted. :-)

  • ReedFisher

    Very cool, only it fails in Safari on my iPad. Is making it more cross-browser compliant difficult?

    • BrenFM

      iOS Safari behaves completely differently to a normal browser. Hard to explain in words but it’s all about the viewport. Statically placed elements don’t stay in one place like you’d expect. I assume that’s where your issue is? Check out this page on github:

      Used this successfully on a project which I can’t show you as it was a temporary promo site, but trust me, it works.

      • BrenFM

        sorry for replying to myself, but I whacked a simple clear:both style declaration on the “directions” div and immediately got the 2d scrolling effect I was looking for – i.e. it totally works, So cheers for the hints there, Raena!

    • I doubt it’d be too hard, but unfortunately I have no iPad to play with at the moment. I’d probably consider a different approach for a mobile device, anyway.

      Come on Apple, announce a new iPad already!

  • BrenFM

    Cheers Raena. I’ve tried to implement something simliar – only with 2 dimensional scrolling – using jquery scrollTo plugin, but it’s REALLY buggy in some browsers (oddly enough firefox is one of them – Webkit makes it the awesome).

    Might have to have play with the code you’ve got here and see if we can’t get more win on this project.

  • Nige

    It looks fantastic, the iPhone & iPad thing is obviously a problem though, any ideas to sort it out?

  • wanderer

    i’m sorry, but this is a very very bad example, which ignores all best practices for accessible web.
    if you are navigating to other page your url in address bar must change and you back button must remain functional. period.
    if as a developer you fail to implement this you shoul go back to drawing board, seriously.
    it’s a pity to see sitepoint publishing such a low quality content, which can misguide a lot of begginners

    • Hi wanderer — since you’re not actually navigating to a different page, there’s no need to change the button. There’s a discussion in other comments (and at the end of the article, too) about adding different behaviours to enhance it. I’m sure you can think of some ways. Unfortunately I can’t always go through every single part of a website build when talking about one technique. Thanks for writing, though.

      • wanderer

        thanks for reply, but
        as far as USER is concerned you actually are navigating to different page. this is a default behavior of web and you shouldn’t break it, otherwise your users will be confused and angry.
        for example, a lot of modern laptops (esp. macbooks) allow you to swipe left/right on touchpad to go back/forward in browser, and i’m a big fan of this and use it all the time, but unfortunately your example totally screws my behavior.
        although this effect is cool, it should be more clearly stated in article that it must be coupled with more advanced techniques like changing the url in address bar and ajax calls. you can’t just take it and easily trow it in every site out there.
        for years we were crapping on badly made flash sites for the lack of back button and we shouldn’t go same route again with javascript.

    • Biodun

      Remember, everything that goes around comes around.
      You just have to embrace the new technology only if you want to run out of business as a web developer.

      Remember core simplicity is what the technology is all about.

      Client are tire of going through the whole web just by clicking and clicking, sometime its take time for the old technology of clicking -home.html -about.html etc to load. But with this your client will be on one page and do all what they want to do.

      Friend, go for it!

  • Phil D

    Instead of using the body tag,
    could this be done inside a wrapper that
    was the same width with an overflow hidden?

    I’m asking because I’ve never been a fan of vertical scroll bars

  • Rome

    What about SEO? how pages will be address if all is on one sliced screen?

  • Claudia

    I like it! One drawback is also that it does not work gracefully without JavaScript enabled. I know I’m old school making this a requirement, but it’s still up there in what I’m looking for. Thanks for the great article!

  • Larry May

    There are 13 different types of scrolling websites seen at:
    Very creative.

  • Hi Claudia,

    In demo 2 you can see that it still works without the JS in place — clicking any tab jumps to that spot on the page. You can also sidescroll with the scrollbar, although you have quite a bit more scrolling to do!

    If you look at demo 4, you’ll see how I’ve made it work only for clients with JS on with some judicious use of classes.

    I bet you can think of lots of other graceful alternatives. :) Thanks for the note!

    • Partha Bhattacharya

      Demo 4 is impressive.. Thanks for this article, Raena.

  • Federica Sibella

    Hi Raena, nice tutorial!
    A while ago, we did a little experiment to play with both horizontal and vertical navigation (unisg jQuery), you can see it here:

    Have a look if you like and tell us what you think about it :)

    • Partha Bhattacharya

      Nicely done, but a bit confusing.. Also, the fonts and the sizes do not look clear!

  • Sphamandla

    Great article guys thanks a lot

  • vinplex

    Nice post! I once saw a French designer’s site who had the same effect, but his also went vertical as well as horizontal. I thought it was a very creative way to show off his portfolio, and instead of standard links, he used little squares of different colors, which like yours, corresponded to the background color of the page section. Good stuff. I’d link, but alas, the site is no more.

    Thanks for the great turorial!

  • tbritt18

    Thank you so much for this tutorial. This stripped down approach is great for people like me:)

    How would I go about implementing the vertical scrolling? I’d like to create the square box effect.

    Do I add something to the javascript or does it have to do with playing with the widths in the “body”and “panel” elements?


    • Hi tbritt,

      That’s right — have a play with the body and panel. Using scrollLeft and scrollTop takes care of scrolling up and down, as well as left and right, as it is.

      Say you have 8 panels of 2,000 pixels each wide and tall. If you make your body element 8,000 pixels wide, and your panels are all floating left, you should have two ‘rows’ and four ‘columns’ of boxes.

      You might need to add in some min-height:blah or display:table-cell trickery to make sure they form a square, or perhaps some other tricks to get the rows to work properly.

  • kruti pandya

    I was very fascinated, when I saw such site few days a ago, and was wondering how to do this trick. Your article is very informative. But I think The site built on this way is not search engine friendly, Because, you have no more separate pages for your key words and the other important info.

  • Luis Cunha

    Excelent Stuff i was just looking around for something like that !

  • Michael

    It may not be for every website or every need – but what a great tool. I can see using this kind of format to break up a very long FORM into sections, making the user experience much better. Thanks!

  • jhanzaib

    its ok

  • Rudie

    You can do this with CSS3 without JS with :target and transitions

  • Ronny

    Does not work in IE7 coz the nav bar is invisible… css issue somewhere?

  • Ronny

    Solution to IE7 problem found: add “top: 0px;” and “left: 0px;” to the #banner in the css file to postion it top left.

  • Kent


    That is AWESOME! Now I, like you, am going to be jonesing for a project that I can add that to. Thanks for the excellent right up.

  • Oliver

    I really want to build one. but what is jquery? step one i understand. But getting it to divide into separate pages i don’t understand. Where should the code go with all the pixels? I am very new to all this and i want a side scrolling website for my furniture business.

    Any help and advice to achieve this would be great. Thanks very much.

  • zayno

    hi, i like your horizontal scroll ,but i have a small glitch,i can’t seem to access any link when i comment out the ajax code i can link trough but when i commented out back i can’t.I saw the demo 4 of your example and saw that you used a absolute link, could that be the glitch?? i always use relative links, please help

  • hi raena,

    i’m trying to do this vertically. is there a way to load at the bottom of the page? how do ensure the vertical scroll bar doesn’t show?

    thanks and great article!


    • Add:

      body {
      overflow: hidden;

      in your css file to make sure you don’t see any scrollbars.

      I’m building a website using this tutorial right now, but it doesn’t work in IE (9). I updated the JQuery sourcecode, but that didn’t make any sense. Does anyone know how to fix this? Thanks!

  • I’m considering using this on a personal site, but I was wondering if you might know if this is possible to implement with a CMS.

    I love the how everything is explained and ease of reading. As a student in Multimedia that is a big plus :)

Get the latest in Front-end, once a week, for free.