mozilla

CSS dinámico

Introducción

Tradicionalmente las páginas web se han dividido en dos categorías: estáticas y dinámicas. Hemos leído muchas veces que con XHTML y CSS se pueden crear documentos de calidad, pero fijos, estáticos. Si quieres que tus páginas se adapten y cambien según las acciones del usuario, si quieres dinamismo, necesitas javascript o similares... Ya no.

Si teniamos DHTML (html dinámico), ahora tenemos CDSS (Css Dinámico Sin Scripts). Como en un cuento de hadas en el que un humilde sapo acaba siendo el príncipe de la historia, unas modestas pseudo-clases pueden acabar siendo las estrellas de la Web.

Las pseudo-clases en principio nacieron para darle dinamismo a los enlaces, y este es el uso que se les ha dado durante los últimos años. Es raro el archivo CSS que no incluya unas líneas semejantes a estas:

a:link { ... }
a:active { ... } 
a:visited { ... }

¡Pero la situación ha cambiado! Ahora podemos aplicarle pseudo-clases a la mayoría de los elementos, y jugando con los selectores podemos crear documentos dinámicos usando exclusivamente CSS.

Poco a poco

Lo veremos poco a poco y por medio de ejemplos centrados en la pseudo-clase :hover. Obviamente combinando diversas pseudo-clases pueden obtenerse efectos más complejos. Para probar los ejemplos basta copiar y pegar el código (sin quitar ni añadir nada) en un archivo vacio y visualizarlo con el navegador.

Empecemos por el uso tradicional:

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

a:hover { color: red; }

</style>

<p> Párrafo con <a>enlace</a> que se pone rojo </p>

Soltamos amarras, levamos 'anclas' y...

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

p:hover { color: red; font-variant: small-caps; }
li:hover { color: blue; background: silver; }  
div:hover { color: orange; text-align: right; }

</style>

<p> Párrafo que se pone rojo y mayúsculo. </p>
<ul> <li> Item que se pone azul y con fondo gris. </li> </ul>
<div> División con texto que se flota a la derecha y se pone naranja. </div> 

Esto nos permite crear con facilidad efectos dinámicos, podemos cambiar la visualización de las cosas dependiendo de los actos del usuario. Con un poco de imaginación y buen gusto se pueden hacer maravillas.

La cosa da mucho juego

Podemos cambiar cualquier propiedad, pero no todas son igual de útiles a la hora de crear dinamismo. Algunas de las más interesantes serían por ejemplo: display, position, z-index...

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

.comun { position: absolute; width: 10em; 
	 padding: 2em; text-align: center; }

#rojo { background-color: red;
        left: 1em; top: 1em; 
        z-index: 1; }

#azul { background-color: blue;
        left: 5em; top: 5em; 
        z-index: 2; }

#naranja { background-color: orange;
           left: 9em; top: 2em; 
           z-index: 3; }

#rojo:hover,
#azul:hover,
#naranja:hover { z-index: 4; }

</style>

<p id='rojo'    class='comun'>El rojo es vivo</p>
<p id='azul'    class='comun'>El azul es elegante</p>
<p id='naranja' class='comun'>El naranja es guay</p>

Pero esto no es todo, aún hay más.

Jugando con los selectores podemos relacionar unos elementos con otros.

Por ejemplo: al posicionarnos sobre p cambiamos las propiedades de a, y al posicionarnos sobre a cambiamos las propiedades de em.

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

em { display: none; }

p:hover a { color: red; }
a:hover em { display: inline; }

</style>

<p> Párrafo <a>con enlace <em>que se pone rojo</em> </a> </p>

Bueno, despues de unos ejemplos simples, uno un poco más complejo:

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'> 

.editorial { width: 30%;} 
.item { list-style: none; list-style-position: inside; 
        padding: 0.2ex; margin: 0.2ex; } 

a { color: darkblue; text-decoration: none;} 
div:hover a { color: blue; text-decoration: underline;} 

.oculto ul { display: none; } 
div:hover ul { display: block; }

ul { border: transparent solid 0.1ex; } 
ul:hover { border: peru solid 0.1ex; } 

ul:hover abbr,
ul:hover dfn { color: red; } 
 
.vista { visibility: hidden; } 
ul:hover .vista { visibility: visible; } 

</style> 

