Grow your CSS skills. Land your dream job.

How To Create a Horizontally Scrolling Site

Published by Chris Coyier

If web pages were made out of wood, the grain would be running up and down. Vertical is the natural flow of web layout. When page elements reach the right edge of the browser window and go over, the flow defaults to "wrapping" that element down onto the next line. The more content on the page, the taller it gets, not the wider. Why is this? Because it just makes sense. Our eyes are used to reading fairly short lines of text, so if we were to see a paragraph of text in one long straight line, it would be painful to read. Paragraphs need to have line breaks in them to be readable (hence the term "blocks" of text). We sure as heck don't want to hard-code line breaks into the markup ourselves. Obviously, we don't have to, the browser does this wrapping for us. Thus the vertical expansion.

This natural flow has lead to conventions in web page layout and even into hardware itself. Notice how many computer mice (mouses?) have a special scroller exclusively for vertical scrolling. But web pages are equipped with both vertical AND horizontal scrollbars right? If we are responsible with our web layout, we can go "against the grain" and create web pages that use primarily horizontal scrolling and can even expand horizontally as we add more content. Perhaps a slight blow to "usability", but it sure can be a cool creative touch!

View Demo   Download Files

The best way to do it

I'm going to go out on a limb here and say that I think a table is the best layout technique for a horizontally scrolling site. Before I explain why, let's look at a couple of other possible techniques:

  • Set a really wide static width. Perhaps the "quick and dirtiest" way to get a horizontal layout started is just to set a really wide static width on the body element itself. Say, 10000px. Go ahead and try it, you'll surely get a horizontal scrollbar. While this works, it's a bit inflexible. Web pages are dynamic places and we should be prepared for expandability, not limiting ourselves with static widths. Think about regular vertical scrolling sites. You don't go around setting static heights on your pages do you?
  • Floats + Whitespace. I spent some time playing with the float property and the white-space property to see if I could find a way to fight browser auto-wrapping, but I didn't have much luck. Page elements which are floated but do not have a width exhibit a property where they expand to the width of the content inside them. I thought perhaps if I put a bunch of float elements inside of that, it might just keep expanding beyond the width of the browser window. No dice. There is also a white-space: nowrap; property in CSS which I thought might be able to be exploited to fight the auto-wrapping, but it only works for text elements, not blocks or just any old thing you set to inline. Oh well.
  • Use JavaScript to set a width. JavaScript clearly has the ability to manipulate page elements and do calculations on-the-fly. We could use this to create an environment which behaves extensibility. However, it considered bad mo-jo to handle page layout with JavaScript. I agree with this in general, but I do believe you can use JavaScript in this way as long you do so unobtrusively and take care to ensure the page will fall back to a usable layout with JavaScript disabled.

The <table> method

What we need is a page element which can expand horizontally as needed and never "wrap". A row of table cells fit the bill perfectly here. Table cells will expand to fit whatever content is inside them by their nature, and the will never wrap until a new row is started. Perfect.

Let's assume we are trying to lay out a series of blog posts one after another horizontally. We would need to use a page structure like this:

<table>
  <tr>
    <td>
       ..  blog post #1
    </td>
    <td>
       ..  blog post #2
    </td>
    <td>
       ..  blog post #3
    </td>
  </tr>
</table>

Yuck, right? It never feels good to use markup like that, not just because it's a table, but also because of how non-semantic it is. We are using a bunch of tags here which are exclusively for presentation and have nothing to do with content.

Ideally, our page structure would be like this:

<article class="post">
  .. blog post #1 ..
</article>
<article class="post">
  .. blog post #2 ..
</article>
<article class="post">
  .. blog post #3 ..
</article>

Using jQuery, we can easily have the best of both worlds!

Write the markup we want, get the markup we need

We are going to use jQuery to allow us to the markup we want (the div structure) and manipulate it to get the markup we need for horizontally scrolling (the table structure). You should have little alarms going off in your head here about using JavaScript for layout, but rest easy, we will ensure that without JavaScript enabled the layout will be perfectly useable. As an added bonus, the layout will be useable with or without CSS enabled as well, and any combination.

Let's first think through what we want to happen:

  • Wrap ALL of the posts in a single table tag and single row tag
  • Wrap EACH post in a table cell tag

