Width of element with 'white-space: nowrap' doesn't adjust to child content
Asked Answered
P

3

24

I am trying to create a horizontally scrolling pane with (tiling) background image, using overflow-x: scroll & white-space: nowrap. The pane spans an arbitrary number of elements.

CSS:

.frame {
   overflow-x: scroll;
}

.pane {
   background-image: url(free-tile-floor-texture.jpg);
   background-repeat: repeat;
   white-space: nowrap;
}

.item {
   display: inline-block;
   width: 150px;
   height: 50px;
   background-color: grey;
}

HTML:

<div class="frame">
   <div class="pane">
      <div class="item"></div>
      <div class="item"></div>
      <div class="item"></div>
   </div>
</div>

fiddle demo

I want the background tile to automatically span the full width of the pane including all its item elements. Currently it only fills to the frame width. The culprit seems to be the pane width property - it doesn't adjust to the overall width of pane contents.

Ofc, it works by adjusting the width property manually, but I need it to adjust dynamically.

How do I get the pane's background image to fill the pane's full width? Is there another way to achieve same result?

Pani answered 7/3, 2014 at 20:39 Comment(0)
G
16

Add this line to .pane

display: inline-block;
Grope answered 8/3, 2014 at 14:32 Comment(1)
The answer would be much more helpful by adding a small explanation why that solves the problem. CSS is already enough guesswork...Thetic
P
12

Short answer :

block elements, like <div> take their parent's width by default (if no width is set), and will not expand further (even if the child content is overflowing). Which is not the case for inline elements, like <span>, which will take the child content's width instead.

So, by using inline-block you will benefit from both the child content's width & height and have what you want.

(Other solutions exist, for example : float: left;, position: absolute;, ...)


More explanations :

I was having the same issue, where I wanted to create a carrousel (or horizontally scrolling pane with tiling as asked by the OP) with padding at the end, so the last item would not be collapsed to the edge of the viewport.

So basically, you would have the carrousel element being scrollable (the frame), then a container for the tiles with the paddings (the pane) and finally the tiles (the items) :

body {
    margin: 20px;
}

.frame {
  overflow-x: scroll;
}

.pane {
  background-color: grey;
  padding: 20px;
  white-space: nowrap
}

.item {
  background-color: red;
  display: inline-block;
  width: 100px;
  height: 100px;
  margin-right: 20px;
}

.item:last-child {
  margin-right: 0;
}
<div class="frame">
  <div class="pane">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
</div>

As you can see, the padding is working at the beginning but not at the end, because the pane's width does not expand beyond the parent width (the frame's width in this case).

Adding display: inline-block; on the pane fixes the problem :

body {
    margin: 20px;
}

.frame {
  overflow-x: scroll;
}

.pane {
  background-color: grey;
  display: inline-block;
  padding: 20px;
  white-space: nowrap
}

.item {
  background-color: red;
  display: inline-block;
  width: 100px;
  height: 100px;
  margin-right: 20px;
}

.item:last-child {
  margin-right: 0;
}
<div class="frame">
  <div class="pane">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
</div>

Modern solution (without white-space: nowrap;) :

Diverging a bit from the OP's question which was about the white-space: nowrap; rule, if you are searching for a more modern solution to create a carousel, you could achieve this using flex rules, as items in a flex container will not wrap by default, and it will also make the CSS a bit cleaner :

body {
    margin: 20px;
}

.frame {
  overflow-x: scroll;
}

.pane {
  background-color: grey;
  display: inline-flex;
  padding: 20px;
}

.item {
  background-color: red;
  width: 100px;
  height: 100px;
  margin-right: 20px;
}

.item:last-child {
  margin-right: 0;
}
<div class="frame">
  <div class="pane">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
</div>
Pliam answered 24/4, 2020 at 17:57 Comment(0)
I
0

You can define background-image in frame which is your whole panel

http://jsfiddle.net/erenyener/9u29k/6/

 .frame {
     overflow-x: scroll;
     background-image: url(http://store.got3d.com/products/30-tile-floor-textures/thumbnails/free-tile-floor-texture.jpg);
     background-repeat: repeat;
}
Identification answered 7/3, 2014 at 21:6 Comment(1)
But then the background image follows the frame, not the panel. The items slide over the background image instead og resting on it. So not really a solution to the problem.Pani

© 2022 - 2024 — McMap. All rights reserved.