El menú desplegable

Un menú desplegable no necesita JavaScript ni nada complicado. Se resuelve con dos propiedades que ya conocemos:

  1. display: none mantiene el submenú oculto. No se ve y no ocupa sitio.
  2. :hover lo muestra, cambiando esa misma propiedad a display: block.

Eso es todo. El submenú está siempre escrito en el HTML: lo único que cambia es si se dibuja o no.

La idea que hay que entender

El :hover no se pone en el submenú, sino en la opción que lo contiene. Si se pusiera en el submenú no funcionaría nunca: está oculto, así que el ratón no puede llegar a ponerse encima de algo que no se dibuja.

.con-submenu:hover  .submenu  { display: block; }
   ↑  el ratón entra aquí      ↑  y se muestra esto

El HTML

Un menú es una lista. Y un submenú es otra lista dentro de una de sus opciones:

<nav>
  <ul>
    <li><a href="aboutme.html">About me</a></li>
    <li><a href="contact.html">Contact</a></li>

    <li class="con-submenu">
      <a href="work.html">Work</a>

      <ul class="submenu">
        <li><a href="naturaleza.html">Naturaleza</a></li>
        <li><a href="retratos.html">Retratos</a></li>
      </ul>

    </li>
  </ul>
</nav>

Fíjate en que la segunda <ul> está dentro del <li> de Work, y que ese <li> no se cierra hasta después del submenú.

El CSS

/* El menú en horizontal */
nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
nav > ul {
  display: flex;
}

/* --- Lo esencial del desplegable --- */

.submenu {
  display: none;              /* oculto de partida */
}

.con-submenu:hover .submenu {
  display: block;             /* visible con el ratón encima */
}

Con solo esas dos reglas el desplegable ya funciona. Pero empuja al resto de la página hacia abajo al aparecer, porque ocupa sitio. Para que flote por encima del contenido hacen falta dos líneas más, de las que vimos en posicionamiento:

.con-submenu {
  position: relative;         /* es el ancla */
}

.submenu {
  display: none;
  position: absolute;         /* sale del flujo: no empuja a nadie */
  top: 100%;                  /* justo debajo de Work */
  left: 0;
}

top: 100% significa «a la altura del 100 % de mi ancla», es decir, justo por debajo de la opción Work.

Resultado

Pasa el ratón por Work:

<nav>
  <ul>
    <li><a href="aboutme.html">About me</a></li>
    <li><a href="contact.html">Contact</a></li>

    <li class="con-submenu">
      <a href="work.html">Work</a>

      <ul class="submenu">
        <li><a href="naturaleza.html">Naturaleza</a></li>
        <li><a href="retratos.html">Retratos</a></li>
      </ul>

    </li>
  </ul>
</nav>

Dos advertencias

  1. En el móvil no hay ratón. Sin :hover, este menú no se abre al tocarlo. Para pantallas táctiles hace falta otra solución, que veremos aparte.
  2. El submenú debe tocar a su opción. Si queda un hueco entre Work y la lista desplegada, el ratón «se cae» por él y el menú se cierra antes de llegar. Nada de márgenes entre los dos.