How should I proceed to create this layout with CSS, keeping future extensibility in mind?

Hello, I need a simple layout that at first might seem like a good candidate for a flex container set to column, with another flex container set to horizontal in the header.

------------------------------------------------------
| <header>               |                           |
| Logo                   |         Navigation        |
|-----------------------------------------------------
| <main>                                             |   
| Content                                            |
|                                                    |
|                                                    |
|                                                    |
|-----------------------------------------------------
|<footer>                                            |
|                                                    |
|----------------------------------------------------|

However, I was thinking that in the future, I might want to add a vertical sidebar to the left side of the main content or to its right side (or maybe both sides).

------------------------------------------------------
| <header>               |                           |
| Logo                   |         Navigation        |
|-----------------------------------------------------
| <aside>  | <main>                                  |   
| sidebar  | Content                                 |
|          |                                         |
|          |                                         |
|          |                                         |
|-----------------------------------------------------
|<footer>                                            |
|                                                    |
|----------------------------------------------------|

With this in mind, wouldn’t it be better to start with a grid container? Later on, this would give me the flexibility of using grid-template-columns to lay out things more easily, and to use flexbox only in the header. (or maybe a sub grid in the header as well?)

Browser compatibility isn’t that crucial to me. As long as it works on something from the past 5 years, it’s fine.

For now, I tried something like this, I do not need the sidebar for now. However, I’m not sure if my approach is good:

   :root {
      box-sizing: border-box;
    }

    *,
    *::before,
    *::after {
      box-sizing: inherit;
    }

    body {
      margin: 0;
      padding: 0;
      background-color: lightblue;
    }

    .grid-container {
      display: grid;
      justify-content: center;
      grid-template-areas:
        "header"
        "main"
        "footer";
    }

    .logo {
      grid-area: logo;
    }

    .header {
      grid-area: header;
      background: lightsalmon;
    }

    .main {
      grid-area: main;
    }

    .footer {
      grid-area: footer;
    }

    @media (min-width: 52em) {
      .grid-container {
        grid-template-columns: minmax(300px, 800px);
        grid-template-areas:
          "header"
          "main"
          "footer";
      }
    }
    <!DOCTYPE html>
    <html lang="en-US">
      <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="style.css">
        <title>Website</title>
      </head>
      <body>
        <div class="grid-container">
          <header class="header">
            <div class="logo">Logo</div>
            <nav class="navigation">Navigation</nav>
          </header>

          <main class="main">
            Main content
          </main>

          <footer>
            Footer
          </footer>
        </div>
      </body>
    </html>

I would be grateful for any suggestions. Thank you.

You don’t need to repeat the same things in your media queries only the differences.

I would only centre the large screen version otherwise the small screen shrinks to content width.

I’d do this:

:root {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}

body {
  margin: 0;
  padding: 0;
  background-color: lightblue;
}

.grid-container {
  display: grid;
  grid-template-areas:
    "header"
    "main"
    "footer";
}

.logo {
  grid-area: logo;
}

.header {
  grid-area: header;
  background: lightsalmon;
}

.main {
  grid-area: main;
}

.footer {
  grid-area: footer;
}

@media (min-width: 52em) {
  .grid-container {
    grid-template-columns: minmax(300px, 800px);
    justify-content: center;
  }
}

I’m not sure about the minmax-columns rules as I would simply have put a max-width of 800px on the wrap. Add the column widths when/If you add the extra column.

I would avoid the complexities of subgrid unless you just meant a nested grid.

Either flex or grid will do what you want but grid may make it slightly easier to add a sidebar as you won’t need to nest it inside another container. (Indeed that layout can be done without flex or grid but they will make it easier.)

In many cases grid or flex are interchangeable but flex needs more nested elements if you want more columns whereas grid can place siblings in columns as required.

Sometimes its just a matter of choice or what you feel most comfortable with. Grid is usually best for the whole structure and then use what’s appropriate inside. Obviously in cases where you have to have horizontal and vertical alignment (like a table structure) then grid is the only property that can do that reliably and without fixing all the dimensions.

What I would say though is that 'Content is King’ and a wire-frame is only a guide. You really should be designing the site to fit the type of content that you are displaying and when testing add full dummy content to test the integrity of your grid structure so you know what breaks before it breaks in the real world.

I see hundreds of wire frame layouts offered as templates but quite often they fail when real content is added because no one thought about simple things such as long words or headings or have used fixed heights for fluid content.

2 Likes

Thank you. Very well explained. I appreciate it.

1 Like