0

I'm newish to flexbox. My current layout isn't working as well as I'd hoped - my columns are only as tall as the content within them.

  +----------------+
  | header         |
  +-+--------------+
  |n|content       |
  |v+--------------+
  +-+
  empty
----------------------

I'm hoping flexbox will solve that. I'll have to retrofit my existing markup.

Page is full screen width, with a full-width header, then the rest of the page is fluid width content with a fixed width sidebar. (Some pages have a sidebar on the left, others have one on the right.)

Ideally, the two content areas will both extend to the bottom of the page (with their coloured backgrounds) but only go over the fold and scroll if the content is longer than a page.

  +----------------+
  | header         |
  +-+--------------+
  |n| content      |
  |a|              |
  |v|              |
--+-+--------------+--

Do I treat the entire page as the "container", in which I create two rows, one of which is split? Or do I just start the flexbox stuff with the second row that has the sidebar?

It seems to me, it has to be the former, if flexbox is to know how high my header is. Otherwise, when I set their heights to 100%, they'll go over the fold by an amount equal to my header.

I didn't see a header-and-split-columns as a simple example in the flexbox docs, but I'll continue to read and experiment.

(Naturally, it will also have to be responsive, so that, at smaller screen sizes, the elements wrap under each other to fit on a narrow screen.)

DaveC426913
  • 2,012
  • 6
  • 35
  • 63

4 Answers4

2

OK, gathering all the feedback I've gotten above, and borrowing heavily from here, this is what I came up with.

<div class="page-body no-nav no-aside">
    <main>
        <p>content</p>
    </main>
    <nav>nav</nav>
    <aside>details</aside>
</div>

.

.wrapper {
    display: flex;
    min-height: 100vh;
    flex-direction: column;
    background-color: blue;

    header {
        height: 155px;
    }

    .page-body {
        display: flex;
        flex: 1;
        background-color: lavender;
        flex-direction: column;
        min-height: calc(100vh - 155px);
        min-height: -webkit-calc(100vh - 155px);

        nav {
            order: -1;
            background-color: red;
        }

        aside {
            background-color: orange;
        }

        &.no-nav nav,
        &.no-aside aside {
            display: none;
        }
    }
}

@media (min-width: 768px) {

    .wrapper {

        .page-body {
            flex-direction: row;
            flex: 1;

            main {
                flex: 1;
            }

            nav {
                flex: 0 0 385px;
            }

            aside {
                flex: 0 0 320px;
            }
        }
    }
}
  • Header is fixed height
  • Page-body fills the rest of the page
  • pretty straightforward to add a footer if needed (see Holy-Grail article above)
  • all columns are full height, no scrolling unless content flows
  • sidebars are fixed width, content body is fluid
  • structure is responsive
  • added some functionality to hide/show the sidebars as-needed per page

Oddly, this defaults to small-screen as has a media query that overrides for larger screens. (Usually the other way around where I come from.)

DaveC426913
  • 2,012
  • 6
  • 35
  • 63
1

You can create two flexboxes - one to divide header and "rest", and the other inside "rest" to divide it into nav and content.

Also you can just set min-height of header, as can be seen here

fen1x
  • 5,616
  • 6
  • 28
  • 39
1

You can use calc for the min-height (assuming header height as 50px):

.content {
  min-height: calc(100% - 50px);
  min-height: -webkit-calc(100% - 50px);
}

As for the fixed width sidebar, prevent it from growing or shrinking:

.sidebar {
  flex-shrink: 0;
  flex-grow: 0;
}

I would only put the sidebar and the content in the flex box. Put both the sidebar and the content inside a container div and assign display:flex to the container:

.container {
  display: flex;
  flex-direction: row;
}

You will likely need your sidebar to collapse or become fluid with media queries when the window width decreases to a certain point. Also, I find this tool helpful when working with flex, as it does get complex.

Smaft
  • 142
  • 10
0

I hope I've understood your question.. This approach might help get you started. Let me know if you have any specific questions...

body {
  margin: 0;
  height: 100vh;
  font-family: sans-serif;
  color: white;
}

.container {
  height: 100%;
  background: grey;
  display: flex;
  flex-direction: column;
}

header {
  height: 150px;
  background: blue;
}

.content {
  height: 100%;
  display: flex;
  background: green;
}

.sidebar {
  background: #76c5ff;
  width: 200px;
}

.main {
  background: #ef3a59;
  flex: 1;
}

@media (max-width: 600px) {
  body {
    height: initial;
  }
  .content {
    height: initial;
  }
  .content {
    flex-direction: column;
  }
  .sidebar {
    width: 100%;
    order: 2; /* remove this to keep sidebar above main content */
  }
}
<div class="container">
  <header>header
  </header>
  <div class="content">
    <div class="sidebar">sidebar</div>
    <div class="main">main content</div>
  </div>
</div>
sol
  • 22,311
  • 6
  • 42
  • 59
  • Sidebar is fixed width. – DaveC426913 Jul 13 '17 at 15:35
  • Also, the content does not reach the bottom of the page. Yes, they're both the same height, but there's a big white space at the bottom. – DaveC426913 Jul 13 '17 at 15:45
  • @DaveC426913 The content reaches the bottom in my snippet. Is that not what you wanted? – sol Jul 13 '17 at 15:47
  • @DaveC426913 I don't see any white space at the bottom of the snippet I provided. Can you be more specific? Perhaps the browser you're viewing the snippet on doesn't support `viewport` units? – sol Jul 13 '17 at 15:49
  • I see the problem. There are a bunch of system-generated elements (this is an angular2 app) between body and my content wrapper. The right combination of height: 100% and height: 100vh gets rid of the white space. – DaveC426913 Jul 13 '17 at 15:56
  • So, the only problem remaining is that it is not responsive. It remains in the same orientation no matter how small I make the browser. Do I add bootstrap grid classes on top of the flexbox rules? Are they compatible? – DaveC426913 Jul 13 '17 at 15:58
  • @DaveC426913 updated - I would use a media query and just make some simple changes. – sol Jul 13 '17 at 16:03
  • No idea how media queries are supposed to override flex to make it responsive. Presumably, setting sidebar and content display: block should cause them to wrap but it has no effect. – DaveC426913 Jul 14 '17 at 18:41
  • https://css-tricks.com/snippets/css/a-guide-to-flexbox/ You might find this link informative – sol Jul 14 '17 at 19:02