Simple SASS Menu for Websites

I always need some sort of menu system in every website. I though it’d be good to create a basic layout in SASS that I could reuse.

The HTML

The menu is created with the following HTML structure, although obviously the menu items will be meaningful and the links will point to somewhere!

The ‘main’ menu options are <li>’s within the top-level <ul>. Sub-menus can be embedded as a new <ul> within a parent <li>. Sub-sub menus are also supported. Menus deeper in the tree than this will be displayed, but I’d be careful that about doing this as they’re likely to not fit on the screen! I probably should look at preventing these menus from displaying at all.

This HTML format is also by default how WordPress generates its menus, and so this should be usable in WordPress themes too.

<div id="menu">
  <ul>
    <li><a href="#">Main 1</a></li>
    <li><a href="#">Main 2</a></li>
    <li><a href="#">Main 3</a>
      <ul> <!-- SUBMENU -->
        <li><a href="#">Sub 1</a></li>
        <li><a href="#">Sub 2</a></li>
      </ul></li>
    <li><a href="#">Main 4</a>
      <ul> <!-- SUBMENU -->
        <li><a href="#">Sub 1</a>
          <ul> <!-- SUB-SUB MENU -->
            <li><a href="#">Sub-Sub 1</a></li>
            <li><a href="#">Sub-Sub 2</a></li>
          </ul></li>
      </ul></li>
  </ul>
</div>

[GARD]

The SASS

@import "compass/css3/box-shadow";
$highlight: #d9c10c;
$highlight-text: #efebdf;

#menu {
	text-align: center;
	border-bottom: 2px solid $black;
	background-color: adjust-lightness($light, -5);
	background-color: rgba(0,0,0,.15);
	font-family: BebasNeueRegular, arial, sans;
	font-size: 140%;
	line-height: 1em;

	/* Main menu items */
	li {
		display: inline-block;
		position: relative;

		/* Space out the links */
		a {
			padding: 1em;
			display: block;
		}

    	/* Hide sub menus & sub-sub menus
     	* Position *underneath* originating li (see ul ul below) */
		ul, ul ul {
			display: none;
			position: absolute;
			z-index: 999;
			top: 100%;
			left: 0;
			width: 12em;
			background-color: adjust-lightness($highlight, -10);
			@include box-shadow (-5px 5px 10px rgba(0,0,0,.5));
		}

    	/* Position sub-subs to right of parent li */
		ul ul {
			left:100%;
			top: 0;
			background-color: adjust-lightness($highlight, -15);
		}

	    /* Make sub & sub-sub li's fill parent ul
     	* Add feint border to bottom to separate items */
		li {
			display: block;
			border-bottom: 1px solid adjust-lightness($highlight, -8);
		}
	}

	/* Highlight li on hover */
	li:hover {
		background-color: $highlight;

		/* Change anchor colour to highlighted text */
		> a {
			color: $highlight-text;
			background: none;
		}

		/* Display subs and sub-subs on parent hover */
		> ul {
			display: block;
		}

  	}

	/* Don't display menus further than 3 deep in ul tree */
	ul ul ul li:hover ul {
		display: none;
	}

	/* Make sure no padding & margins round <ul>s.
	 * Very likely to have been set in CSS for rest of site */
	ul {
		padding: 0;
		margin: 0;
	}

}

Compile the SASS using Compass. I’ve got a guide on how to do that if you need it!

Hopefully that’ll be helpful to somebody. It’s currently a bit of a work-in-progress, so I’d appreciate any improvements you can suggest in the comments.

Update 30th May 2013

  • Stopped menu <ul>s nested too deeply into the tree (more than 3 levels) from displaying.
  • Reset padding and margins around <ul>s. Most sites will probably have an indent set for <ul>s, and it messes up the menu item highlighting,

Update 13th May 2013

  • I’ve moved the spacing for the menu items from the <li> to the <a> tags. This means you can click anywhere in the menu items and the anchor will still work.
  • Also removed any background changes from a tags, as I sometimes use that in a:hover for the rest of the site, and it appears outside the menu borders. Ugly.

[GARD]


COMMENTS