Now let's include jQuery on our page in the head section, and write the jQuery we need to get this done.

<script src="js/jquery.js"></script>
<script>
	$(function(){
		$("#page-wrap").wrapInner("<table cellspacing='30'><tr>");
		$(".post").wrap("<td>");
	});
</script>

That should do it! Notice how the cellspacing is added as an inline attribute to the table element. We might normally apply padding to cells with CSS, but we want to make sure that each blog post block is as readable as possible even with CSS turned off. Without this, the blocks would butt right up against each other making them tough to read.

The entire CSS file for this example is very very simple:

* {
	margin: 0; 
	padding: 0; 
}
body { 
	font-size: 62.5%; 
	font-family: 'Lucida Grande', Helvetica, sans-serif;
	background: #121212;
	color: #999; 
	padding: 20px;
}
tr { 
	vertical-align: top;
}
.post { 
	width: 500px; 
}
p { 
	font-size: 1.2em; 
	margin: 0 0 15px 0; 
}
h1 { 
	font-family: Sans-serif; 
	font-size: 4.0em;
	letter-spacing: -1px; 
	color: #ccc; 
}
h2 { 
	font-family: Sans-serif; 
	font-size: 3.0em;
	letter-spacing: -1px; 
	color: #ccc; 
}

Only a few things worth noting. The static width on the .post div controls the width of each block. The vertical-align property on the table row keeps each of the blocks aligned to the top of their table cells. This defaults to middle, so this is necessary.

The Results

With CSS and JavaScript both on (99% of users), we'll have a nicely executed horizontally scrolling site. With CSS and JavaScript both off (screen readers), the structure of the individual blog posts rule the page, assuming they are semantically marked up, the page will look great. The only quirk here is if JavaScript is on and CSS is off (RARE), the page looks a little bizarre.

View Demo Download Files

Other techniques for horizontal scrolling

Literally expanding the width of your page and using scrollbars to navigate it is only one way to achieve the horizontally scrolling effect. Javascript sliders are another route you could take, which simulate the effect. Flash would be another possibility. When it comes to web design, there is always many ways!

Examples of nicely designed horizontally scrolling sites

