Home > Mobile >  Is there a way to get a flexbox to fill all available height?
Is there a way to get a flexbox to fill all available height?

Time:08-17

I'm working in a browser like environment and I need to make a container dynamically fill all available space.

Here is what I have so far:

/* user agent stylesheet */
html {
    display: flex;
    flex-direction: column;
    font-size: 10px;
}
body {
    display: flex;
    flex-direction: column;
    padding: 0px;
    font-size: var(--uxp-body-font-size);
    color: #505050;
}

/* my stylesheet */
body {
   width: 100%;
   height: 100%;
}

.header {
  height: 100px;
  border: 1px solid gray;
}

.content {
   background-color: lightblue;
   height: 100%;
}
<html>
   <body>
      <div >header</div>
      <div >content</div>
   </body>
</html>

If I set the html tag height to 100% then it does sortof work but I don't know if I can set that because it's a controlled environment (edit: I can set the html height to 100% and it sort of working).

Comment by @tacoshy if he doesn't put this in a comment:

"Set body to 100vh"

That causes a few issues. First, you have an instant overflow because you didn't reset the default body margin. Second, you get an overflow issue as you used a fixed height instead of a min-height. Third you miss an actual explanation of why the issue is caused. Last but not least you miss a property to let the other elements fill the remaining space (flex-grow);

CodePudding user response:

The main issue is caused because the default height of the body being set to fit-content. As such it will calculate its own height depending on the content. The next issue is, that height: 100% means 100% of the parent's height. By default, the <html>-tag is set to fit-content as well. So the height is undefined and 100% of undefined is also undefined. Therefore the body's height is undefined as well even though you set it to 100%.

The Flexbox is applied to the wrong container. You have to apply it to the direct parent of the element you want to let fill the remaining space. Logically the parent needs a height larger than the child as otherwise, the child can't grow to the parent's height (that we covered above). To let the child element grow to fill the remaining height you can use flex-grow.

The technique to solve the issue is quite simple:

  1. You need to apply the flexbox container to the body as the body contains the visual content: body { display: flex; flex-direction: column; }
  2. to fill at least the viewport you apply a min-height of 100vh. If you set a fixed height then you can run into overflow issues and need to add an overflow rule: body { min-height: 100vh; }
  3. This causes an overflow issue by default as most browsers have a default body margin of 8px. So you overflow by 16px. You can't sue calc(100vh - 16px) as not all browsers have the same body margin. Easiest solution is to reset the body margin: body { margin: 0; }
  4. Since you use flexbox you can use flex-grow to let an element occupy the remaining space: main { flex-grow: 1; }

Note that I replaced the div for header and content with the correct semantic tags. This is necessary for screen readers and as such accessibility. Without semantic tags, a screen reader won't know what those elements are and not be able to tell a handicapped user what those elements are for.

/* my stylesheet */
body {
  width: 100%;
  min-height: 100vh;
  margin: 0;
  display: flex;
  flex-direction: column;
}

header {
  height: 100px;
  border: 1px solid gray;
}

main {
  background-color: lightblue;
  flex-grow: 1;
}
<html>

<body>
  <header>header</header>
  <main>content</main>
</body>

</html>

CodePudding user response:

I'm posting this as a partially working example to not edit the original example.

The part that works is the html body is now fully filling the available space. The part that is not working is in my environment the items are spaced out.

/* user agent stylesheet */
html {
    display: flex;
    flex-direction: column;
    font-size: 10px;
    border: 2px solid blue;
    height: 100%;
}
body {
    display: flex;
    flex-direction: column;
    padding: 0px;
    font-size: var(--uxp-body-font-size);
    color: #505050;
}

/* my stylesheet */
body {
margin: 0;
   width: 100%;
   height: 100%;
}

.header {
  height: 100px;
  border: 1px solid gray;
  padding: 0px;
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
  height: 33px;
  display: flex;
  flex-direction: row;
  align-items: center;
}

.content {
  background-color: lightblue;
  height: 100%;
  font-size: 11px;
  width: 100%;
  display: flex;
  flex-direction: column;
}
<html>
   <body>
      <div >header</div>
      <div >content</div>
   </body>
</html>

  • Related