jQuery Icon Menu

Designers and developers are continually challenged with ways to display large amounts information. In this age of content, the amount of information being displayed can easily lead to clutter if interface decisions are not carefully considered.

In a previous post, I described how to make an accordion menu using jQuery UI and WordPress without a plugin. Today I’ll describe another helpful design pattern in the form of an icon menu and produce the effect in about 20 lines of jQuery.

What is an Icon Menu?

Welie.com defines an icon menu as a design pattern that allows “users to select a menu item by selecting an image and display the label in a fixed location.” This is another useful tool to display information in a compact space since the labels are usually not shown by default.

Icon Menu on the Food Network Home Page

In this example, jQuery and the scrollTo jQuery plugin will be used to write code that does the following:

  • Degrades gracefully when JavaScript is disabled.
  • Open an icon item assigned at random.
  • Only one icon can be opened at a time.
  • Scroll to the open item and distinguish it from the others.

Structure the Markup

Since this project involves manipulating HTML based on user interaction, it is easiest to start with the HTML. The key is that each menu item is a list item containing a <div> for the icons and another one for the details. After the HTML is in place, the CSS can be used to get the icon menu looking right, and the JavaScript can be added to handle the user interaction and open/close components.

<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>jQuery Feature Box</title>
    <link rel="stylesheet" href="assets/styles/momentum.css" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
    <script src="assets/scripts/jquery.scrollTo-min.js"></script>
    <script src="assets/scripts/featurebox.js"></script>
  </head>
  <body>
    <div class="container">
      <div class="content feature-box">
        <ul class="icons none">
          <li>
            <div class="icon">
              <img src="http://farm7.static.flickr.com/6145/6206056530_16cd2d638a_t.jpg" width="100" height="75" alt="Iceland Glacier">
            </div>
            <div class="description">
              <h5><a href="http://www.flickr.com/photos/edgincvg/6206056530/" title="Iceland Glacier by edgincvg, on Flickr">Iceland Glacier</a></h5>
              <p>
                Northern Iceland
              </p>
            </div>
          </li>
          <li>
            <div class="icon">
              <img src="http://farm4.static.flickr.com/3009/5766640191_a69c4c247c_t.jpg" width="100" height="75" alt="Bartholomew Scenery">
            </div>
            <div class="description">
              <h5><a href="http://www.flickr.com/photos/edgincvg/5766640191/" title="Bartholomew Scenery by edgincvg, on Flickr">Galapagos</a></h5>
              <p>
                Island of Bartholomew
              </p>
            </div>
          </li>
          <li>
            <div class="icon">
              <img src="http://farm5.static.flickr.com/4074/4937793131_dc6476b71f_t.jpg" width="100" height="75" alt="IMG_2264">
            </div>
            <div class="description">
              <h5><a href="http://www.flickr.com/photos/edgincvg/4937793131/" title="IMG_2264 by edgincvg, on Flickr">Sunset at Dinner</a></h5>
              <p>
                Cabarete, D.R.
              </p>
            </div>
          </li>
          <li>
            <div class="icon">
              <img src="http://farm4.static.flickr.com/3340/4624376976_1110e97f9d_t.jpg" width="100" height="75" alt="IMG_2050">
            </div>
            <div class="description">
              <h5><a href="http://www.flickr.com/photos/edgincvg/4624376976/" title="IMG_2050 by edgincvg, on Flickr">Tulips</a></h5>
              <p>
                Cincinnati Zoo
              </p>
            </div>
          </li>
          <li>
            <div class="icon">
              <img src="http://farm4.static.flickr.com/3119/2793606607_7ac5270b50_t.jpg" width="100" height="75" alt="Jaguar Ruin at Lamanai in Belize">
            </div>
            <div class="description">
              <h5><a href="http://www.flickr.com/photos/edgincvg/2793606607/" title="Jaguar Ruin at Lamanai in Belize by edgincvg, on Flickr">Jaguar Ruin</a></h5>
              <p>
                Lamanai Ruins, Belize
              </p>
            </div>
          </li>
        </ul>
      </div>
    </div>
  </body>
