Skip to content Skip to sidebar Skip to footer

How To Get A Flexbox Not To Use More Space Than The Container?

I am building a modal, and want it to be centred in my page and grow organically but only until it reaches a certain width and height. I center this modal (.modal) with flexbox, an

Solution 1:

A simple fix is to make the .modal a flex container with column direction.

/* Centers the child */
.modal-container {
  display: flex;
  align-items: center;
  justify-content: center;
}
  
/* The box in the middle, that should grow
   organically, but be restricted as well */
.modal, .modal-content--merged-with-modal {
  width: 30rem;
  max-width: calc(50vw - 3rem);
  max-height: calc(100vh - 3rem);

  /* Irrelevant styling */
  background: rgba(255, 255, 255, 0.6);
  border-radius: 3px;
  line-height: 1.5rem;
}
  
  
.modal-content {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
  
.modal-content__body {
  flex: 1;
  min-height: 0;
  overflow-y: scroll;

  /* Irrelevant styling */
  padding: 0.75rem;
  background: rgba(0, 0, 255, 0.1);
}
  
  
.modal-content__footer {
  /* Irrelevant styling */
  border-top: 1px solid silver;
  background: rgba(0, 255, 0, 0.1);
  padding: 0.75rem;
}
.modal {
  display:flex;
  flex-direction:column;
}
  
  
/* Irrelevant styling to present the problem */
html {
  font-family: arial, sans-serif;
  font-size: 16px;
}
main {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  
  display: flex;
}
section {
  flex: 1;
  background: rgba(255, 0, 0, 0.1);
}
<main>

  <section class="modal-container">
    <div class="modal-content modal-content--merged-with-modal">
      <div class="modal-content__body">
        <code>BODY // </code> srollable<br>
        <br>
        Container resizes as expected when<br>
        the container height is reduced.<br>
        <br>
        In this case, the modal is the same<br>
        element, as the flexbox handling<br>
        the body and the footer.<br>
        .<br>
        .<br>
        .<br>
        .<br>
        .<br>
        .<br>
      </div>
      <div class="modal-content__footer">
        <code>FOOTER // </code> Works
      </div>
    </div>
  </section>

  <section class="modal-container">
    <div class="modal">

      <div class="modal-content">
        <div class="modal-content__body">
          <code>BODY // </code>simply grows<br>
          <br>
          Container overflows when<br>
          the container height is reduced.<br>
          <br>
          In this case, the modal <strong>contains</strong><br>
          the flexbox, that handles the<br>
          body and the footer.<br>
          .<br>
          .<br>
          .<br>
          .<br>
          .<br>
          .<br>
        </div>
        <div class="modal-content__footer">
          <code>FOOTER // </code> Doesn't work
        </div>
      </div>

    </div>
  </section>

</main>

Why?

Initially the .modal was a block element with a max-height set and the default overflow behavior (when there is an overflow) is visible and you are facing an overflow issue.

By making the .modal a flex container, you introduce the shrink effect as by default the flex item will have flex-shrink:1 so its height won't go beyond the height of the flex container (it will shrink to fit) and you will have the need result.

You may set flex-shrink:0 to .modal-content and you will see the same overflow issue as if there is no display:flex.


Solution 2:

In order for the overflow property to work, it needs a fixed length limitation.

From MDN:

In order for overflow to have an effect, the block-level container must have either a set height (height or max-height) or white-space set to nowrap.

In your code, there is no height limitation on .modal-content__body (where the overflow is set):

.modal-content__body {
    flex: 1;
    min-height: 0;
    overflow-y: scroll;
}

Nor is there a height limitation on the parent:

.modal-content {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

flex-basis: 0 – the relevant component of flex: 1 in .modal-content__body – isn't enough to trigger the overflow condition. But look what happens if you switch to flex-basis: 100px

/* Centers the child */
.modal-container {
  display: flex;
  align-items: center;
  justify-content: center;
}
  
/* The box in the middle, that should grow
   organically, but be restricted as well */
.modal, .modal-content--merged-with-modal {
  width: 30rem;
  max-width: calc(50vw - 3rem);
  max-height: calc(100vh - 3rem);

  /* Irrelevant styling */
  background: rgba(255, 255, 255, 0.6);
  border-radius: 3px;
  line-height: 1.5rem;
}
  
  
.modal-content {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
  
.modal-content__body {
  flex: 1 0 100px; /* new for demo 1 */
  min-height: 0;
  overflow-y: scroll;

  /* Irrelevant styling */
  padding: 0.75rem;
  background: rgba(0, 0, 255, 0.1);
}
  
  
.modal-content__footer {
  /* Irrelevant styling */
  border-top: 1px solid silver;
  background: rgba(0, 255, 0, 0.1);
  padding: 0.75rem;
}
  
  
  
/* Irrelevant styling to present the problem */
html {
  font-family: arial, sans-serif;
  font-size: 16px;
}
main {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  
  display: flex;
}
section {
  flex: 1;
  background: rgba(255, 0, 0, 0.1);
}
<main>
  <section class="modal-container">
    <div class="modal">
      <div class="modal-content">
        <div class="modal-content__body">
          <code>BODY // </code>simply grows<br>
          <br> Container overflows when<br> the container height is reduced.<br>
          <br> In this case, the modal <strong>contains</strong><br> the flexbox, that handles the<br> body and the footer.<br> .
          <br> .
          <br> .
          <br> .
          <br> .
          <br> .
          <br>
        </div>
        <div class="modal-content__footer">
          <code>FOOTER // </code> Doesn't work
        </div>
      </div>
    </div>
  </section>
</main>

The scrolling works. A height limitation made the difference.

Here's a potential solution:

Since the height of .modal (the parent) and modal-content (the child) are the same, move the dimensions from the parent to the child. This brings the height limitation close enough to the content items to trigger the overflow.

Instead of this:

.modal {
    width: 30rem;
    max-width: calc(50vw - 3rem);
    max-height: calc(100vh - 3rem);
}

.modal-content {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

Try this:

.modal {    }

.modal-content {
    display: flex;
    flex-direction: column;
    min-height: 0;
    width: 30em;
    max-width: calc(50vw - 3rem);
    max-height: calc(100vh - 3rem);
}

/* Centers the child */
.modal-container {
  display: flex;
  align-items: center;
  justify-content: center;
}
  
/* The box in the middle, that should grow
   organically, but be restricted as well */
.modal, .modal-content--merged-with-modal {


  /* Irrelevant styling */
  background: rgba(255, 255, 255, 0.6);
  border-radius: 3px;
  line-height: 1.5rem;
}
  
  
.modal-content {
  display: flex;
  flex-direction: column;
  min-height: 0;   
     width: 30rem;
     max-width: calc(50vw - 3rem);
     max-height: calc(100vh - 3rem);
}
  
.modal-content__body {
  flex: 1;
  min-height: 0;
  overflow-y: scroll;

  /* Irrelevant styling */
  padding: 0.75rem;
  background: rgba(0, 0, 255, 0.1);
}
  
  
.modal-content__footer {
  /* Irrelevant styling */
  border-top: 1px solid silver;
  background: rgba(0, 255, 0, 0.1);
  padding: 0.75rem;
}
  
  
  
/* Irrelevant styling to present the problem */
html {
  font-family: arial, sans-serif;
  font-size: 16px;
}
main {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  
  display: flex;
}
section {
  flex: 1;
  background: rgba(255, 0, 0, 0.1);
}
<main>

  <section class="modal-container">
    <div class="modal">

      <div class="modal-content">
        <div class="modal-content__body">
          <code>BODY // </code>simply grows<br>
          <br>
          Container overflows when<br>
          the container height is reduced.<br>
          <br>
          In this case, the modal <strong>contains</strong><br>
          the flexbox, that handles the<br>
          body and the footer.<br>
          .<br>
          .<br>
          .<br>
          .<br>
          .<br>
          .<br>
        </div>
        <div class="modal-content__footer">
          <code>FOOTER // </code> Doesn't work
        </div>
      </div>

    </div>
  </section>

</main>

Post a Comment for "How To Get A Flexbox Not To Use More Space Than The Container?"