19

I've seen this asked a few times on SO, and the same answers are given which do not work on my end in Chrome or Firefox.

I want to make a set of left-floated divs run off, horizontally a parent div with a horizontal scroll bar.

I'm able to demonstrate what I want to do with this crappy inline css here: http://jsfiddle.net/ajkochanowicz/tSpLx/3/

However, from the answers given on SO*, this should work but does not on my end. http://jsfiddle.net/ajkochanowicz/tSpLx/2/

Is there a way to do this without defining absolute positioning for each item?

*e.g. Prevent floated divs from wrapping to next line

Community
  • 1
  • 1
Adam Grant
  • 12,477
  • 10
  • 58
  • 65

3 Answers3

16

This should be all you need.

    .float-wrap {
      /* 816 = <number of floats> * (<float width> + 2 * <float border width>) */
      width: 816px;
      border: 1px solid;
      /* causes .float-wrap's height to match its child divs */
      overflow: auto;
    }
    .left-floater {
      width: 100px;
      height: 100px;
      border: 1px solid;
      float: left;
    }
    .outer {
      overflow-x: scroll;
    }
<div class="outer">
  <div class="float-wrap">
    <div class="left-floater">
      One
    </div>
    <div class="left-floater">
      Two
    </div>
    <div class="left-floater">
      Three
    </div>
    <div class="left-floater">
      I should be to the <s>left</s> right of "Three"
    </div>
    <div class="left-floater">
      I float.
    </div>
    <div class="left-floater">
      I float.
    </div>
    <div class="left-floater">
      I float.
    </div>
    <div class="left-floater">
      I float.
    </div>
  </div>
</div>

.float-wrap keeps space open for the divs. Because it will always maintain at least enough space to keep them side-by-side, they'll never need to wrap. .outer provides a scroll bar, and sizes to the width of the window.

AaronSieb
  • 8,106
  • 8
  • 39
  • 58
  • 6
    Excellent work, Aaron. Here is a link to the JSFiddle for readers: http://jsfiddle.net/ajkochanowicz/wkqQU/ – Adam Grant Mar 14 '12 at 13:48
  • 1
    Is it possible to have the `width:` attribute in the `.float-wrap` selector automatically computed? Or must it be hard-coded? – feralin Jun 30 '14 at 18:06
  • @feralin In standard CSS, it has to be hard coded. If you use LESS or Sass, you can use variables to get something like `width: @floatsPerRow * (@floatWidth + 2 * @floatBorderWidth)` – AaronSieb Jun 30 '14 at 18:35
  • If the number of floats in the row can change over time, then is javascript the way to go to compute the required width? – feralin Jun 30 '14 at 18:39
  • @feralin Probably. It depends on your exact requirements. For example, if you're just switching between portrait and landscape mode, you would probably just use classes to control the number of elements per row. – AaronSieb Jun 30 '14 at 18:48
  • 1
    Hey folks this is perfect, but my number of elements depends on how many items the user will add, so I can't set a specific width to the .float-wrap element. Any ideas? Thanks. – Leandro Faria Dec 11 '15 at 21:33
  • @LeandroFaria Set the width on the element directly when you find out the number of elements. Or use a different structure entirely (e.g. display: table; and display: table-cell; or display: inline-block; and white-space: nowrap;). It depends on exactly what you're going for. – AaronSieb Dec 11 '15 at 21:49
1

Use a second wrapper around the elements with absolute positioning. Then you can just float the individual items.

<style type="text/css">
    #outter {
        position: relative;
        width: 500px;
        height: 200px;
        overflow: scroll;
    }
    #inner {
        position: absolute;
        top: 0;
        left: 0;
        width: 1000px;
        height: 200px;
    }
    #inner .item {
        float: left;
        display: inline;
    }    
</style>

<div id="outter">
    <div id="inner">
        <div class="item">Item #1</div>
        <div class="item">Item #2</div>
        <div class="item">Item #3</div>
    </div>
</div>

You will have to adjust the width of #inner based on the number of items you'll have inside it. This can be done on load if you know the number of items or with javascript after the page loads.

Kory Sharp
  • 490
  • 3
  • 11
  • Sorry. Just fixed the CSS. #inner .left should have been #inner .item. – Kory Sharp Mar 12 '12 at 17:59
  • Thanks, @Kory. I cleaned this up and added a width and height value to the floated divs, but it still does the same thing: http://jsfiddle.net/ajkochanowicz/7Feaj/ – Adam Grant Mar 12 '12 at 18:03
  • Just made a revision, it appears if you make another child div and give that the width/height values (but not "float:left") it then works: http://jsfiddle.net/ajkochanowicz/7Feaj/1/ – Adam Grant Mar 12 '12 at 18:06
  • Hmm, but now you have to specify a px value for the width of .outer. Making it 100% breaks it. – Adam Grant Mar 12 '12 at 18:12
  • Are you wanting this to be a fluid width container? Either way, you'll need to dynamically update the width of the #inner container to accommodate the exact size of it's children. That make sense? – Kory Sharp Mar 12 '12 at 18:35
  • Hey there. I understand. I think @Aaron just posted a similar solution. – Adam Grant Mar 14 '12 at 13:49
  • `float: left; display: inline;` makes no sense, cause `float:left` forces `display: block`. – Paul Kozlovitch Mar 28 '14 at 13:38
0

This question has been asked quite a while ago, but still shows up high in search engine results. Therefore I feel it is still useful to add a new answer. It is now also possible to achieve the desired outcome without setting a fixed width to the parent by using flexbox (which now has decent browser support).

Using the class names from the example (which are a bit off now since the elements aren't actually floated anymore):

.float-wrap {
  display: flex;
  flex-wrap: nowrap;
}

.left-floater {
  flex: 0 0 100px;
}

.outer {
  overflow-x: auto
}
BraMKJ
  • 183
  • 1
  • 11