23

I'm trying to create a horizontally scrolling list. I'm going to replace this with a fancy version when Javascript is enabled, but I want the markup and css to look and work fine without Javascript on reasonably modern browsers (any suggestions that uses Javascript in any way is off).

My current markup/css works, but here's what I don't like about it:

  • The current markup specify a very wide ul (i.e. 10000px) and a container that scrolls on this. Is there a way to avoid this and instead have the width expands based on its content (i.e. the blue background shouldn't be there)?
  • There are two extraneous divs (those with id #extra1, #extra2) that is just for styling purpose. Is there a way to eliminate this extra div?
  • If there is not enough image to fill the page width, the scrollbar should collapse, but currently it does not because I have a very wide ul which cannot collapse.
  • The <a> tag are separated by the horizontal list, I preferably want to keep them together. Is there a way to have them close together and cleanly separate them in CSS?

Aside, do you know of any tutorials that discussed this sort of thing? I've seen several tutorials that demonstrated having the whole page to scroll, and I took some ideas from those, but I can't find any that demonstrated scrolling ul/ol element.

Extra info that might help:

  • The width of the page is static (i.e. it is not fluid/elastic layout).
  • The images in the page is dynamically generated from PHP, and the number of images can change.
  • The width of the thumbnails are well-defined.

Stripped down live example: http://dl.dropbox.com/u/17261360/horiz.html

Lie Ryan
  • 62,238
  • 13
  • 100
  • 144

1 Answers1

35

Update (2018): The original solution based on display: inline is over 7 years old now. In today's world, I would recommend the flexbox approach, because it gives you full control over the gaps that appear between the images.


Using flexbox

Check browser compatibility first (you're probably fine), and add prefixes as needed.

ul.images {
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: row;
  width: 900px;
  overflow-x: auto;
}

ul.images li {
  flex: 0 0 auto;
  width: 150px;
  height: 150px;
}
<ul class="images">
  <!-- Inline styles added for demonstration purposes only. -->
  <li style="background-color: #dff">...</li>
  <li style="background-color: #fdf">...</li>
  <li style="background-color: #ffd">...</li>
</ul>

Using display: inline

This works for me, tested in Firefox 4 beta 10, would be advisable to test it in IE as well:

ul.images {
  margin: 0;
  padding: 0;
  white-space: nowrap;
  width: 900px;
  overflow-x: auto;
}

ul.images li {
  display: inline;
}
<ul class="images">
  <!-- Inline styles added for demonstration purposes only. -->
  <li style="background-color: #dff">...</li>
  <li style="background-color: #fdf">...</li>
  <li style="background-color: #ffd">...</li>
</ul>

The trick in the CSS is to set the lis to display: inline, so they are treated as characters and placed next to each other, and set white-space:nowrap on the ul so that no line breaking is done. You cannot specify a size on inline elements, but they will be stretched to fit the img elements inside them. The scrolling is then simply overflow-x: auto on the parent ul element.

Adding prev/next buttons could be done with position:absolute, or with float:left, or whatever other method you fancy.


Using display: inline-block

Similar to the previous approach, but allowing us to set a size on each individual image block:

ul.images {
  margin: 0;
  padding: 0;
  white-space: nowrap;
  width: 900px;
  overflow-x: auto;
}

ul.images li {
  display: inline-block;
  width: 150px;
  height: 150px;
}
<ul class="images">
  <!-- Inline styles added for demonstration purposes only. -->
  <li style="background-color: #dff">...</li>
  <li style="background-color: #fdf">...</li>
  <li style="background-color: #ffd">...</li>
</ul>
Thomas
  • 174,939
  • 50
  • 355
  • 478
  • 1
    This and a similar technique with inline-block works, but it creates a small gap that can only be cleared by running all the `
  • ` in a single line (or doing worse hacks) since in inline/inline-block the whitespaces are significant; which totally ruins the readability of the HTML (I don't want to compromise semantic/readability for a fallback mechanism).
  • – Lie Ryan Mar 06 '11 at 02:57
  • Good point, sorry. Here are some ways to get around that, none very pretty: http://stackoverflow.com/questions/2628050/ignore-whitespace-in-html Also, I think (but look into this yourself) that `inline-block` is not well supported on IE. – Thomas Mar 06 '11 at 09:52
  • 1
    Thank you!! OMG I'm so happy now!! I have a question! How do you select an image in the list and display them in full screen? (with animation and zooming effects) and have the feature to close them as well? This is probably the last thing on my list before I launch my website :) – PatrickGamboa Jan 14 '13 at 01:40
  • Can you please explain, what's the point of setting `width: 900px;` in `ul.images`. My container is fluid. Will it work If I set to `100%`..? – shashwat Mar 10 '14 at 06:59
  • 1
    I think so. Why don't you just try it? – Thomas Mar 10 '14 at 15:59
  • @PatrickGamboa your comment made my day. This thread went from wow that was helpful and did a small specific task to lets turn this little solution into a full blown plugin – Samuel Thompson Feb 13 '17 at 23:24
  • Live example is dead 404. You you mind post a SO snippet? – a--m May 06 '18 at 10:12
  • 1
    @a--m Thanks, my web host folded on me. Made snippets, and also made a better answer for today's age. – Thomas May 12 '18 at 12:53