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

Dominar las listas con CSS

por Mark Newhouse

Ya en 1999 estaba alabando las virtudes de las hojas de estilo en cascada en las listas de correo. Hay cosas que nunca cambian.

Lo que ha cambiado es la manera en que considero las CSS, y la estructra subyacente de (X)HTML al que se aplican. Por ejemplo, encuentro que la mayoría de páginas en el web contienen un menú de enlaces en un área de navegación. Estos enlaces frecuentemente están marcados como una serie de enlaces, a menudo en DIVs separados o en párrafos. Estructuralmente, sin embargo, son una lista de enlaces, y deberían codificarse como tales.

Por supuesto, la razón por la cual no los codificamos como tales es porque no queremos un botón delante de cada enlace en nuestra área de navegación. En un artículo anterior señalaba varias técnicas pra utilizar CSS para maquetar una página web. Una de esas técnicas implica manipular una lista para mostrarse horizontalmente en lugar de verticalmente.

En este artículo, demostraré como utilizar CSS para controlar las indomables listas. Ya es hora de que les digar a las listas como comportarse, en lugar de dejarlas libres haciendo lo que quieran en tu página web.

Preparación

En este artículo voy a utilizar listas no ordenadas. El mismo CSS se podría aplicar también, con resultados similares, a listas ordenadas. A menos que se indique otra cosa, todos los ejemplos en este artículo utilizan este código para las listas.

<ul>
	<li>Item 1</li>
	<li>Item 2</li>

	<li>Item 3</li>
	<li>Item 4</li>
	<li>Item 5 we'll make a bit longer so
	    that it will wrap</li>
</ul>

Cada lista se coloca dentro de un diferente DIV, y se redacta un CSS para que el comportamiento de la lista esté determinado por el contenedor en el que está. Cada DIV tiene una regla básica:

#base {
	border: 1px solid #000;
	margin: 2em;
	width: 10em;
	padding: 5px;
	}

Sin otros estilos adicionales, la lista se muestra de este modo en el DIV básico:

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5 we'll make a bit longer so that it will wrap

Posicionamiento

A veces el sangrado por defecto de una lista es demasiado grande para el diseño en el que trabajas. Pero simplemente cambiando el margen o el espaciado de la UL no funciona para todos los programas navegadores. Para hacer que la lista se ajustea la izquierda, por ejemplo, deben cambiarse tanto el margen como el espaciado (padding). Esto se debe a que Internet Explorer y Opera optan por crear el sangrado con el margen izquierdo, mientras que Mozilla/Netscape utilizan espaciado. Más información en el artículo de DevEdge Consistent List Indentation.

En el siguiente ejemplo tanto el margen izquierdo, margin-left y el espaciado izquierdo, padding-left de la UL en el DIV se establecen como cero:

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5 we'll make a bit longer so that it will wrap

Fijémonos que los marcadores ahora están fuera del DIV. Si la caja contenedora fuera el BODY del documento HTML document,los marcadores se desplazarían fuera de la ventana del navegador, haciéndose invisibles. Si quieres que los marcadors estén alineados dentro del, pero en su parte izquierda, indica que tanto el margen como el espaciado son de un em:

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5 we'll make a bit longer so that it will wrap

Marcadores

Tal vez has requerido un marcador específico para algún proyecto. Su es así, puedes haberlo codificado en una tabla con una columna que contiene imágenes GIF como marcadores alineados arriba y a la derecha, y la otra columna conteniendo lo que deberían haber sido LIs. Con CSS es posible utilizar una imagen como marcador de lista. Si el navegador no reconoce esta arte de CSS (o no representa imágenes), se empleará el punto por defecto (o puedes especificar un marcador en HTML diferente, si lo deseas).

La regla es algo parecido a:

ul {
	list-style-image: url(bullet.gif);
	}

Y el navegador lo muestra como:

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5 we'll make a bit longer so that it will wrap

Para especificar un marcador en html que se emplee si el navegador no reconoce esta parte de CSS, añade:

	list-style-type: disc;

