Why 4 divs with `width: 25vw;` cannot align together?

529 Views Asked by At

There are 4 divs, each of them has width: 25vw; and height: 100vh;. I thought they could horizontally align in a line and so that tile the whole browser viewport. But they didn't. A line break was between the 3rd and the 4th div, and the scroll bar also appeared.

Then I inspected them, and DevTools told me the computed width of each was 480px, which exactly equaled to 25vw(My screen is 1920 * 1080).

Finally, I gave the body overflow: hidden. The scroll bar disappeared, and the viewport was filled with 4 divs. Everything was fine, except I got totally confused. Why? 100vw & 100vh shouldn't make any overflow.

Here is my code:

body {
  padding: 0;
  margin: 0;
  font-size: 0;
}

div {
  display: inline-block;
  width: 25vw;
  height: 100vh;
  background-color: lightblue;
}
<body>
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
</body>

or

body {
  padding: 0;
  margin: 0;
}

div {
  float: left;
  width: 25vw;
  height: 100vh;
  background-color: lightblue;
}
<body>
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
</body>

P.S. I have tried both display: inline-block; and float: left; on Chrome & Firefox & Chromium Edge, the results are the same.

P.P.S. After saw the comments & answers, I tried to give the body width: 100vw;, and everything got nice. It seems that it is 25vw > the width of the body that causes the overflow. But still, I cannot understand this behavior. As far as I am concerned, the body is a block, and its width will be extended until equal to its content width if there is enough space. Since 100vw doesn't exceed the viewport, there is no overflow. The only reasonable explanation here is that the body has its own width by default, which value is less than 100vw, so the line break and scroll bar appears. The question is, is it true? Where is the default value from? I inspected it and found the value is 1519.2px. Why so strange?

New code:

body {
  padding: 0;
  margin: 0;
  width: 100vw;
}

div {
  float: left;
  width: 25vw;
  height: 100vh;
  background-color: lightblue;
}
<body>
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
</body>
2

There are 2 best solutions below

1
On

The reason is because vw doesn't take into account the scrollbar. So if you have a div at width: 100vw and there is a visible scrollbar, that div will overflow the screen slightly.

The viewport-percentage lengths are relative to the size of the initial containing block. When the height or width of the initial containing block is changed, they are scaled accordingly. However, any scrollbars are assumed not to exist.

csswg

You might have better luck setting the div to width: 25% which would factor in the scrollbars.

1
On

For horizontal aligning it's best you use flexbox.

body{
 display: flex;
 width: 100vw;
}
body div{
 flex: 0 0 25%;
 max-width: 25%;
}

And be sure all margin, padding and border space are removed from the body