1

I'm not being able to make the footer stay at the page bottom and the subheader to be just below the header without spacing, while I can add or remove the content in-between.

.wrapper {
  display: flex;
  height: 100%;
  flex-wrap: wrap;
  font-weight: bold;
  text-align: center;
}

.header {
  background: tomato;  
  
  flex-grow: 1;
  flex-basis: 100%;
  height: 40px;
  align-self: flex-start;
}

.subheader {
  background: deepskyblue;
  
  margin-bottom: auto;
  flex-grow: 1;  
  flex-basis: 100%;
  height: 60px;
  align-self: flex-start;
}

.sidebar-wrapper {
  background: gold;

  height: 100%;
  flex-grow: 1;
  flex-basis: 20%;
}

.sidebar {
  background: purple;
  
  height: 80vh;
  top: 15px;  
  position: sticky;
}

.content {
  background: hotpink;
  
  height: 100%;
  flex-grow: 1;
  flex-basis: 80%;
}

.footer {
  background: lightgreen;
  
  height: 40px;
  flex: 1 100%;
  margin-top: auto;
}
<div class="wrapper">

    <div class="header">Header</div>

    <div class="subheader">Subheader</div>

    <div class="sidebar-wrapper">
      <div class="sidebar">
        Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor
        quam, feugiat vitae, ultricies eget, tempor sit amet, ante.
      </div>
    </div>

    <div class="content">
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor
        quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean
        ultricies mi vitae est. Mauris placerat eleifend leo.</p>
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor
        quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean
        ultricies mi vitae est. Mauris placerat eleifend leo.</p>
    </div>

    <div class="footer">
      Footer
    </div>

  </div>

To see the 'misbehavior', just remove the 'sidebar-wrapper' and 'content' elements. Sorry that I can't find a simpler way of describing my problem.

https://stackblitz.com/edit/angular-umydqv

BBacon
  • 2,456
  • 5
  • 32
  • 52

2 Answers2

0

You are trying to do too many things with too few wrappers.

Use one flex container with the direction set to column to build a layout with a header group at the top and a footer at the bottom with a main section in the middle.

Then use another flex container to set up your main area to have the sidebar and content.

Removing your sidebar or content from the main area will not mess up the outer layout this way.

html,
body {
  height: 100%;
  margin: 0;
}

.wrapper {
  display: flex;
  flex-direction: column;
  height: 100%;
  flex-wrap: nowrap;
  font-weight: bold;
  text-align: center;
}

main {
  flex: 1 1 100%;
  display: flex;
}

.header {
  background: tomato;
  height: 40px;
}

.subheader {
  background: deepskyblue;
  height: 60px;
}

.sidebar {
  background: purple;
  flex: 1 0 40%;
}

.content {
  background: hotpink;
}

.footer {
  background: lightgreen;
  height: 40px;
}
<div class="wrapper">

  <header>
    <div class="header">Header</div>
    <div class="subheader">Subheader</div>
  </header>

  <main>

    <div class="sidebar">
      Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante.
    </div>

    <div class="content">
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
        Mauris placerat eleifend leo.</p>
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
        Mauris placerat eleifend leo.</p>
    </div>

  </main>

  <div class="footer">
    Footer
  </div>

</div>
JasonB
  • 6,243
  • 2
  • 17
  • 27
  • I understand my 'lack of wrappers', but I am building and Angular app, and If I need to add a wrapper to each page seems a bit off in reusability terms. Thanks for the answer though. – BBacon Jun 21 '19 at 19:47
0

This layout can be achieved with flexbox, but it's a bit complicated and inefficient. At a minimum, it may require nested containers.

A potentially better solution lies with CSS Grid. No changes necessary to the HTML.

(grid browser support)

Your layout, with extra content items:

.wrapper {
  display: grid;
  grid-template-rows: 40px 60px 1fr 40px;
  grid-template-columns: 20% 1fr;
  height: 100vh;
  font-weight: bold;
  text-align: center;
}

.header {
  grid-column: 1 / -1;
  background: tomato;
}

.subheader {
  grid-column: 1 / -1;
  background: deepskyblue;
}

.footer {
  grid-row: 4 / 5;
  grid-column: 1 / -1;
  background: lightgreen;
}

.sidebar-wrapper {
  background: gold;
  display: flex; /* for full height of child */
}

.sidebar {
  background: purple;
}

.content {
  background: hotpink;
}

body {
  margin: 0;
}
<div class="wrapper">
  <div class="header">Header</div>
  <div class="subheader">Subheader</div>
  <div class="sidebar-wrapper">
    <div class="sidebar">
      Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante.
    </div>
  </div>
  <div class="content">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
      Mauris placerat eleifend leo.</p>
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
      Mauris placerat eleifend leo.</p>
  </div>
  <div class="footer">Footer</div>
</div>

Your layout, without extra content items:

.wrapper {
  display: grid;
  grid-template-rows: 40px 60px 1fr 40px;
  grid-template-columns: 20% 1fr;
  height: 100vh;
  font-weight: bold;
  text-align: center;
}

.header {
  grid-column: 1 / -1;
  background: tomato;
}

.subheader {
  grid-column: 1 / -1;
  background: deepskyblue;
}

.footer {
  grid-row: 4 / 5;
  grid-column: 1 / -1;
  background: lightgreen;
}

.sidebar-wrapper {
  background: gold;
  display: flex; /* for full height of child */
}

.sidebar {
  background: purple;
}

.content {
  background: hotpink;
}

body {
  margin: 0;
}
<div class="wrapper">
  <div class="header">Header</div>
  <div class="subheader">Subheader</div>
  <div class="footer">Footer</div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • I would not call that a 'perfect' solution, since I'll have to order each of my components to avoid issues when removing/adding those. It feels amazingly bad to me that I can't just make some elements 'fill' the space left behind that was not occupied by other elements. Just as other users described, flexbox is just a table design with a different name. Another terrible way of building layouts. – BBacon Jun 24 '19 at 14:03