a la regla. Dependiendo de la imagen que hayas elegido puede suceder que no quede alineada con los ítems de la lista de la manera que desearías. En este caso puedes colocar la imagen dentro del bloque de los ítems de la lista (en lugar de fuera de la lista) Añade lo siguiente:

	list-style-position: inside;

a la regla y se producirá el cambio. Estas tres declaraciones se pueden combinar en una sola, resumida, como se ilustra en la regla siguiente:


ul {
	list-style: disc url(bullet.gif) inside;
	}

que equivale a:

ul {
	list-style-type: disc;
	list-style-image: url(bullet.gif);
	list-style-position: inside;
	}

Así es como aparece en la página web:

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5 we'll make a bit longer so that it will wrap

A veces tienes una lista en la que no quieres marcadores en forma de punto, o quieres utilizar algún otro tipo de carácter en lugar de un círculo. De nuevo, las CSS nos proporcionan una solución rápida. Simplemente añade list-style: none; a la regla y forzará a los LIs a mostrar un sangrado en las líneas, sin marcadores. La regla es así:

ul {
	list-style: none;
	margin-left: 0;
	padding-left: 1em;
	text-indent: -1em;
	}

Debe especificarse que bien el margen o bien el espaciado es cero, y el otro con un valor de 1em. Dependiendo del “marcador” que elijas, puedes modificar este valor. el sangrado negativo, con text-indent hace que la primera línea se mueva hacia la izquierda con un valor como el indicado, creando una sangría francesa.

El HTML contiene nuestra lista estándar, UL, pero con cualquier carácter o entidad de HTML que quieras utilizar en lugar del círculo precediendo el contenido de los elementos de la lista. En nuestro caso utilizaremos &#187;, la comilla doble angular derecha: ».

  • » Item 1
  • » Item 2
  • » Item 3
  • » Item 4
  • » Item 5 we'll make a bit longer so that it will wrap

Debería añadir que Netscape6/7/Mozilla (y otros navegadores basados en Gecko) y Opera pueden crear contenido generado mediante el pseudo-elemento de CSS2 :before. Podemos aprovecharlo para generar automáticamente el carácter » (o cualquier otro carácter) para los marcadores. Esto nos permite dejar el contenido de las listas aislado. Si utilizas Opera o un navegador basado en Gecko, el CSS que sigue creará la misma lista que antes, pero utilizando el UL estándar sin contenido extra:

#custom-gen ul li:before {
	content: "\00BB \0020";
	}

La propiedad content puede contener texto, URIs y otros, incluyend caracteres especiales. cuando utilices estos caracteres, como », es necesario codificarlos como sus valores HEX equivalentes. Para la comilla doble derecha, utilizamos \00BB (el otro carácter,\0020, es un espacio). El resultado final (recuerda que el carácter sólo será visible en Opera o Mozilla/Netscape):

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5 we'll make a bit longer so that it will wrap

Listas horizontales auténticas

¿Quién dice que una lista debe estar dispuesta verticalmente, alineada con círculos en la parte izquierda de cada elemento? Quizá deseas tener la estructura de una lista ordenada de enlaces, pero visualmente quieres que parezca una barra de navegación vertical en la página. O quizá quieres que los enlaces se dispongan horizontalmente en la parte superior de la página.

Esto se puede aplicar a más situaciones que a las listas de enlaces. A veces necesitarías listar varios elementos en medio de un párrafo; tal vez una lista de libros que quieres leer. Estructuralmente tiene sentido codificar esto como una lista, pero en presentación no deseas romper el flujo del párrafo. ¡CSS al rescate de nuevo!

Puesto que esta lista no se separará del resto del párrafo, no la colocaré dentro del DIV de base que hemos utilizado en las listas previas. Esta vez, el código es el de un párrafo, seguido de la misma lista, que a su vez continúa con otro párrafo.

Te oigo protestar“¡TRAMPA! Creí que ibas a colocar una lista dentro de un párrafo, no entre dos párrafos.”

A lo que voy a contestar que “Bueno, sí. Perot el (X)HTML no permite que una lista aparezca dentro de un párrafo. Sin embargo, con la ayuda de nuestra hoja de estilos, es así como se mostrará en la página web.”

