Un completo curso de diseño gráfico, ilustración, diseño web y tipografía.

Menús desplegables híbridos en CSS

por Eric Shepherd

Ya sé lo que piensas...“¿Realmente hace falta otro artículo sobre menús desplegables con CSS?” Permitidme que os convenza. ¿Qué tal si pudiéramos tener un menú limpio, bien estructurado que combinara el dinamismo y simplicidad de código de los menús desplegables y prescindiera de sus principales problemas (por no mencionar que degradara bien)? Los problemas con los desplegables son:

  1. sus opciones secundarias son inacesibles a menos que actives el sistema de menú por completo, y
  2. no ofrecen suficientes pistas al usuario. Puede ser difícil navegar dentro de una sección particular del sitio porque tienes que ir hacia atrás en el menú desplegable para cambiar de página.

Esta técnica es una forma a prueba de bomba para asegurar la compatibilidad con navegadores y mantener la usabilidad de las personas que tienen navegadores obsoletos o dificultades para acceder a los menús desplegables, sea por una discapacidad o por otros motivos. También orienta mucho mejor al usuario a través del sitio que los menús desplegables convencionales.

Atención: esta técnica no funcionará tan bien para listas que exijan muchos elementos, un caso en el que ciertamente los desplegables bien brillan, o bien se colapsan bajo el peso de su propia masa, dependiendo de tu propia perspectiva.

Vamos a crear un menú híbrido que funciona horizontalmente a través de la ventana. Tiene dos niveles de navegación (en nuestro ejemplo, temas principales y sus páginas asociadas). Nuestro menú permitirá que se pueda acceder a través del desplegable a todas las páginas en ambos niveles de navegación, mostrará cual es la selección actual constantemente, mantendrá al usuario al tanto de dónde se encuentra en el sitio y será limpio y ligero.

Suena muy bien. Vamos a empezar.

Primero necesitamos una lista

Comencemos con una lista de periodos históricos en la arquitectura, como ejemplo, y con algunos de los principales representantes de cada periodo. Añadiremos un identificador en forma de etiqueta ID a los elementos y clases <ul> en unos estados “off” y “on” (inactivo / activo) a todos los elementos principales de la lista (si bien no es probablemente la mejor solución, funcionará bien para el objetivo de este artículo):

<ul id="nav">
<li class="off"><a href="#">Renaissance</a>
<ul>
  <li><a href="#">Brunelleschi</a></li>
  <li><a href="#">Alberti</a></li>
  <li><a href="#">Palladio</a></li>
  <li><a href="#">Michelangelo</a></li>
  <li><a href="#">Bramante</a></li>
</ul></li>
<li class="off"><a href="#">Art Nouveau</a>
<ul>
  <li><a href="#">Mackintosh</a></li>
  <li><a href="#">Guimard</a></li>
  <li><a href="#">Horta</a></li>
  <li><a href="#">van de Velde</a></li>
</ul></li>
<li class="on"><a href="#">Modern</a>
<ul>
  <li><a href="#">Sullivan</a></li>
  <li><a href="#">Le Corbusier</a></li>
  <li><a href="#">Mies</a></li>
  <li><a href="#">Gropius</a></li>
  <li><a href="#">Yamasaki</a></li>
</ul></li>
<li class="off"><a href="#">Postmodern</a>
<ul>
  <li><a href="#">Venturi</a></li>
  <li><a href="#">Eisenman</a></li>
  <li><a href="#">Stern</a></li>
  <li><a href="#">Graves</a></li>
  <li><a href="#">Gehry</a></li>
</ul></li>
<li class="off"><a href="#">Digital</a>
<ul>
  <li><a href="#">Xenakis</a></li>
  <li><a href="#">Lynn</a></li>
  <li><a href="#">Diller+Scofidio</a></li>
  <li><a href="#">Zellner</a></li>
  <li><a href="#">Hadid</a></li>
</ul></li>
</ul>

Añadir algo de estilo

Este es un buen lugar para empezar. Código simple y con valor semántico que se puede mantener bien y está centralizado en un solo lugar. Se parece lo que deseas que se vea.

Lo primero que haremos con nuestro CSS es mostrar el primer nivel horizontalmente, utilizando la propiedad float y ocultar todas las listas de sub-navegación. También haremos que los enlaces se muestren en negrita, coloreados y que tengan un borde.

#nav li {
  /*flotar los elementos principales de lista*/
  margin: 0;
  float: left;
  display: block;
  padding-right: 15px;
}

#nav li.off ul, #nav li.on ul {
  /*coultar la subnavegacion*/
  display: none;
}

#nav li a {
  /*para todos los enlaces de la lista*/
  color: #f90;
  font-weight: bold;
  display: block;
  height: 15px;
  width: 100px;
  border: 1px solid #29497b;
  padding: 5px;
}


A continuación, posicionaremos nuestro segundo nivel de navegación debajo de la lista principal, de modo que cuando se muestre esté en el lugar correcto.


#nav li.off ul, #nav li.on ul {
  /*para colocar la subnavegacion debajo y ocultarla*/
  display: none;
  position: absolute;
  top: 33px;
  height: 15px;
  left: 0;
  padding-top: 10px;
}
  

Finalmente, mostraremos la barra de sub-navegación para el área de tema activa, “Modern.” La mejor manera de hacerlo si quieres un sólo fichero central con el menú completo, es con uan clase en el body llamada, por ejemplo, “Modern,” y los correspondientes selectores. En este artículo, hemos establecido una clase llamada “on” para el tema activo y otra llamada “off” para los inactivs.


