5

I have 3 nested divs:

<div class="outer">
  <div class="inner"><div class="item"></div></div>
</div>

The .inner div is position absolute and they each have 1px border:

.outer{
  width:50%;
  height:100px;
  border: 1px solid red;
  position:relative;
  overflow-x:hidden;
  box-sizing:border-box;
}
.inner{
  border:1px solid blue;
  height:100%;
  position: absolute;
  box-sizing: border-box;
}
.item{
  width:100px;
  height:100%;
  background-color:yellow;
  display: inline-block;
  border:1px solid green;
  box-sizing:border-box;
}

This arrangement results in a scrollbar on the .outer div.

Here's a codepen

Why is this and what do I need to change to stop it happening?

If the width of the border of the .inner div is increased to 3px then the scrollbar goes away. Again, why is this happening?

Will Jenkins
  • 9,507
  • 1
  • 27
  • 46

4 Answers4

4

This is happening because your .item element is set to display as an inline-block. This means it's affected by things like line-height and vertical-align.

The default vertical alignment on inline-block elements is baseline. This means they're set to appear at the base line of any text that may be entered alongside it. I'm not 100% sure but I think there may be an issue here where box-sizing is ignored when making this calculation, and the base line ends up being 2 pixels below where it should be (due to the cumulative 2 pixels of border applied to the top and bottom of the element).

If you want that element to remain being displayed this way, a quick fix is to set its vertical-align to top:

.item {
    ...
    vertical-align: top;
}

Codepen demo.

James Donnelly
  • 126,410
  • 34
  • 208
  • 218
  • @WillJenkins I'm not sure what you mean. If you want the `.item` element to appear centred, you can give your `.inner` element a `width` of `100%` and a `text-align` set to `center`. http://codepen.io/anon/pen/XmRQpL – James Donnelly Oct 07 '15 at 14:43
  • Removing `display: inline-block`, setting either `vertical-align: top/middle/bottom` or `position: absolute` on item all work, but why does the inline-block child of an absolutely positioned element take up space in the parent anyway?? – webketje Oct 07 '15 at 14:44
  • @Tyblitz I've updated my answer with a theory as to why I think this happens. – James Donnelly Oct 07 '15 at 14:46
  • @JamesDonnelly I mean vertically centered. Now, by doing this the scroll bar goes away: http://codepen.io/anon/pen/MamRpL – Will Jenkins Oct 07 '15 at 14:48
  • @WillJenkins the `middle` vertical-alignment here will only work if it has something to align itself against. If we remove `.item1` from that the vertical alignment stops working. You could however apply a `line-height` of `98px` on your `.inner` element to achieve this. – James Donnelly Oct 07 '15 at 14:50
  • @JamesDonnelly That sounds logical to me, and I've also encountered this 2px-ish change before.. +1 – webketje Oct 07 '15 at 14:51
  • Hah, ok @JamesDonnelly - new challenge is to add the line-height and then make a vertically-aligned single item fit without a gap at the top or a scroll bar http://codepen.io/anon/pen/PPmgOE – Will Jenkins Oct 07 '15 at 14:57
  • maybe I should write a new question... ? – Will Jenkins Oct 07 '15 at 14:57
  • New question here: http://stackoverflow.com/questions/32996119/css-vertical-alignment-with-nested-divs – Will Jenkins Oct 07 '15 at 15:18
2

The weirdest thing is that if you remove overflow-x:hidden; the scrollbar goes away. The reason is that the default behavior of overflow is visible thus if you don't mess with it, the results will be no scrollbars, but setting overflow-x to some value, sets overflow-y to auto instead of the default value which is visible and as a result, the scrollbar appears.

If you set overflow to auto the scrollbar will also appear.

On the other hand, .item is set to inline-block so it has line-height which produces the space on the bottom. Setting .inner to line-height:0 will make the space disappear, and if you increase it it will increase as well.

On the other ( third hand ) you can just constrict the space that the elements inside .inner take by setting .inner to overflow:hidden

xpy
  • 5,481
  • 3
  • 29
  • 48
0

Why you use inline-block in the inner item? If you change to block your scroll disappears:

.item{
  width:100px;
  height:100%;
  background-color:yellow;
  display: block;
  border:1px solid green;
  box-sizing:border-box;
}
Marcos Pérez Gude
  • 21,869
  • 4
  • 38
  • 69
-1

It's because your height is 100% then you're adding 1px of border on each div. Working demo: http://codepen.io/anon/pen/VvbNXp

So your .inner and .item classes need the height changed to:

height:calc(100% - 1px);
deebs
  • 1,390
  • 10
  • 23
  • Nope, box-sizing:border-box takes the border width in to account. – Will Jenkins Oct 07 '15 at 15:02
  • I believe the box-sizing only takes into account the padding and margin, right? Because this solution takes away the scrollbar – deebs Oct 07 '15 at 15:04
  • 1
    Nope. It's padding and border but not margin. See here: https://developer.mozilla.org/en/docs/Web/CSS/box-sizing – Will Jenkins Oct 07 '15 at 15:06
  • Okay. I think it's the whitespace on your inline-block element. https://css-tricks.com/fighting-the-space-between-inline-block-elements/ Remove that and you're good. And vote my answer back up while you're at it ;) – deebs Oct 07 '15 at 15:12
  • Oh. sorry. But if you do remove inline-block from the .item class it's fixed, or if you add margin: -1px. Plus there are issues of whitespace with inline-block elements, as noted in that article – deebs Oct 07 '15 at 15:15