Los estilos necesarios son:

#inline-list {
	border: 1px solid #000;
	margin: 2em;
	width: 80%;
	padding: 5px;
	font-family: Verdana, sans-serif;
	}

#inline-list p {
	display: inline;
	}

#inline-list ul, #inline-list li {
	display: inline;
	margin: 0;
	padding: 0;
	color: #339;
	font-weight: bold;
	}

El marcado consiste en un <div id="inline-list">. Este DIV contiene un párrafo seguido de nuestra UL corriente, y un segundo párrafo a continuación. La lista UL list se ha modificado de manera que cada elemento de la lista tiene una coma detrás, con el último elemento seguido por un punto.

Los resultados son los siguientes (la lista aparece en color azul):

Un poco de texto aparece antes de la lista. Tal vez el contexto trata de un marido que recibe una llamada de su esposa para que compre algunas cosas al volver a casa. Realmente no importa, para nuestros propósitos solo necesitamos algo de texto antes de la lista:

  • Item 1,
  • Item 2,
  • Item 3,
  • Item 4,
  • Item 5 we'll make a bit longer so that it will wrap.

Y este es el texto que sigue a la lista. Una o dos frases son suficientes para este ejemplo.

Como en el ejemplo de los marcadores a medida, podríamos utilizar CSS para generar automáticamente las comas y punto después de cada ítem. Si tan sólo tuvieras que ocuparte de Opera y los navegadores de Gecko, sería ideal. En este caso, los estilos serían:


#inline-list-gen ul li:after {
	content: ", ";
	}
		
#inline-list-gen ul li.last:after {
	content: ". ";
	}

Aquí podemos utilizar el pseudo-elemento :after para añadir una coma detrás de cada elemento, y un punto detrás del ítem que tiene la clase class="last" (último), y resultará lo siguiente (recuerda de nuevo, sólo es visible en Opera or Mozilla/Netscape):

Un poco de texto aparece antes de la lista. Tal vez el contexto trata de un marido que recibe una llamada de su esposa para que compre algunas cosas al volver a casa. Realmente no importa, para nuestros propósitos solo necesitamos algo de texto antes de la lista:

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5 we'll make a bit longer so that it will wrap

Y este es el texto que sigue a la lista. Una o dos frases son suficientes para este ejemplo.

Navegación

Como ya mencioné antes, los menús de enlaces que aparecen en casi cada sitio web deberían codificarse como listas, puesto que eso es lo que son. Ya que no queremos el estilo por defecto de las listas en estas listas, podemos utilizar CSS para modificar el aspecto con el que se muestran en la página. Como vimos antes, se puede forzar las listas a disponerse horizontalmente (inline) en lugar de verticalmente (el comportamiento por defecto). Al hacer esto, el círculo marcador desaparece y tienes muchas opciones a la hora de separar los elementos de la lista.

Estos ejemplos de listas horizontales utilizan en cada caso el mismo DIV, con los estilos siguientes:

#h-contain {
	padding: 5px;
	border: 1px solid #000;
	margin-bottom: 25px;
	}

Los dos ejemplos siguientes utilizan la misma UL de los ejemplos anteriores, pero sin el ítem final de la lista con su texto extra También incluirán una clase adidiconal que separa uno de los LI de esta lista.

Bordes

Un carácter de barra vertical, |, se emplea con frecuencia para separar las diferentes opciones. Es un carácter separador bastante obvio, y puede emularse añadiendo bordes a los elementos de lista:

#pipe ul {
	margin-left: 0;
	padding-left: 0;
	display: inline;
	} 

#pipe ul li {
	margin-left: 0;
	padding: 3px 15px;
	border-left: 1px solid #000;
	list-style: none;
	display: inline;
	}
	
		
#pipe ul li.first {
	margin-left: 0;
	border-left: none;
	list-style: none;
	display: inline;
	}

Aquí añadimos class="first" al primer LI de manera que no acabe con un borde en su parte izquierda.

  • Item 1
  • Item 2
  • Item 3
  • Item 4