</html>

Style with CSS

Once the HTML is in place, begin working on the CSS. The icon menu needs to degrade gracefully with JavaScript turned off, and CSS is the crucial step to pulling that off. The goal at the end of this step is to have all of the menu items in their expanded state.

/**
 *  Add whatever reset you want to use here -
 *  I am using Eric Meyer's CSS reset
 */
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dd, dl, dt, li, ol, ul, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {
  border: 0;
  font-weight: inherit;
  font-style: inherit;
  font-size: 100%;
  line-height: 1;
  font-family: inherit;
  text-align: left;
  vertical-align: baseline;
  margin: 0;
  padding: 0; }

a img, :link img, :visited img {
  border: 0; }

ol, ul {
  list-style: none; }

/**
 * Begin core styling
 */
body {
  background: #dde9de;
  color: black;
  font: 62.5% cambria, georgia, "Times New Roman", Times, serif;
  text-align: center;
  margin-top: 10px; }

h5 {
  font: 18px/1.389 "Franklin Gothic Medium", Tahoma, "Helvetica Neue", Arial, sans-serif; }

ul, ol, dl, p {
  font-size: 14px;
  line-height: 1.389;
  margin-bottom: 1em; }

dd, dt, li, label {
  font-size: 14px;
  line-height: 1.389; }

a {
  color: #706f5c; }
  a:hover {
    color: #a3a28f;
    text-decoration: underline; }
  a:visited {
    color: #a3a28f; }

address, div {
  font-size: 14px;
  line-height: 1.389; }

.container {
  text-align: center; }

.content {
  margin: 0 auto;
  text-align: left; }

/**
 * feature box
 */
.feature-box {
  background: #fff;
  height: 150px;
  padding: 10px 5px 0;
  overflow: auto;
  width: 450px; }

.icons {
  float: left; }

.feature-box li {
  background: #fffeea;
  display: block;
  float: left;
  margin-bottom: 1em;
  width: 250px; }

.icon {
  float: left; }

.icon img {
  display: block; }

.description {
  float: left;
  padding: 5px;
  width: 140px; }

.collapsed .description {
  display: none;
  visibility: hidden; }

li.collapsed {
  margin: 20px 5px 0;
  width: 100px; }

.expanded {
  -webkit-box-shadow: 0px 0px 5px black;
  -moz-box-shadow: 0px 0px 5px black;
  box-shadow: 0px 0px 5px black;
  border: 1px solid #d6d4b0;
  margin-top:0; }

Make the Icon Menu Interactive with jQuery

The final step is to bring it all together with jQuery so only one item is expanded at a time and the items scroll on-click thanks the the scrollTo plugin.

$(document).ready(function(){
  var icons = $('.icons'),
    icon = icons.find('li'),
    numIcons = icon.length,
    openIcon = Math.floor(Math.random()*icon.length),
    iconContainer = $('.feature-box'),
    expandedClass = 'expanded',
    collapsedClass = 'collapsed';

  $(icon[openIcon]).addClass(expandedClass);
  icon.not($('.' + expandedClass)).addClass(collapsedClass);

  icons.css('width', numIcons * 150);

  icon.click(function(e){
    icon.addClass(collapsedClass).removeClass(expandedClass);
    $(this).removeClass(collapsedClass).addClass(expandedClass);
    iconContainer.scrollTo($('.' + expandedClass)[0], 500, {offset: {left:-80}});
  });
});

$(window).load(function(){
  $('.feature-box').scrollTo($('.expanded')[0], 500, {offset: {left:-80}});
});

Conclusion

With about 20 lines of JavaScript, it is possible to put the icon menu to use. If this code is being reused in multiple places, it would be best to set up the dimensions as parameters being used in the JavaScript file so that the code does not get repetitive, but a simple, working example can be achieved in very little time.

See more articles like this in: user interface development javascript jQuery