Comments

  1. I find sites that do this very “trendy,” but this type of site design probably isn’t the most practical for business use. I don’t get turned off by sites that employ this, but I feel safe in saying that most people would find it unnatural.

    That said, cool post!

  2. hi chris the evanescence site is the only one that will scroll horizontally using the mouse wheel why is that?

  3. I think horizontal sites are less popular because you get more area from scrolling in the smaller screen dimension and for monitors that is the height. Also, your example scrolls downward when you use the scroll wheel on the mouse. I’d make my site a horizontal site if I had less content… such as a portfolio page.

  4. @roger: Looks like the Evanescence site uses a bit of Javascript to get this done:

    http://www.evanescenceuk.co.uk/js/thw.js

    Pretty neat.

  5. Not this time, Chris.

    Possibly, it I (we) could adjust to it…

    Traditionally and in general, most of us are used to reading LTR or RTL. Having move completely in blocks of 500px to the right is distracting & breaks rhythm. Most of use can can tick our mouse down as we read as second nature.
    ‘Zeroing’ on a new page, just doesn’t work.

    Interesting concept, but there is good reason we try to avoid wider than screen development.

    Dave

  6. @chris yep just added it to your example and its now scrolling with the wheel!

    i think the general public would find it hard to adjust but for designer showcases/portfolio’s or show offs it’s just something different and open’s up more design possibilies.

    not everyone’s bag but different…

  7. My website was like this a while ago, but i had anchor links that went to parts of the page. I think it works for designer sites – or other sites that people expect to be “different” but not for the general internet public.

    Good post!

  8. Floats stack one after another by default.
    The reason why you can’t make them stack in this example is body element. It has overflow set to auto which means that anything sticking out will be trimmed visibly and the scrollbar will appear. However, floats can’t behave like this in space beyond boxes’ frame. You could try disabling overflow (visible), but then you have another side-effect: browser window width.

    I don’t recommend tables. You should play with display: table-cell and expression() for IE if you want such fancy effect.

  9. It’s a nice thing for designers but have you ever tried to print out something :0)

  10. Permalink to comment#

    please…

    Stop abusing javascript frameworks for such fixes.. I dont even understand why on earth u need javascript for this..

    Perhaps a slight blow to “useability”,

    U mean a BIG blow.. most mouses doesnt have a horizontal scroll wheel o.o

  11. Al
    Permalink to comment#

    not workibg for me at all in IE7,

    Al

  12. Interesting that IE 7 doesn’t work. IE 8 beta is working alright. I wonder if there are some quirks to how IE 7 needs that jQuery stuff formatted that I don’t know about. I know it’s not valid code (you could abstract it away to fix that), but I don’t really see what else is wrong with it.

  13. Al
    Permalink to comment#

    works in FF2 and FF3

    in IE7, the paragraphs are just displayed vertically

    anybody else experience this?

    Al

  14. Al
    Permalink to comment#

    downloaded the example files and does the same in IE7,
    in FF, paragraphs seem to centered vertically, not sure if that
    was the intent

    Al

  15. Permalink to comment#

    http://www.hotel-oxford.ro/

    I’ve stumbled on quite a few mootools sites that use this technique.

    What I particularly like about the hotel site, is with javascript disabled, it’s still a funcitonal site!

  16. Leroy
    Permalink to comment#

    Horizontal scrolling isn’t used in webpages often for the same reason text doesn’t span across a spread in publications: the long scrolls across a page will tire the eyes of readers much faster. Of course you can create interest by defying convention, but that should only be done if the context of your design lends itself to such. Usability doesn’t have to be uninspiring; it can lead to great designs that are not only practical but highly creative as well.

  17. anonymous
    Permalink to comment#

    There was no need for the horizontal layout to totally not work if Javascript is disabled , is there ?

  18. Permalink to comment#

    @anonymous – the point is that the page is USABLE with JS off. If you go to the site, you can see for yourself. It’s a matter of making the experience entertaining to the user, to keep their attention, and to make it a more “fun” experience.

  19. Michael
    Permalink to comment#

    http://www.tiffanymumford.com/fashion

    I used, whitespace:nowrap , specified a container height and set image class to display:inline.

    That worked for me.

  20. http://www.tiffanymumford.com/fashion

    I used, whitespace:nowrap , specified
    a container height and set image class
    to display:inline.

    That worked for me.

    Ah, that looks good! I think its great to use horizontal scroll for pictures like that. For some reason I feel more comfortable reading text and scrolling up and down.

    That list of examples has some really cool looking sites. Makes me want to try this.

  21. Permalink to comment#

    I’ve found this other very nice example of a horizontal scrolling site : http://deanoakley.com/

    It’s built in divs using the “dirty” technique of the fixed width mentioned above. You can’t use the wheel to scroll if you deactivate javascript, but moving the bar itself works.

    I generally like this kind of design when it’s used on original, content light, site like portfolio but I don’t see it used on a corporate or e-commerce site for the reason Leroy explained above.

  22. Permalink to comment#

    DON’T

    Horizontally scrolling websites are one of the 7 deadly sins of web design, along with using animated gifs, busy backgrounds and forcing the browser window to re-size.

    BAD BAD BAD

  23. anonymous
    Permalink to comment#

    how could you miss http://www.csszengarden.com/?cssfile=037/037.css

    :O :O

    haven’t you read the CSS zen garden book ?

  24. anonymous
    Permalink to comment#

    and the people who are complaining .. see the link I just gave.. it is extremely usable imho. additionally , I use middle click to scroll so I don’t find that annoying.

    For sites in which the main aim is information dissipation and NOT web applications, I can imagine this being really useful , esp. the WOW factor traction that it gives you. I am tired of the stupid rounded corners and bright colors on all site wanting to get on 2.0 bandwagon.

  25. Daniel
    Permalink to comment#

    Hi.. about evanescence site.. and others.. they use the script thw.js

    You can find more informations here: http://www.thehorizontalway.com/

    Bests

  26. I realize it doesn’t strictly qualify as the kind of “side-scrolling” site you’re discussing, but Jonathan Yuen’s website is the single best personal website I have ever seen. It definitely breaks convention. I think it’s impossible to navigate (explore?) without experiencing genuine delight.

    http://www.jonathanyuen.com/main.html

  27. @Jason: Wow, that is quite a pleasure to explore, thanks for that link!

  28. Permalink to comment#

    Hi Chris,

    I hate to correct you but screen readers do not switch off CSS or JavaScript by default.

    For historic reasons they also have little or no difficulty transversing table structures, as long as they make sense linearised.

    To a screen reader horizontal or vertical scrolling are conceptually irrelevant. It’s just a stream of linear data, with jump points (headings, table, tr, td etc).

  29. Permalink to comment#

    I tried to implement wordpress into a horizontal layout but my main problem was having a ‘next post’ link after every post on the home page which would then link to the next post on that very same home page.

    You can do it easily from individual post page to individual post page, but not post to post whilst remaining on the home page. Putting anchor links into the index.php template gets all screwy.

    I’m still holding out for a solution because I think horizontal sites can look and function great.

  30. It’s also possible to dynamically alter an external style sheet. Take a look at http://www.itskevandeursen.nl where I have a PageManager class (in PHP) from which I can get the number of pages that will show up in my site. I print the number of pages inside a javascript block in the header of my page. That piece of javascript constructs a call to a css file which is actually a php file with a text/css header. The width of the body element is set based on the number of pages and the width of the users screen width. It’s not quite perfect, but it works. A major downside is that, when javascript is turned off, the css file isn’t loaded :(.

    I’ve also used one of jQuery’s plugins (serialScroll) to slide from page to page because jumping to an elements id does not quite work as expected in all browsers.

  31. NO NO NO NO NO NO NO – this is an awful approach and I hope people do not copy it or even think about using it.

    Inserting tables using JS is just as bad as inserting it from the start, at the end of the day the page will contain a bloody table.

    Disappointed :<

  32. Permalink to comment#

    Tnx for this :)

  33. Gianni
    Permalink to comment#

    I think this would be tough for reading text, but for a photo gallery it could be used in a fun way. A friend of mine sent me this website, it’s her friend who is a photographer, and I’m working on a photography website and thought that would be good to use.

    http://www.francodeleo.com/

  34. rafote
    Permalink to comment#

    Doesn’t work on IE6. It pulls the divs down one after each other.

    Any solution?

  35. Daps
    Permalink to comment#

    Does anybody have a solution to fix IE6 and IE7?

    Please….

    • Permalink to comment#

      IE issue solution !

      The HTML from this JS comes clumsy, with some extra DIV tag between the TR to the TD set.
      I switch the code to something like this, and its all works fine for both browsers:

      $(function(){
      $("#page-wrap").wrapInner(document.createElement("tr"));
      $("#page-wrap").wrapInner(document.createElement("table"));
      $(".post").wrap("<td>");
      });

      Its essential to actual create the element before warping some content with it. Another IE oddity comes to an end….

  36. Matti
    Permalink to comment#

    I also have the IE6 problem.

  37. Permalink to comment#

    http://www.hotel-oxford.ro/ -

    I looked at this site, and there is no bottom scroll bar. Does anyone know how they created a horizontal web site without having scroll bars?

  38. uxepi
    Permalink to comment#

    ya folks ever heard of this simple little ditty -

    ….”for to scroll “horizontally”,
    press the ‘SHIFT’ key and scroll as you would…..
    ah….its amazing.

    i can scroll normally on my “mouse”, whilst holding the Shift key and voila.

  39. Hello Chris, it’s an interesting quest to make a natural website that scrolls horizontally, and you wrote a good article on it.
    However, it seems to me the most natural and correct way to achieve something like this, without using tables, would be by not setting the width of the body but only limit the height to 100% or less.
    Than by giving the “paragraph” tag a width of, for example 45em, and making sure it floats left and is displayed as a block, I’m sure it would all line up pretty well horizontally. The only thing you would need to worry about is not to create paragraphs any longer than 20 lines of text or so for example. But when does one create such large paragraphs anyway?

    Why didn’t you experiment with anything like that? Or am I misunderstanding what you are trying to accomplish?

    Best regards,
    David Bartenstein

  40. Phillip Penny
    Permalink to comment#

    Instead of using javascript to create tabular behaviour, can’t we just use the css commands

    display:table;

    or

    display:table-cell;

    instead?

  41. Niklas
    Permalink to comment#

    How about relative width?

    body {
    width: 500%;
    }

    sektion {
    width: 20%;
    }

    Works quite well for 5 sektions. At least in Chrome.

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".