Puedes modificar estos estilos para crear fácilmente un efecto de navegación con pestañas:

#tabs ul {
	margin-left: 0;
	padding-left: 0;
	display: inline;
	} 

#tabs ul li {
	margin-left: 0;
	margin-bottom: 0;
	padding: 2px 15px 5px;
	border: 1px solid #000;
	list-style: none;
	display: inline;
	}
	
		
#tabs ul li.here {
	border-bottom: 1px solid #ffc;
	list-style: none;
	display: inline;
	}
  • Item 1
  • Item 2
  • Item 3
  • Item 4

En este ejemplo, añadiendo class="here" a un LI crea un borde en la parte inferior que concuerda con el color de fondo para indicar que la pestaña se refiere a la página actual.

Nota: Esta técnica fue propuesta en primer lugar por Randal Rust, y desarrollada por muchos otros en la lista de correo css-discuss.

Secuencias de navegación

Otra lista de enlaces que típicamente tiene una orientación horizontal en una página es lo que se llama breadcrumbing, o migas de pan (una secuencia de navegación.) Nos muestra dónde estamos en la jerarquía del sitio, partiendo de la página principal, y pasando a través de las secciones hasta la sección actual o la página en que estamos. Si quieres que este código sea realmente significativo, deberías crearlo como una serie de listas anidadas, ya que cada sección es parte de la sección precedente:

<div id="bread">
<ul>
	<li class="first">Home
	<ul>

		<li>&#187; Products
		<ul>
			<li>&#187; Computers
			<ul>
				<li>&#187; Software</li>
			</ul></li>

		</ul></li>
	</ul></li>
</ul>
</div>

crea lo siguiente:

  • Home
    • » Products
      • » Computers
        • » Software

Añadiendo las siguientes reglas a la hoja de estilo para la página:

#bread {
	color: #ccc;
	background-color: #006;
	padding: 3px;
	margin-bottom: 25px;
	}

#bread ul {
	margin-left: 0;
	padding-left: 0;
	display: inline;
	border: none;
	} 

#bread ul li {
	margin-left: 0;
	padding-left: 2px;
	border: none;
	list-style: none;
	display: inline;
	}

consigue:

  • Home
    • » Products
      • » Computers
        • » Software

De nuevo, podemos generar el carácter » (o cualquier otro carácter que queramos usar como separador) con el pseudo-elemento :before, en combinación con una clase del tipo class="first" para que el primer LI no genere un separador:

#bread-gen ul li:before {
	content: "\0020 \0020 \0020 \00BB \0020";
	color: #ff9;
	}
	
#bread-gen ul li.first:before {
	content: " ";
	}

Y el resultado final es:

  • Home
    • Products
      • Computers
        • Software

En el mundo real

Me gustaría terminar con una aplicación en el mundo real de algunas de las técnicas que hemos tratado aquí. Utilizaremos una lista corriente UL que contiene enlaces para crear un menú dinámico con efectos de realce al pasar por encima. Para conseguir este efecto necesitamos que la lista UL proporcione la estructura, y los estilos de los enlaces proporcionarán la mayor parte de los efectos visuales.

Este menú de enlaces es realmente una solución a un problema planteado por Michael Efford en la lista de correo css-discuss. Michael ha creado este mismo efecto utilizando una tabla, imágenes y JavaScript. Michael planteó si se podría hacer con CSS. Acepté el reto, y con la ayuda de otros participantes que resolvieron algunos problemas específicos de diferentes navegadores, conseguimos una hoja de estilo que funciona en este código:

<div id="button">

<ul>
	<li><a href="#">Home</a></li>
	<li><a href="#">Hidden Cameras</a></li>
	<li><a href="#">CCTV Cameras</a></li>

	<li><a href="#">Employee Theft</a></li>
	<li><a href="#">Helpful Hints</a></li>
	<li><a href="#">F.A.Q</a></li>

	<li><a href="#">About Us</a></li>
	<li><a href="#">Contact Us</a></li>
</ul>
</div>

Echemos un vistazo a la hoja de estilo regla a regla, y explicaré por qué cada regla se ha construído de la manera en que está.