#nav li.on a {
  /*cambia el color del borde del area activa*/
  border: 1px solid #f90;
}

#nav li.on ul a, #nav li.off ul a {
  /*  cancela el borde heredado en subnav del tema activo */
  border: 0;
}

#nav li.on ul {
  /*muestra la lista activa de subnav*/
  display: block;
}

Después de añadir un par de bordes, puedes ver lo que tenemos hasta el momento aquí.

Más detalles

Activemos ahora el rollover, el cambio de aspecto al pasar el ratón. No será muy diferente de cualquier otro sistema de menús desplegables — el estado hover se asigna a los elementos de lista, li, lo que hará que Internet Explorer se atragante debido a su pobre implementación de la pseudo clase :hover. Lo arreglaremos dentro de un minuto. El CSS que sigue elimina el borde en el segundo nivel de navegación, hace que la subnavegación activa se muestre siempre, y hace que los menús de subnavegación inactivos se muestren cuando se pase el ratón sobre sus elementos padre. Estableceremos un valor de posición z-index para asegurarnos que los cambios de estado siempre tienen prioridad sobre el menú de sub-navegación actual.

#nav li.on ul a, #nav li.off ul a {
  float: left;
  /*ie no hereda la flotacion*/
  border: 0;
  color: #f90;
  width: auto;
  margin-right: 15px;
}

#nav li.on ul {
  /*mostrar el tema actual*/
  display: block;
}

#nav li.off:hover ul {
  /*  mostrar los otros temas cuando se pasa sobre el padre */
  display: block;
  z-index: 6000;
}

Lo haremos un poco más agradable al usuario, con un fondo diferente en los elementos de menú que se ve al pasar el ratón.


#nav li.off a:hover, #nav li.off:hover a {
  background: #29497b;
  color: #f90;
}

  

Comprueba nuestro progreso aquí.

Adaptación a nuestros amigos los navegadores “especiales”

Tienes dos opciones con los usuarios de navegadores como Internet Explorer, que no admiten :hover en ningún otro elemento aparte de <a>. Puedes bien dejar el menú tal como está, sabiendo que funcionará perfectamente dentro de unos años, cuando todos los navegadores admitan :hover (toquemos madera), y quedar tranquilo de que todas las opciones de navegación serán visibles y accesibles para todos los usuarios, oand resting in the knowledge that all the navigation options will be visible and accessible to all users, or puedes añadir un poquito de JavaScript para reformar los selectores de CSS en un modo que IE entienda para hacer que el dinamismo de los desplegables sea accesible a todos.

Tendremos que ajustar el posicionamiento utilizando el truco del asterisco:

#nav li.off ul, #nav li.on ul {
  /*colocar a subnavegacion debajo*/
  top: 33px;
  *top: 44px; /*reposicionar para IE*/
}

Así que funciona muy bien en los navegadores modernos que cumplen los estándares, y de una manera degradada pero funcional y con posicionamiento correcto, en las versiones 5 y 6 de Internet Explorer. Con algo de ayuda, podemos hacer que todo funcione incluso en IE. Este trocito de JavaScript reescribe los eventos de hover como eventos de mouseover, y funciona en todas las versiones de IE/Win 5x y 6x. Muchas gracias a Patrick Griffiths y Dan Webb, cuyos “Suckerfish Dropdowns” me introdujeron en los sistemas de menú basados en CSS. Su JavaScript es como sigue:

startList = function() {
if (document.all && document.getElementById) {
navRoot = document.getElementById("nav");
for (i=0; i<navRoot.childNodes.length; i++) {
  node = navRoot.childNodes[i];
  if (node.nodeName=="LI") {
  node.onmouseover=function() {
  this.className+=" over";
    }
  node.onmouseout=function() {
  this.className=this.className.replace
      (" over", "");
   }
   }
  }
 }
}
window.onload=startList;

With a simple change to the CSS:

#nav li.off:hover ul, #nav li.over ul { 
  display: block;
  z-index: 6000;
}

#nav li.off a:hover,
#nav li:hover a,
#nav li.over a {
  background: #29497b;
  color: #f90;
}

al añadir la clase “.over” a los items de la lista que requieren cambio al pasar el ratón, la funciona funciona incluso para los usuarios de IE/Win. Deberíais pensar en obtener un mejor navegador, pero por el momento continuaremos ofreciendo soporte a las masas de la manera en que ya nos hemos acostumbrado.

Y eso es todo. Un cambio ligero, quizás, respecto de los trabajos anteriores con menús desplegables con CSS, pero es a la vez otro ángulo para que puedas explorar en los casos en que es realmente útil tener las opciones de navegación a la vista en lugar de ocultas dentro de un menú desplegable.

¿Pero puede ser más bonito?

Ok, no es eso. No podemos dejaros sin una versión algo más rica gráficamente para mostrar el poder de esta técnica y aplicarla a un caso más real. Con algunos cambios, un sistema de navegación con espectros de CSS (gracias, Dave Shea), una foto que tomé en Nueva York, un poco más de CSS, tenemos un menú que realmente muestra el poder de CSS combinado con el del diseño gráfico. Compruébalo en el menú híbrido final en CSS, completamente funcional en todos los navegadores modernos.

Eric Shepherd es el fundador de arkitrave web media, una pequeña firma de diseño en Buffalo, New York. Tiene un master en arquitectura en la Universidad de Buffalo. También es pianista. Su trabajo ha aparecido en el venerable CSS Zen Garden, y es un asociado en Nepo Strategies, una compañía de comercio electrónico y estrategia web en Buffalo.

[ Este artículo ha sido traducido con permiso de A List Apart y su autor.]