lunes, 11 de abril de 2011

ESPECIFICIDAD CSS

Seguimos con la serie de post sobre CSS.

Después de un primero (donde se habló de DOCTYPE) y de un segundo (donde se habló de la herencia y la cascada), ahora toca abordar un tercero que pretendo sea preludio de un gran final que nos lleve a saber un poco más de CSS.

DÓNDE ESCRIBIR CSS

Antes de escribir CSS lo primero es saber dónde podemos escribir CSS (genial, eh?).

Podemos incluir código CSS en nuestros diseños de las siguientes formas:

  • Hoja de estilos externa.
  • En el propio documento.
  • En el propio elemento.

La hoja de estilos externa hace mención a un fichero .css que se inserta en la página con la etiqueta <link>, dentro de la etiqueta <head>.

<link href="MiHoja.css" rel="stylesheet" type="text/css" />

En el propio documento hace mención a la etiqueta <style>, también dentro de la etiqueta <head>.

<style type="text/css">

/* Código CSS*/

</style>

Aquí aprovecho para decir que los comentarios CSS existen, que pueden ser multi-línea y que no sale urticaria por utilizarlos. Aunque también te digo que si tu código .css es 80% comentarios, 20% código, tampoco es cuestión de hincharse.


Por último, en el propio elemento (también llamada “en línea”) es aplicar estilos a través de la propiedad style de cualquier etiqueta.

<div id="Div1_1" style="color: Yellow;"></div>

Cada una de estas formas tiene sus ventajas y desventajas, pero a grandes rasgos podríamos decir lo siguiente:

 

  • Hoja de estilos externa.
    • Reutilizable entre distintas páginas.
    • Favorece los mecanismos de caché del navegador.
    • Minimiza el tamaño de la página.
  • En el propio documento.
    • Sólo para la página actual.
    • Normalmente se utiliza cuando nuestro código CSS es para una sola página y no se piensa reutilizar.
  • En el propio elemento.
    • Sólo para el elemento actual.
    • Se podría utilizar para estilos muy concretos un solo elemento, pero se desaconseja su uso ya que va en contra de la separación entre diseño y contenido que promueve justamente CSS.
    • Podría resultar útil si estamos utilizando un lenguaje de programación como ASP.NET, para combinar desde el código de servidor nuestro HTML con CSS.

 

Aunque no se ha desaconsejado “en el propio documento”, lo cierto es que la opción más habitual y que mejor resultará casi siempre es una “hoja de estilos externa”. Esta es la forma que recomienda la w3c y es la que más favorece la separación total entre diseño y contenido (piensa que si cambia algo del fichero .css no tienes porqué tocar tus ficheros de contenido).

Al igual que sucedía con las hojas de estilo del navegador, usuario y autor, también el orden en el que aparecen nuestros estilos es relevante a la hora de aplicar la cascada.

Se considera lo más cercano definir CSS en el propio elemento, después estilos definidos en el propio documento y una hoja de estilos externa tiene el mismo peso.

Además, en caso de que existan varias reglas que definan un mismo estilo para un mismo elemento, prevalecerá la más cercana y por más cercana entendemos la que aparece por último en nuestro código. Veamos un ejemplo:

Tenemos una primera hoja de estilos externa “MiHoja.css” con el código:

#Div1 { color: Red; }

Tenemos una segunda hoja de estilos externa “MiOtraHoja.css” con el código:

#Div1 { color: Olive; }

Además, tenemos definido en el propio documento 2 bloques de código CSS:

<style type="text/css">

#Div1 { color: Brown; }

</style>

 

<style type="text/css">

#Div1 { color: Blue; }

</style>

Por último, también tenemos definido un estilo en línea para el elemento:


<div id="Div1" style="color: Green;">Texto de ejemplo</div>

 

El código final es:

<html>

<head>

<link href="MiHoja.css" rel="stylesheet" type="text/css" />

<link href="MiOtraHoja.css" rel="stylesheet" type="text/css" />

<style type="text/css">

#Div1{color: Brown; }

</style>

<style type="text/css">

#Div1{color: Blue; }

</style>

</head>

<body>

<div id="Div1" style="color: Green;">Texto de ejemplo</div>

</body>

</html>

Si ahora vemos con Firebug las reglas aplicadas podemos ver que primero se aplicaron las hojas externas en orden de aparición, después los estilos del documento también orden de aparición y por último la regla en línea, que es la que ganó y se aplicó al elemento:

 

clip_image001

Sin embargo, ahora vamos a hacer unos pequeños cambios. Eliminar el estilo en línea del elemento, y cambiar el orden en que aparecen las hojas de estilo externas y los bloques de código CSS del propio documento.

<link href="MiHoja.css" rel="stylesheet" type="text/css" />

<style type="text/css">

#Div1 { color: Brown; }

</style>

<style type="text/css">

#Div1 { color: Blue; }

</style>