#button {
	width: 12em;
	border-right: 1px solid #000;
	padding: 0 0 1em 0;
	margin-bottom: 1em;
	font-family: 'Trebuchet MS', 'Lucida Grande',
	  Verdana, Lucida, Geneva, Helvetica, 
	  Arial, sans-serif;
	background-color: #90bade;
	color: #333;
	}

La primera regla es para el DIV#button. Define el espacio que el menú ocupa y proporciona un contexto para el menú de manera que podamos especificar de qué manera se comportará la lista y los enlaces dentro de este DIV. Elegí hacer el menú fluído, basado en las preferencias del tamaño de fuente del navegador, así que (casi) todas las unidades están en ems. Esto incluye el ancho del menú. El borde sólido y negro a la derecha está basado en la versión original de Michael. El espaciado inferior permite ampliar el DIV hacia abajo, más allá del menú de enlaces para que se pueda ver el fondo del DIV. Nuevamente, esto sigue el diseño original. El margen inferior permite separar el DIV de lo que le sigue. Los colores son los del diseño original.

	#button ul {
		list-style: none;
		margin: 0;
		padding: 0;
		border: none;
		}
		
	#button li {
		border-bottom: 1px solid #90bade;
		margin: 0;
		}

Después definí cómo se mostraría la lista. Ya que todos los elementos de la lista han de ser enlaces, y la funcionalidad de rollover estaría integrada en el CSS, esencialmente eliminé todo el estilo de las listas. Añadí un borde de un pixel en la parte inferior de cada enlace que concordaba con el fondo del DIV #button, para actuar como separador. En el diseño original, éste era una imagen.


	#button li a {
		display: block;
		padding: 5px 5px 5px 0.5em;
		border-left: 10px solid #1958b7;
		border-right: 10px solid #508fc4;
		background-color: #2175bc;
		color: #fff;
		text-decoration: none;
		width: 100%;
		}

	html>body #button li a {
		width: auto;
		}

	#button li a:hover {
		border-left: 10px solid #1c64d1;
		border-right: 10px solid #5ba3e0;
		background-color: #2586d7;
		color: #fff;
		}

Finalmente, defniní los enlaces. El diseño original tiene bordes de 10 píxeles a derecha e izquierda. Estos bordes, junto con el fondo, cambian de color al pasar el ratón. Esto es fácil de controlar con la pseudo-clase :hoverde CSS, así que la incluí en los enlaces.

Hay un problema a resolver en esta parte de la hoja de estilos. Para que los enlaces sean activos en todo el ancho del DIV, los hice display: block;. Esto funciona perfectamente, excepto en IE/Windows. Si das al bloque un valor explícito de ancho del 100%, entonces IE/Windows funciona. Pero al hacer esto, surgen problemas con IE5/Mac y Netscape/Mozilla. Así que usé el selector hijo (child) “>” para redefinir el ancho a auto. Puesto que IE/Windows no entiende selectores hijos, ignora la regla. IE5/Mac, Opera y Netscape/Mozilla siguen la regla y así todos quedan contentos.

La regla para la pseudo-clase :hover crea lo cambios de color en fondo y borde cuando se pasa el ratón sobre los enlaces.

El estilo y el código de la lista (más o menos 1K) reemplaza aproximadamente 5K de JavaScript y TABLE, por no mencionar otros 8K de imágenes para los efectos de rollover. Además, el código se hace mucho más fácil de editar y mantener, ya que no necesitas crear nuevas imágenes si el nombre de un enlace cambia. Puedes ver el resultado final en el contexto del sitio en Asset Surveillance.

La punta del Iceberg

Lo creas o no, sólo hemos arañado la superficie de lo que se puede hacer para modificar las listas con hojas de estilo. No mantendré que todas las técnicas presentadas aquí sean el CSS más práctico que te puedas encontrar, pero sí espero que te hagan pensar en que utilizando CSS puedes conseguir un código mucho más estructurado.

Mark Newhouse tiene un blog engnuhaus.com, trabaja en noao.edu, y participa en realworldstyle.com.

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