Tips for ensuring a flexbox stays within the bounds of its container and doesn't exceed the available space

I am in the process of developing a modal that needs to be centered on my page and expand organically, but only up to a specific width and height limit.

Using flexbox, I have successfully centered this modal (.modal) on the page.

Within the modal, there is another flexbox (.modal-content) containing a body (.modal-content__body) and a footer (.modal-content__footer). I aim for the body to expand until the entire .modal reaches the defined max-height, at which point the .modal-content__body should start scrolling vertically.

The HTML structure is as follows:

.modal-container // Takes up the full screen
  .modal // Centered box with max-width and max-height limits
    .modal-content // Content inside the modal
      .modal-content__body // Content that may grow dynamically
      .modal-content__footer

I am encountering an issue where the content within .modal-content overflows. It does not adhere to the height restrictions set by its parent element (.modal) and continues to expand to accommodate more content.

If I merge the .modal and .modal-content without the additional div layer, everything functions as intended. However, due to constraints imposed by using a framework (Angular), altering the structure of HTML elements is not feasible.

(NOTE: Applying

max-height: -webkit-fill-available;
to .modal-content resolves the issue, but this property's compatibility issues prevent its use)

Below is a code snippet illustrating the problem:

/* Centers the child */
.modal-container {
  display: flex;
  align-items: center;
  justify-content: center;
}


/* The central box that should naturally grow 
   whilst remaining constrained */
.modal,
.modal-content--merged-with-modal {
  width: 30rem;
  max-width: calc(50vw - 3rem);
  max-height: calc(100vh - 3rem);
  /* Styling details irrelevant to the problem */
  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;
  /* Styling details irrelevant to the problem */
  padding: 0.75rem;
  background: rgba(0, 0, 255, 0.1);
}

.modal-content__footer {
  /* Styling details irrelevant to the problem */
  border-top: 1px solid silver;
  background: rgba(0, 255, 0, 0.1);
  padding: 0.75rem;
}


/* Irrelevant styling given to highlight the issue */

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 if<br> container height is reduced.<br>
          <br> In this case, modal <strong>contains</strong><br> flexbox managing<br> body and footer.<br>.
          <br> .
          <br> .
          <br> .
          <br> .
          <br> .
          <br> .
          <br>
        </div>
        <div class="modal-content__footer">
          <code>FOOTER // </code> Doesn't work
        </div>
      </div>

    </div>
  </section>

</main>

Answer №1

An easy solution is to change the .modal to a flex container with a 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;
}
  
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>

Reasoning Behind the Change

Initially, the .modal behaved as a block element with a set max-height which resulted in an overflow issue due to default overflow behavior being visible.

With the adjustment to make the .modal a flex container, the inherent shrink effect is introduced where the flex item will automatically shrink to fit within the height of the flex container, providing the desired outcome.

If you remove display:flex from .modal-content, similar overflow issues will reappear unless you set flex-shrink:0.

Answer №2

To enable the overflow property, a specific length restriction is required.

As per MDN:

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

In your code snippet, there is no height constraint on .modal-content__body (where the overflow property is applied):

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

Similarly, the parent element lacks a height limitation:

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

The use of flex-basis: 0, which is part of flex: 1 in .modal-content__body, does not trigger the overflow condition. However, changing it to flex-basis: 100px demonstrates an impact.

The scrolling behavior is only observed when a height limit is imposed.

A potential resolution could involve transferring the dimensions from the parent (.modal) to the child (modal-content). This adjustment brings the height limitation closer to the content elements to initiate overflow.

Instead of:

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

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

Consider:

.modal { }

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What are effective ways to eliminate script tags from a webpage?

I have implemented tags on my website that users can use to interact with the site. My goal is to figure out how to make the browser only read text from a specific file I write, without any HTML. This should be restricted to certain sections of my websit ...

What are the steps to transforming shorthand CSS into longhand?

Is there a tool available that can automatically convert shorthand CSS to longhand? I am in need of this functionality because I would like to utilize SmartSprites, which is not compatible with shorthand formatting. Additionally, if there is a tool that c ...

The meter.value update feature is functioning properly, however, it does not refresh the displayed "hover" value

When using JavaScript to update a meter's value, I encountered an issue: var LFRMSMeter = document.getElementById("LFRMSMeter"); LFRMSMeter.value = parseFloat(j[0]); Although the updating of the value works fine, hovering over the meter displays the ...

Develop a JSF/XHTML project that showcases a single XHTML page containing duplicated content of itself

