I have a behavior that puzzles me. The code below is the result of debugging a larger app. I know I can simplify it and make it work. However, I would like to understand and learn.
There are two rectangles (height: 100px and height: 400px) stacked on top of each other in a column flex box. When the window gets smaller than 500px, the browser will add a scrollbar. Ok. But if it gets smaller than 400px, the blue box shows a scrollbar.
I would have expected either the body-scrollbar or the blue-box-scrollbar, but not both. Can anyone explain
HTML
*,
::before,
::after {
box-sizing: inherit;
}
html,
body {
margin: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
/* overflow: visible; */
}
.full-size {
width: 100%;
height: 100%;
}
.container {
display: flex;
flex-direction: column;
}
.content {
flex: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Hi</title>
<base href="/" />
<link rel="stylesheet"
href="style.css" />
<meta name="viewport"
content="width=device-width, initial-scale=1" />
</head>
<body>
<div class="full-size container">
<div style="width:300px; height: 100px; background-color: green; flex-shrink: 0;">Upper content</div>
<div class="full-size content">
<div class="full-size"
style="overflow: auto; background-color: blue;">
<div style="width:300px; height: 400px; background-color: yellow;">Lower content</div>
</div>
</div>
</div>
</body>
</html>
It's related to the use of the cascade height: 100%
until the content
element. Inside your container, you have an element with a height equal to 100px
and another with a height equal to 100%
. This will logically result in an overflow but the shrink effect will strike and the second element will get smaller than 100%
.
But on small screen the yellow box will trigger another effect and will prevent the shrinking due to the default min-height
configuration (Why don't flex items shrink past content size?) and will block your element at height: 100%
which will trigger the body-scrollbar and the yellow box inside is bigger than height: 100%
which will trigger the blue-scrollbar.
To avoid this, add min-height: 0
to content
html,
body {
margin: 0;
height: 100%;
}
.full-size {
height: 100%;
}
.container {
display: flex;
flex-direction: column;
}
.content {
flex: 1;
min-height: 0;
}
<div class="full-size container">
<div style="width:300px; height: 100px; background-color: green; flex-shrink: 0;">Upper content</div>
<div class="full-size content">
<div class="full-size" style="overflow: auto; background-color: blue;">
<div style="width:300px; height: 400px; background-color: yellow;">Lower content</div>
</div>
</div>
</div>
Now the blue box will always shrink and you will never get the body-scrollbar