Nothing matches your search.

Pure CSS Responsive Flex Menu

Making a pure CSS responsive menu using flexbox.

This resource is a responsive menu based on CSS using flexbox. It relies upon a checkbox input to toggle between states and can therefore be used as an alternative to JavaScript-based solutions.

What We’ll be Making

This resource is a responsive menu based on CSS using flexbox. It relies upon a checkbox input to toggle between states and can therefore be used as an alternative to JavaScript-based solutions. For desktop-sized displays, the menu will display as a list of text links, while on mobile devices, the menu will display as an icon that toggles the display of text links.

Creating the Structure

Structuring the HTML

Our HTML will be structured in 2 main containers, a nav element that contains our menu and a header element that contains some preview content.

We’re using an unordered list for our navigation links, contained in a nav element with the class of “wrapper”. Our entire menu system is in-turn wrapped in a nav element with the class of “navBar”. We’ll target these classes with CSS to adjust our layout.

We’ll use a basic div with a class of “logo” to act as placeholder for a logo.

A simple header with a heading and some filler text will give our page some content to preview.

<nav class="navBar">
	<nav class="wrapper">
		<div class="logo"></div>
		<ul>
			<li><a href="#">Lorem</a></li>
			<li><a href="#">Ipsum</a></li>
			<li><a href="#">Serum</a></li>
		</ul>
	</nav>
</nav>
<header class="wrapper">
  <h1>Big ol' Lorem</h1>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis, sint corporis dolores omnis consectetur quaerat nesciunt beatae maiores, itaque labore ex vero pariatur nulla non fugiat, facilis eaque sunt doloremque!</p>
</header>

Basic CSS Styling

We’ll add some basic styling to our snippet with CSS. I’m using Sass for this example, but you could just as easily use plain ol’ CSS. We’ll give our h1 some extra top-padding so that it displays below our navigation.

@import url(https://fonts.googleapis.com/css?family=Oswald:400,700);

//Color Variables
$color1: #E84545; //Red
$color2: #53354A; //Plum
$color3: #903749; //Maroon

// Base Styles
body {
  background-color: $color1;
  color: $color2;
  font-family: 'Oswald', sans-serif;
  line-height: 2em;
  text-transform: uppercase;
}

h1 {
  font-size: 3em;
  padding: 1em 0;
}

header {padding-top: 75px;}

Our content is centered by giving the .wrapper class the property margin: 0 auto. We limit its width by giving it the property max-width: 960px.

.wrapper {
  margin: 0 auto;
  max-width: 960px;
  padding: 0 2%;
}

We ensure that the navigation stays at the top of the browser window by giving it a position: fixed property. Setting its width to min-width: 100% will ensure that the navigation spans the full width of the browser window.

.navBar {
  background-color: $color2;
  position: fixed;
  min-width: 100%;
}

Lastly, we’ll give our logo placeholder some definition by giving it a height, width and background-color.

.logo {
  background-color: $color1;
  border-radius: 50px;
  display: inline-block;
  height: 45px;
  margin: 1em 0;
  width: 45px;
}

Navigation Styling

We’ll focus on styling the navigation for our full, desktop version first and then implement our mobile toggle afterward.

CSS Menu - Desktop Version

The desktop version of the menu with full, inline navigation links.

We’ll target our navigation wrapper by nesting the selector .wrapper within the nav element. This allows us to specifically target the wrapper when it is a child of a nav element. We give this class the display: flex property to make it a flex container. We can vertically center the child elements (navigation links and logo) by giving the parent container the flex property align-items: center. Lastly, giving the parent container the flex property justify-content: space-between evenly distributes the child elements within the parent flex container, effectively floating our logo to the left and our menu items to the right.

nav {
   .wrapper {
    align-items: center;
    display: flex;
    justify-content: space-between;
  }
 }

Next we’ll target our navigation links by nesting them within our nav element. In the same manner that we set our nav .wrapper to display as a flex container, we can set give the ul the display: flex and justify-content: space-between properties to control the spacing between our list items. Traditionally, we might achieve spacing between list items using right and left padding. The flexbox model allows the spacing between these items to be intelligently adjusted.

We set our list items to display: inline-block so that they don’t stack. We’ll also add a bit of transitioning to our anchors for a bit of visual interest.

nav {
  ul {
    display: flex;
    justify-content: space-between;
    list-style-type: none;
    width: 50%;

    a {
      color: $color1;
      text-decoration: none;
      transition: all .5s ease;

      &:hover {color: $color3;}
    }
  }

  li  {
    display: inline-block;
  }
 }

Adding the Menu Toggle

Setting Up the Input/Label

We’ll place our input menu as a sibling to our logo div and navigation ul. Our mobile menu will use a checkbox type input, which we’ll give an id of “menu-toggle”. We’ll also give the input a label with a class of “label-toggle”.

<input type="checkbox" id="menu-toggle">
      <label for="menu-toggle" class="label-toggle"></label>
</input>

In our CSS we’ll set both elements to display: none.

#menu-toggle {display: none;}

.label-toggle {display: none;}

CSS Menu - Toggled State

The mobile version of the menu, toggled open.

Adding a Media Query and Toggled States

We’ll set our media query to target screen widths at or below 768px by nesting the following code within @media screen and (max-width: 768px). We’ll switch our ul and li to display: block so that our list items will stack vertically. We set transition: all for the ul because we’ll be transitioning the height, opacity, and visibility properties when toggling.

nav {
      ul {
        a {
          color: $color2;
        }
      }
    }

ul {
  background-color: $color1;
  display: block;
  height: 0;
  list-style-type: none;
  opacity: 0;
  text-align: center;
  transition: all 1s ease;
  width: 100%;
  visibility: hidden;
}

li {
  border-bottom: 2px solid $color2;
  color: $color2;
  display: block;
  font-size: 1.5em;
  padding: 2em 0;
}

Because the display property isn’t effected by transition, we’ll need to transition our menu using a combination of visibility: hidden, height: 0, and opacity: 0. In our toggled state, dictated by #menu-toggle:checked, we’ll set the transitioned properties to the following:

#menu-toggle:checked ~ ul {
      opacity: 1;
      height: 100vh;
      visibility: visible;
}

Now when toggling our menu, the menu container will expand and transition nicely. This menu, built on CSS alone, serves as a responsive way to serve navigation. You can also remove the desktop state to have a full-screen toggle menu at any screen width.

The Finished Result

Below you’ll see the finished result, which you can fork on Codepen. Note that in order to see the responsive aspects of the menu, you’ll need to run this snippet in debug mode to access the media query breakpoint.

See the Pen Pure CSS Responsive Menu by Christopher Murphy (@Splode) on CodePen.