<link href="MiOtraHoja.css" rel="stylesheet" type="text/css" />


clip_image002

Como vemos, se han aplicado los estilos en el siguiente orden:

  • MiHoja.css
  • Primer bloque de código en el propio documento
  • Segundo bloque de código en el propio documento
  • MiOtraHoja.css

Otro punto que nunca he tenido claro cuando hablo de CSS es la instrucción @import. Es decir, para mí sólo existía la etiqueta <link> para enlazar a hojas de estilos externas, pero… no, amigo! Existe también @import!

La instrucción @import permite importar hojas de estilo dentro de otras hojas de estilos, una forma más de compartir.

La forma de utilizar esta instrucción es incluyendo una etiqueta <style> y la instrucción @import como primera instrucción del bloque o bien incluir la sentencia dentro de una hoja de estilos .css

<style type="text/css">

@import "MiHoja.css";

#Div1 { color: Brown; }

</style>

En cualquier caso, @import no parece una instrucción muy utilizada hoy en día. La w3c no la utiliza y además hay posts que hablan sobre sus inconvenientes.

REGLAS CSS

Llevamos varios post hablando sobre las reglas CSS. Aunque no es el propósito de estos post, por lo menos daremos una breve guía sobre cómo hacer una regla y después ya sí nos meteremos con los distintos selectores.

Una regla CSS consta de:

·         Selector

·         Atributo

·         Valor

Por ejemplo, para:

#Div1 { color: Blue; }

·         #Div1 es el selector.

·         color es la propiedad.

·         Blue es el valor.

De propiedades y valores no voy a hablar porque ese será otro post, pero los selectores son una parte importantísima de CSS y merece la pena invertir algo de tiempo en su estudio.

Los selectores son una parte básica del CSS y tiene que manejarse con soltura. Con un selector estamos decidiendo sobre qué elementos queremos aplicar nuestro código CSS… y te aseguro que en páginas de mediana o gran envergadura no tener claro este concepto te llevará a la ruina.

No son todos los que son, pero sí todos lo que están.

Tipo

Ejemplo

Notas

Universal

*

Todos los elementos

Etiqueta

p

Todos los párrafos (p)

Clase

.NombreClase

Todos los elementos con class=”NombreClase”

Id

#Identificador

Elemento con id=”Identificador”

Descendente

p a

Todos los elementos a que sean descendientes (da igual que sean hijos, nietos, etc.) de elementos p

Hijo

p > a

Todos los elementos a que sean hijos de elementos p

Hermanos adyacentes

p + a

Todos los elementos a que sean hijos adyacentes de elementos p

Primer hijo

P:first-child

Todos los elementos p que son el primer hijo de su padre.

 

a:link

Enlace aún no visitado.

 

a:visited

Enlace visitado.

Activo

a:active

Elemento activo (por norma suele ser a)

Foco

p:focus

Elementos de tipo p con el foco tomado

Sobre

p:hover

Elementos de tipo p sobre el que el usuario tiene el ratón encima.

Atributo establecido

P[atributo]

Todos los elementos p que tiene su atributo “atributo” establecido a cualquier valor.

Atributo a un valor concreto

P[atributo=’Valor’]

Todos los elementos p que tiene su atributo “atributo” establecido a “Valor”.

:first-letter

   

:fisrt-line

   

:before

   

:after

   


Si quieres saber la compatibilidad de los selectores en los navegadores actuales,
aquí hay una lista actualizada que debería ser documento de referencia

Además, para una lista actualizada de selectores, puedes visitar la especificación de CSS2 y la especificación de CSS3.

Los selectores permiten agrupar. De este modo, si tenemos 2 o más selectores que establecen las mismas propiedades podemos agruparlos separando los selectores con la coma. Por ejemplo:

.Estilo1 { color: Red; }

.Estilo2 { color: Red; }

Se podría escribir como

 

.Estilo1, .Estilo2 { color: Red; }

Y por ejemplo:

.Estilo1 { color: Red; font-size: 12px; }

.Estilo2 { color: Red; font-size: 24px; }


Se podría escribir como:

.Estilo1, .Estilo2 { color: Red; }

.Estilo1 { font-size: 12px; }

.Estilo2 { font-size: 24px; }


En cualquier caso, la agrupación de selectores es un asunto de sentido común y sólo la experiencia nos servirá para llenar a un acuerdo que nos satisfaga.

Otro asunto importante a propósito de los selectores es que se pueden anidar.

Finalmente una regla sólo afectará a un tipo de elemento (sin contar con la agrupación, claro está), pero para marcar el camino hasta esos tipos de elementos podemos anidar selectores que “dibujen” el camino de forma más precisa. Por ejemplo: DIV P#Parrafo1, en realidad quiere decir elementos con el atributo id igual a “Parrafo1” que además sean del tipo P y que además sean descendientes de elementos de tipo DIV. Ahora sólo es cuestión de imaginar el resto y complicar como queremos nuestros selectores.