<div class='editorial oculto'> 
   <h2> <a> CSS </a> </h2> 
   <ul class='item'> 
      <li> <dfn>CSS</dfn> es una c seguida de dos eses. </li> 
      <li> También es un estándar del <abbr>W3C</abbr>. </li> 
      <li class='vista'> No se me ocurre qué poner aquí. </li>
   </ul> 
   
</div> 

<div class='editorial'> 
   <h2> <a> HTML </a> </h2> 
   <ul class='item'> 
      <li> <dfn>HTML</dfn> es un lenguaje para el marcado de hipertextos. </li> 
      <li> Es un estándar del <abbr>W3C</abbr>. </li> 
      <li class='vista'> Creado por Tim Berners-Lee. </li> 
   </ul> 
</div>  

Tipos de relaciones familiares

Hasta el momento todos los ejemplos muestran relaciones padre → descendiente, si has consultado la especificación sabrás que no son las únicas, las posibilidades son las siguientes:

Padre → hijo

Esta relación se expresa por medio del combinador (">"), relaciona un elemento con sus descendientes directos. En el siguiente ejemplo seleccionamos los elementos con clase 'subrayado' que sean hijos directos de div

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

body:hover > .subrayado { text-decoration: underline;}

</style>

<div>
<p> Lo siguiente es una  
 <span class='subrayado'>cita</span>: 
</p>
<hr>
<blockquote class='subrayado'> <p>Si buscas resultados distintos, no hagas siempre lo mismo.  
 <cite>Einstein</cite> </p>
</blockquote>
</div>
Padre → descendiente

Esta relación se expresa por medio de un espacio en blanco (" ") relaciona un elemento con un descendiente. Este es el método más flexible, puedes seleccionar cualquier elemento independientemente del parentesco exacto.

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

     p:hover em { visibility: hidden;}

</style>

<h2> Selección de descendientes</h2>
<p> 
  <em>Este em es hijo de un párrafo</em> 
  <span> span tambien, pero...
     <em>Este em no es hijo de un párrafo, </em> 
     aunque sí descendiente (hijo de un hijo).
  </span> 
</p>
Hermano → hermano (adyacente)

Esta relación es expresa por medio del combinador ("+"), relaciona un elemento con su hermano adyacente (el inmediatamente siquiente). Este es el método aparentemente más limitado, pero el que abre más puertas.

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

#primero + li { list-style-type: none; }

</style>

<ul>
  <li id='primero'>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
</ul>


Esto de relacionar hermanos está muy bien, pero solo se puede seleccionar el adyacente, esto es una limitación importante, pero bueno, siempre puedes seleccionar el adyacente del adyacente, o el...

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

#primero + li + li + li { list-style-type: none; }

</style>

<ul>
  <li id='primero'>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
  <li>item 4</li>
</ul>
Otros parentescos

Padres, hijos y hermanos no son las únicas relaciones dentro de una familia. ¿Qué pasa si quiero seleccionar un nieto, o un sobrino? ¿Se puede?

Seleccionando un nieto
No tiene mayor complicación, al fin y al cabo, un nieto no es más que un hijo de un hijo.
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

p:hover > span > em { color: red; }

</style>

<p> 
 <em>este em es hijo de un párrafo</em> 
 <span> span también, pero...
   <em>este em es nieto</em> </span> 
</p>
Seleccionando un sobrino.
No hay problema, un sobrino no es más que un hijo de un hermano.
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

p:hover + div > em { color: red; }

</style>

<p>Al ponerte sobre este párrafo</p> 
<div> Cambias las propiedades de 
   <em>este em</em> 
</div>
Limitaciones

De los ejemplos anteriores se desprende que es muy fácil abarcar todas las combinaciones posibles. Siempre y cuando la secuencia de los selectores sea:

  1. Descendente - Un elemento y sus descendientes.
  2. Horizontal - Un elemento y sus hermanos.
  3. Mixta - Una combinación de las anteriores.

Lo que no se puede hacer es seleccionar un ascendiente (ej. un padre). Por lo tanto el siquiente ejemplo ni funciona ni debe hacerlo:

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

em:hover #div { color: red; }

</style>

<h1>Este ejemplo ni funciona ni debe hacerlo.</h1> 

<div id='div'> 
   <em>Este em</em> 
   no puede cambiar las propiedades de su padre.
</div>

Además hay una curiosa limitación ¿será un bug? Un selector compuesto puede empezar por un elemento o por un #id con :hover, Pero no puede empezar por una clase con :hover. Sorprendentemente con el selector universal (*) tampoco funciona.

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

