Published on

Flexbox and CSS Grid

Authors

Getting Flexbox and CSS Grid layouts to behave as intended can often be a bit tricky because of all of the moving parts under the hood. However, over time, I've found that sticking to several patterns helps with creating proper layouts and reducing frustration. This post will outline some common Flexbox and CSS Grid examples that can be implemented in just about any frontend project.

First, let's review the concepts and the goals of the Flexbox and Grid layouts...

Flexbox is a one-dimensional layout system that is used to create a row or a column axis layout. Flexbox consists of (at least) two elements - a flex container and flex items (i.e. elements within the container). Once flex properties are applied on the items it is easier to control/manipulate things like alignment and flow.

CSS Grid is a two-dimensional layout system that manipulates rows and columns together. In this regard, it is more powerful than Flexbox. Similiar to Flexbox though, a container is created and elements placed within.

Both Flexbox and Grid provide developers with the means to create clean, appealing layouts. A key benefit of these systems though is responsiveness. If you're building with responsive design it mind, it is likely Flexbox and/or Grid will be needed.


Flexbox

Stretch All w/ Fixed Spacing

Diagram of flexbox with fix-spaced, evenly stretched items

A very basic flexbox pattern is to have a container with several boxes that evenly fill the width.

<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>
.container {
  display: flex;
  padding: 0.25rem;
  border-radius: 5px;
  background-color: #e5e5e5;
}

.item {
  flex-grow: 1;
  height: 100px;
  border-radius: 5px;
  border: 2px solid #fca311;
  background-color: #14213d;
}

.item + .item {
  margin-left: 4%;
}

Note that a flex-direction property with a value of column could be added to the container selector to covert this layout from a row to a column (by default, flex with be a row). Also note that a margin-left is being applied here to all items except for the 1st.

Stretch Middle w/ Fixed Spacing

Diagram of flexbox with fix-spaced, middle item stretched

Here we give the first and last items a fixed width then apply a class to the middle item that has a property of flex-grow: 1. This tells the middle item to fill the available space (between the first and last items).

<div class="container">
  <div class="item"></div>
  <div class="item item-center"></div>
  <div class="item"></div>
</div>
.container {
  display: flex;
  padding: 0.25rem;
  border-radius: 5px;
  background-color: #e5e5e5;
}

.item {
  width: 100px;
  height: 100px;
  border-radius: var(--border-radius);
  border: var(--border);
  background-color: var(--background-color);
}

.item-center {
  flex-grow: 1;
  border-radius: var(--border-radius);
  border: var(--border);
  background-color: var(--background-color);
}

.item + .item {
  margin-left: 2%;
}

Alternating Grid

Diagram of alternating grid layout using flexbox

The key here is the flex-wrap: wrap property. This allows for items in the container to wrap to a new line when it runs out of space. Additionally, we use the .item:nth-child(3n) selector to apply a width of 100% to the 3rd item / 2nd row to give that offset look.

<section class="wrapper">
  <div class="container">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
</section>
.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  padding: 0.25rem;
  border-radius: 5px;
  background-color: #e5e5e5;
}

.item {
  width: 49%;
  height: 100px;
  margin-bottom: 2%;
  border-radius: var(--border-radius);
  border: var(--border);
  background-color: var(--background-color);
}

.item:nth-child(3n) {
  width: 100%;
}

Grid

Grid Template Areas

Diagrams of responsive grid layouts

Utilizing the grid-template-areas property is a pretty intuative approach to building grid layouts for a page. Furthermore, this property allows for nice control over responsiveness - how the layout looks / behaves at different screen widths.

<section class="wrapper">
  <header class="main-head item">The Header</header>
  <nav class="main-nav item">
    <ul>
      <li><a href="#">Nav Item One</a></li>
      <li><a href="#">Nav Item Two</a></li>
      <li><a href="#">Nav Item Three</a></li>
    </ul>
  </nav>
  <article class="content item">
    <h1>Main Article Area</h1>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum massa sapien, vehicula nec
      nisi in, fermentum efficitur enim.
    </p>
  </article>
  <aside class="side item">Sidebar Content</aside>
  <div class="ad item">An Advertising Space</div>
  <footer class="main-footer item">The Footer</footer>
</section>
/* MOBILE FIRST APPROACH */
.wrapper {
  display: grid;
  gap: 20px;
  max-width: 80%;
  margin: 0 auto;
  grid-template-areas:
    'header'
    'nav'
    'content'
    'sidebar'
    'ad'
    'footer';
}

/* GRID AREAS */
.main-head {
  grid-area: header;
}

.content {
  grid-area: content;
}

.main-nav {
  grid-area: nav;
}

.side {
  grid-area: sidebar;
}

.ad {
  grid-area: ad;
}

.main-footer {
  grid-area: footer;
}

/* MEDIA QUERIES */
@media (min-width: 500px) {
  .wrapper {
    grid-template-columns: 1fr 3fr;
    grid-template-areas:
      'header  header'
      'nav     nav'
      'sidebar content'
      'ad      footer';
  }
  nav ul {
    display: flex;
    justify-content: space-between;
  }
}

@media (min-width: 700px) {
  .wrapper {
    grid-template-columns: 1fr 4fr 1fr;
    grid-template-areas:
      'header header  header'
      'nav    content sidebar'
      'nav    content ad'
      'footer footer  footer';
  }
  nav ul {
    flex-direction: column;
  }
}

Additional Resources