Recently, I encountered a scenario where I have an xhtml page containing a sessionscoped bean. I am looking to utilize this page twice within another html page - once on the left side and again on the right side of the screen. The issue I faced is that w ...

Utilize HTML5, CSS, and Responsive Web Design to place four boxes into a div container

Is there a way to arrange four boxes inside a div so that they are positioned at the corners of the top-left, top-right, bottom-left, and bottom-right? And when you click on the box in the middle, a window opens with text. I'm looking for something s ...

Designing templates for websites and applications using node.js

Simplified Question: As I delve into improving my skills with node.js, I'm exploring the concept of templating. How would using node to serve one HTML file and loading page-specific information through AJAX/sockets impact performance and design princ ...

Using Jquery to toggle the visibility of divs based on radio button selections

I am struggling to hide the divs with the radio buttons until their title is clicked on. However, I am facing issues as they are not showing up when their title is clicked on. Any assistance would be greatly appreciated. SPIKE <!DOCTYPE html> &l ...

Retrieve the bounding rectangle of a div that has the CSS style `display: contents` using the getBoundingClientRect

My objective is to apply styling and obtain the bounding box of an entire "row" within a CSS grid, including features like highlighting when hovering over it. To achieve the styling aspect, I make use of the display: contents property, so that the styles ...

The ng-repeat directive adds an additional line after each iteration of the list item

Whenever the angular directive ng-repeat is utilized with an <li> element, I notice an additional line appearing after each <li>. To demonstrate this issue, see the simple example below along with corresponding images. Here is a basic example ...

Guide on displaying the <html> tag within text using AngularJS

I need to display some data in HTML, which looks like this: <p>abcd efg hijk....(<a href=\"http:\/\/www.facebook.com\/stock\/NBR\">NYSE:NBR<\/a>),, however, there are some HTML tags within ...

creating a stunning video background that spans 200 viewport heights

My goal is to incorporate a background video for VH1 and VH2 that remains fixed but stops at VH3. When a user opens the page, they will see #VH1 and the #videoBG as a background video. As they continue scrolling, they will reach #VH2 without the backgrou ...

Changing React Phone Number input field's default style: A step-by-step guide

Is there a way to modify the appearance of the react-phone-number-input component using this npm package: https://www.npmjs.com/package/react-phone-number-input? I am working with React Hook Form and Tailwind CSS alongside this component. However, I' ...

Is there a way for me to retrieve the name of a newly opened browser tab from the original tab?

I have written a code snippet to create a new tab within the same browser by clicking on a link. function newTab() { var form1 = document.createElement("form"); form1.id = "newTab1" form1.method = "GET"; form1.action = "domainname"; //My ...

Alignment of elements in a list at the bottom

I am looking to create multi-level tabs using <li> that grow from bottom to top. Here is the current code I have: div{ width: 200px; border: 1px solid black; } ul{ margin: 0px; padding: 0px; } li{ margin: 2px; width: 20px; display: ...

An option instead of using a pop-up window

Currently, I have a PHP script and a small form that allows users to upload image files. The user can access this feature by clicking on a button on the parent HTML page, which opens up a Pop Up Window. I understand that not everyone is a fan of 'Pop ...

ng-required is ineffective when used with number inputs that have a minimum value requirement

In my form, I have implemented a checkbox that, when checked, toggles the visibility of a div using AngularJS's ng-show. Within this div, there is an input field of type "number" with a validation setting of min="10000". I am trying to prevent the f ...

Creating formatted code blocks within my HTML document

I'm currently working on achieving this layout in my HTML: https://i.stack.imgur.com/2LEQO.png Here is the JSFiddle link: https://jsfiddle.net/cr9vkc7f/4/ I attempted to add a border to the left of my code snippet as shown below: border-left: 1px ...

Is it possible to utilize the addition assignment operator (`+=`) to modify the `transform:rotate('x'deg);` CSS property using

This is the code I have been working on: #move{ height:70px; width:70px; border:2px solid black; border-radius:15px; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <input type="button" val ...

Node JS login leads to fetching /favicon.ico

I've implemented a login/register system using express (passport) on my website. I'm facing an issue where after the user logs in, they are redirected to /favicon.ico instead of the saved originalUrl. Can anyone help me identify what might be cau ...

Show a grid layout featuring varying heights using HTML

I am trying to create a grid view for displaying images in an HTML document. I want each li tag to have a different height, but currently they are all the same height. Below is my HTML code: <div class="blog_main_midd_section"><ul> ...