* { color: red; }

  .uno       .cero { color: blue; }      /* esto sí funciona */
 *.uno       .cerocero { color: blue; }  /* esto sí funciona */

  #uno:hover .dos { color: blue; }       /* esto sí funciona */
ul.uno:hover .cuatro { color: blue; }    /* esto sí funciona */

  .uno:hover .tres { color: blue; }      /* esto NO funciona */
 *.uno:hover .cinco { color: blue; }     /* esto TAMPOCO funciona */

</style>

<div class='uno'>
  .uno       .cero { color: blue; }
  <em class='cero'>Esto sí funciona,</em> y... <br>
  *.uno       .cerocero { color: blue; }
  <em class='cerocero'>esto también funciona.</em> 
</div>

<ul id='uno' class='uno'>
  <li class='dos'>#uno:hover .dos - esto sí funciona.</li>
  <li class='tres'>.uno:hover .tres - esto NO funciona.</li>
  <li class='cuatro'>ul.uno:hover .cuatro - esto sí funciona.</li>
  <li class='cinco'>*.uno:hover .cinco - esto TAMPOCO funciona.</li>
</ul>

Los navegadores pueden dividirse en dos grupos: IE y el resto.

  • IE: IE6 no lo implementa, pero IE7 sí, aunque parece que sólo parcialmente... (probado en IE7 beta).
  • El resto: cada día son más los navegadores que implementan este uso de las pseudo-clases:
    • Firefox 1.5 - sí lo implementa, al igual que todos los navegadores basados en las últimas versiones de Gecko.
    • Opera - sí lo implementa (pendiente de confirmación plena).
    • Konqueror/Safari - sí lo implementa (pendiente de confirmación plena) al igual que todos los navegadores basados en las últimas versiones de KHTML.

Referencia

Lo cierto es que no hay mucho escrito sobre el tema (en castellano casi nada, o nada), la gente sólo suele escribir sobre las cosas que funcionan en IE. Pero tampoco hace mucha falta. Todo lo que necesitamos está en el estándar CSS-2. Además, curiosamente, los dos pilares que sostienen esta funcionalidad (pseudoclases y selectores), están explicados en la misma página: el capítulo 5.

Recomiendo encarecidamente la lectura completa y atenta de todo el capítulo, y ya puestos, de toda la especificación. Aunque para el asunto que nos ocupa nos interesan principalmente:

Sobre los selectores por parentesco, sub-capítulos: 5.5, 5.6, 5.7
Sobre las pseudo-clases, sub-capítulo: 5.11

CSS-3

Todo lo explicado es conforme a CSS-2.1 ¿Qué nos depara el futuro? Si los pilares de esta técnica son las pseudo-clases y los selectores, CSS-3 traerá muchas más pseudo-clases y muchos más selectores, en definitiva, muchas más posibilidades de hacer cosas interesantes.

Por ejemplo, hemos visto las limitaciones de CSS-2 para seleccionar hermanos, con CSS-3 esta limitación desaparece. Lo siguiente es CSS-3 pero funciona (usando el navegador apropiado).

<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>

.gracias { visibility: hidden; }

#primero:hover + .gracias { visibility: visible; }
#primero:hover ~ * span { color: red; } /* esto:'~' es CSS-3 */

</style>

<ul>
  <li id='primero'>Por favor, ponga el cursor encima de esta frase.</li>
  <li class='gracias'>Le doy las gracias con CSS-2.1</li>
  <li>Item normal y corriente</li>
  <li>El futuro: <span>span en rojo gracias a CSS-3</span></li>
</ul>

Notas finales

  • Sí, es cierto que con JavaScript o PHP pueden hacerse cosas mucho más avanzadas, pero aquí está la gracia del artículo, que sin necesidad de Javascript o PHP, solo con CSS, puede añadírsele mucho dinamismo a las páginas web.
  • Este artículo es sólo una introducción al tema, por razones didácticas los ejemplos son premeditadamente simples y limitados a una sola pseudo-clase (:hover). Puede que en el futuro exista un CSS Dinámico II que profundice más en el tema, muestre el uso de otras pseudo-clases y ejemplos más complejos.

Categorías

Etiquetas y colaboradores del documento

Etiquetas: 
Contributors to this page: Nukeador, RickieesES, Jorolo, Peperoni, Hande
Última actualización por: RickieesES,