Search code examples
htmlcsslayoutflexbox

Flex item fill height but without flex-direction: column


What I have so far

This is the flex layout I have. It is based on the idea of holy-grail. This is what current layout look

What I'm trying to do

I need main to stretch to fill remaining height This is what I'm trying to make

Most solutions I found on the internet won't work for me.
So far my attempts with %based heights have nothing fruitful.
Setting main height to 100% will make it overflow parent container.
Headers and footer don't have fixed height, hence, calc based solutions also won't work.


External Links:

current_layout: https://i.sstatic.net/GooN5.png
trying layout: https://i.sstatic.net/3Ovic.png

Code snippet

.ctm .grail {
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;

    justify-content: flex-start;
    align-content: space-between;

    gap: var(--ctm-gap, 1em) var(--ctm-gap, 1em);
}

.ctm .grail>details,
.ctm .grail>header,
.ctm .grail>nav,
.ctm .grail>footer {
    flex-basis: 100%;
}

.ctm .grail>header {
    min-height: 4em;
}

.ctm .grail>main {
    flex-grow: 3;
}

.ctm .grail>aside {
    flex-grow: 1;
    min-width: min(6em, 100%);
}

<!DOCTYPE html>
<html lang="en" class="ctm">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Consortium Test</title>

    <link rel="stylesheet" href="../../assets/output/web/styles.css">

    <style>
        body {
            margin: 0;
            min-height: 100vh;
            background-color: #122334;
        }

        details {
            background-color: #f00;
            color: #fff;
        }

        header {
            background-color: #f44;
            color: #fff;
        }

        nav {
            background-color: #0f0;
            color: #fff;
        }

        aside {
            background-color: #00f;
            color: #fff;
        }

        main {
            background-color: #ff0;
            color: #000;
        }

        footer {
            background-color: #f0f;
            color: #fff;
        }

    </style>
</head>

<body class="grail">
    <details>
        <summary>Notification</summary>
        <p>Details</p>
    </details>
    <header>Header</header>
    <nav>Navigation</nav>
    <aside>Left</aside>
    <main>Main</main>
    <aside>Right</aside>
    <footer>Footer</footer>
</body>

</html>


Solution

  • Structure of HTML needs to be change to get the required output

    <!DOCTYPE html>
    <html lang="en" class="ctm">
      <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Consortium Test</title>
    
    
        <style>
          body {
            margin: 0;
            min-height: 100vh;
            background-color: #122334;
          }
    
          details {
            background-color: #f00;
            color: #fff;
          }
    
          header {
            background-color: #f44;
            color: #fff;
          }
    
          nav {
            background-color: #0f0;
            color: #fff;
          }
    
          aside {
            background-color: #00f;
            color: #fff;
          }
    
          main {
            background-color: #ff0;
            color: #000;
          }
    
          footer {
            background-color: #f0f;
            color: #fff;
          }
    
          .ctm .grail {
            display: flex;
            flex-direction: column;
            flex-wrap: wrap;
    
            justify-content: flex-start;
            align-content: space-between;
    
            gap: var(--ctm-gap, 1em) var(--ctm-gap, 1em);
          }
    
          .ctm .grail > details,
          .ctm .grail > header,
          .ctm .grail > nav,
          .ctm .grail > footer {
            width: 100%;
          }
    
          .ctm .grail > header {
            min-height: 4em;
          }
    
          .body main {
            flex-grow: 2;
          }
    
          /* .ctm .grail   */
          .body {
            display: flex;
            flex-direction: row;
            flex: 1;
            gap: 16px;
            /* wid */
          }
          .body aside {
            flex-grow: 1;
            min-width: min(6em, 100%);
          }
        </style>
      </head>
    
      <body class="grail">
        <details>
          <summary>Notification</summary>
          <p>Details</p>
        </details>
        <header>Header</header>
        <nav>Navigation</nav>
        <div class="body">
          <aside>Left</aside>
          <main>Main</main>
          <aside>Right</aside>
        </div>
        <footer>Footer</footer>
      </body>
    </html>