¿CÓMO SE APLICAN LAS REGLAS?

Cuando creamos un selector, lo ideal es ser lo suficientemente y mínimamente específico para alcanzar el elemento deseado al queremos aplicar el estilo pero sin caer en escribir todo la ruta al elemento, lo que haría que su mantenimiento posterior fuera más complicado además de que después podremos tener problemas con la especificidad (no te preocupes si ahora no sabes qué es esto, it’s coming...).

Si por ejemplo leo DIV P#Parrafo1 asumo que se ha puesto antes DIV P porque probablemente podría haber un elemento con id=”Parrafo1” y que no fuera del tipo P, o si lo fuera, no tuviera un padre DIV. Si no hubiera contemplado estos casos, debería haber escrito simplemente #Parrafo1.La conclusión de todo esto es: Utiliza siempre la mínima profundidad necesaria para seleccionar el elemento y evita en la medida de lo posible !important (estas 2 reglas te harán la vida más sencilla a la hora de calcular la especificidad).

Ahora ya estamos llegando a una de las grandes verdades de CSS. De las “cienes” y “cienes” de reglas que se aplican a mi elemento ¿Cuál de ellas se aplicará? ¿Cuál será el resultado final?.

Espero que te acuerdes que las reglas podían venir de la hoja de estilos del navegador, del usuario, también del autor, podían ser en línea, en el propio documento o en una hoja externa, además también era importante su orden de aparición Por otro lado un selector podría ser por id, otro alcanzar el elemento por tipo de etiqueta, otro por ser hijo de, otro más por ser descendiente de… uff! Basta!, está claro que un elemento HTML puede recibir una cantidad ingente de información relativa al CSS que le afecta, luego tiene que haber unas reglas muy precisas para saber qué valor aplicar finalmente al elemento… y eso se le llama especificidad.

Primero unos enlaces por si mi explicación no te satisface:

http://www.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/

http://css-tricks.com/specifics-on-css-specificity/

La especificidad es la regla interna que usa CSS para saber que selector tiene que usar”. Es decir, ante múltiples selectores que aplican estilos a un elemento, el selector con coeficiente de especificidad mayor es el que aplica su estilo” (Frase extraída del libro “CSS” de Xavier Colomés Fornós)

Para calcular la especificidad se cuenta:

  • Nº de atributos id en el selector
  • Nº de atributos class en el selector
  • Nº de nombres de etiquetas en el selector

Después se suma el número y se obtiene el valor de especificidad.

Fuera de éste cálculo queda el atributo style del elemento, que siempre prevalece (tiene una especificidad simulada de 1000).

Veamos algunos ejemplos:

 

Nº ID

100

Nº CLASS

10

Nº TAG

1

ESPECIFICIDAD

DIV

1

1

#Div1

100

   

100

DIV #Div1

100

1

101

.MiClase

 

10

 

10

P.MiClase

 

10

1

11

#Parrafo1

100

 

 

100

P#Parrafo1

100

 

1

101

DIV P#Parrafo1

100

 

2

102


Puedes descargar una cheatsheet de especifidad desde http://www.vcarrer.com/2009/09/css-specificity-cheat-sheet.html o incluso utilizar una calculadora on-line desde http://josh.github.com/css-explain/

Es por estas reglas que cuando vemos código como el siguiente nos cuesta entender por qué el párrafo no es rojo y sin embargo es azul (aunque haya sido definido después). Esto es porque p.Parrafo vale 11 y P vale 1.

Como se puede observar la norma es que siempre prevalece lo más específico sobre lo más general (y es por ello que se recomienda que nuestro selectores sean los menos específicos posibles, esto es que usen la mínima profundidad necesaria para seleccionar el elemento deseado).

p.Parrafo { color: Blue; }

p { color: Red; }

 

clip_image003

Ya como colofón a esta serie de posts (que aunque quedan unos pocos por hoy basta), repasemos todas las reglas que aplica CSS para aplicar estilo a los elementos:

  • Encontrar todos los selectores que afectan al elemento.
    En caso de no haber ninguno se busca por valores heredados, y en caso de no haber ninguno valor heredado se establece el valor inicial de la propiedad (según la especificación de la propiedad).
  • Se ordenan las reglas por origen (de menos a más).
    • Navegador.
    • Usuario.
    • Creador.
  • Se ordenan las reglas por especificidad
    (según el cálculo expuesto).
  • En caso de que aún haya ambigüedad sobre que regla aplicar, se ordenan las reglas por orden de aparición. Recuerdo que la última regla especificada tiene más peso.
  • Se aplica la regla.

Bueno, lo cierto es que hoy me quedo muy satisfecho con lo aquí visto. Yo no sé tú, pero yo hace unas semanas no sabía lo que era la especificidad y hasta que hemos llegado han pasado unos cuantos posts que creo han merecido la pena.

Un saludo!

No hay comentarios:

Publicar un comentario