No Time Dad

A blog about web development written by a busy dad

Another CSS Responsive Layout Example

It’s easy to get caught up in flashy designs. You start trying to replicate Apple’s homepage and before you know it five hours have gone by and you barely have a single section of a landing page done. Or most likely, nothing at all. I’ve found that a good way to avoid this trap is to focus on creating a working skeleton page first, then go back and fill in the parts to make it shine.

Below is a working skeleton of a responsive layout. Here are the goals I set out to accomplish with this example:

Small screens:

    1. It should have a toggleable nav menu
    1. The sidebar menu should be hidden

Large screens:

    1. Mobile menu and toggle button should be hidden
    1. Sidebar menu should be displayed

responsive-nav-template

The code isn’t complex at this stage. Remember, it’s a skeleton template and meant to be functional but simple. No bells and whistles. It should just work.

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <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" />
    <link rel="stylesheet" href="styles.css" />
    <script src="portfolio.js"></script>
    <title>Responsive Portfolio</title>
  </head>
  <body>
    <header>
      Portfolio
      <button id="mobile-button" type="button" onclick="toggle()">Menu</button>
    </header>
    <main>
      <nav class="hide-mobile" id="mobile-nav">
        <ul>
          <li>Home</li>
          <li>About</li>
          <li>Projects</li>
          <li>Contact</li>
        </ul>
      </nav>
      <div class="sidebar">
        <nav>
          <ul>
            <li>Home</li>
            <li>About</li>
            <li>Projects</li>
            <li>Contact</li>
          </ul>
        </nav>
      </div>
      <div class="content">Content</div>
    </main>
  </body>
</html>
/* styles.css */

/*  Resets */
* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* Main styles */
header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background-color: aqua;
}

main {
  background-color: lightgreen;
}

#mobile-nav {
  background-color: lightcoral;
}

.hide-mobile {
  display: none;
}

.sidebar {
  background-color: lightcoral;
  display: none;
}

@media (min-width: 768px) {
  #mobile-button {
    display: none;
  }

  #mobile-nav {
    display: none;
  }

  main {
    display: flex;
  }

  .sidebar {
    display: block;
  }
}
// portfolio.js

function toggle() {
  document.getElementById("mobile-nav").classList.toggle("hide-mobile")
}

The html itself is made up of a header element and a main element. Both elements change based on the size of the screen. In this example, the width of 768px is the only breakpoint to trigger the changes. More breakpoints can be added as needed, but I think this one is a good starting point for most early designs.

The header itself is a flexbox container that uses justify-content space-between to handle the spacing between the elements, as well as align-items center to ensure all elements in the header are vertically and horizonally aligned.

The header also contains a menu button element that is only shown on small screens. Once the screen reaches 768px or larger, the button is hidden via display: none; in the media query. Clicking the button fires off the toggle function from portfolio.js, which toggles the hide-mobile class in the classList.

An alternate approach to hiding the mobile nav would be to change the display value via document.getElementById('mobile-nav').style.display. The issue with doing this is that it adds an inline style to the element which cannot be removed by the media query, so the mobile nav would potentially remain open on larger screens. It would look something like the below.

<div style="display: none;">...</div>

Once the screen size increases to hit the min-width the mobile nav should be hidden regardless of whether its open or not and the sidebar should be displayed instead. The media query changes the sidebar selector display property from none to block, which adds it back into the DOM making it visible. On larger screens the main element is initialized as a flexbox container which creates the structure for the sidebar and content sections.

This responsive nav template looks simple but it’s doing a lot, in my opinion. I think a mistake a lot of developers make when building a layout is diving too deep into flashy style changes before creating a strong foundation to work from. None of the flashy changes are going to matter if the page isn’t working as expected. Start with a basic skeleton first, then build the fanciest styled page possible…if that’s what you want.