Contenido

CSS: Entendiendo y aplicando los hacks

26 Dic

+ 41

¿Cuantas veces has tenido que aplicar hacks a tus CSS? Seguramente la respuesta a esta pregunta será «SIEMPRE», y esto se debe generalmente a las diferencias que hay entre los motores de los navegadores y en como renderizan el HTML y el CSS. Por ese motivo tenemos usar herramientas «poco ortodoxas» para conseguir que el aspecto de nuestra página no desaparezca simplemente por una versión antigua del navegador de turno.

En este artículo vamos a intentar explicar las diferentes formas de aplicar hacks a nuestros navegadores y cual de ellas elegir para nuestro proyecto.

Introducción

Para empezar debemos conocer el funcionamiento del motor a la hora de leer un CSS. Un navegador, recibe el HTMl en el cual encuentra la referencia al fichero CSS que debe cargar (tambien puede encontrarlo en el <head></head>) esté carga todo el HTML y posteriormente pasa a aplicar los estilos CSS encontrados en el fichero o en el <head></head>. Para ello sigue un orden secuencial leyendo el fichero desde el principio hasta el final, aplicando los estilos así como van apareciendo. Tambien es conveniente que sepamos que cada asignación de estilos se sobrepone a la anterior, osea que el último estilo prevalece sobre los anteriores.


#elemento {
	border:3px red solid;
	border:2px blue solid;
}

En este ejemplo estamos aplicando un borde rojo de 3px y posteriormente sobreescribimos la propiedad con un borde azul de 2px, mostrando este último.

Tipos de Hacks CSS

Disponemos de 2 tipos de hacks, los conocidos como condicionales, que se aplican generalmente en los <head></head>, y los hacks en línea, que los encontraremos en nuestro CSS.

Hacks condicionales

Esta pobremente soportado por los estandares, ya que es algo que Microsoft creó para su Internet Explorer 5 con el nombre de «conditionals comments». Estos comentarios nos permiten conocer de que navegador y de que versión se trata y aplicar unos estilos u otros.


Positivo
    <!--[if condicion]> HTML <![endif]-->
Negativo
    <!--[if !condicion]><![IGNORE[--><![IGNORE[]]> HTML <!--<![endif]-->

De esta forma podremos crear una condición que nos carge unos estilos dependiendo del navegador en el cual estén visitando a nuestra aplicación.

Estas son las conciones que podemos consultar.


IE
    Cualquier versión de Internet Explorer
lt IE X
    Versiones inferiores a X
lte IE X
    Versiones inferiores o iguales a X
IE X
    Solo para la version X
gte IE X
    Versiones superiores o iguales a X
gt IE X
    Versiones superiores a X

Pudiendo sustituir X por las versiones de IE disponibles (5,5.5,6 o 7).

Pero creo que será mejor ver un ejemplo práctico para conseguir entenderlo perfectamente.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
	<head>
		<title>Test</title>
		<link href="all_browsers.css" rel="stylesheet" type="text/css">
		<!--[if IE]> <link href="ie_only.css" rel="stylesheet" type="text/css"> <![endif]-->
		<!--[if lt IE 7]> <link href="ie_6_and_below.css" rel="stylesheet" type="text/css"> <![endif]-->
		<!--[if !lt IE 7]><![IGNORE[--><![IGNORE[]]> <link href="recent.css" rel="stylesheet" type="text/css"> <!--<![endif]-->
		<!--[if !IE]>--> <link href="not_ie.css" rel="stylesheet" type="text/css"> <!--<![endif]-->
	</head>
	<body>
		<p>Test</p>
	</body>
</html>

Hacks en línea

Los conocidos como hacks en línea son aquellos que nos encontramos en nuestro CSS, y que están colocados de forma que un navegador que no conozca esa nomenclatura no aplicará dicho efecto dejando el anterior, generalmente se aplican selectores. De esta forma podemos aplicar un estilo y posteriormente aplicar un nuevo valor a ese estilo mediante uno de los hacks y que se ejecute en caso de que el navegador conozca dicho hack y lo pueda interpretar.

Veamos los principales selectores y los navegadores que los interpretan.


IE 6 y anteriores
    * html {}
IE 7 y anteriores
    *:first-child+html {} * html {}
Solor IE 7
    *:first-child+html {}
IE 7 y navegadores modernos
    html>body {}
Navegadores modernos (IE 7 no)
    html>/**/body {}
Ultimas versiones de Opera 9 y anteriores
    html:first-child {}

Estos selectores nos permiten acceder a un mismo elemento por dos caminos diferentes, dependiendo del navegador de la forma en la que interprete los selectores.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
	<head>
		<title>Test</title>
	</head>
	<body>
		<input type="hidden" disabled id="attrhack">
		<p>Test</p>
	</body>
</html>

En este ejemplo podríamos aceder al <p></p> que engloba Test de las siguientes formas.


#attrhack[disabled=""]+p {}
    Firefox 1.5 y anteriores, posiblemente versiones futuras
    Safari 2.0 y anteriores, posiblemente versiones futuras
    Konqueror 3.5 y anteriores, posiblemente versiones futuras
#attrhack[disabled="true"]+p {}
    Opera 9 y anteriores, posiblemente versiones futuras

Dentro de los hacks en línea tenemos otros operadors que nos permiten condicionar el aspecto de nuestras páginas. Aunque no son recomendables por la W3C ya que no nos permite la validación de las hojas de estilos de nuestra aplicación.

  • !important

Internet Explorer 6 y versiones anteriores tienen un problema con este operador, ya que generalmente es ignorado en cualquier declaración, aunque Internet Explorer 7 ya ha conseguido arreglar este problema.

Es usado para que la mayoría de navegadores respeten la importancia que tiene la declaración que lo contenga. 


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
	<head>
		<title>Test</title>
		<style type="text/css">
			p
			{
				background: green !important; /* Navegadores superiores a IE 6 respetarán la importancia inmediatamente */
				background: red; /* IE 6 y anteriores aplicará este estilo aunque esté marcado la anterior como importante */
			}
		</style>
	</head>
	<body class="page-body">
		<p>Test</p>
	</body>
</html>
  • @import «non-ie.css» all;

Internet Explorer 7 y anteriores no soporta las reglas de los selectores @import, por lo tanto son ignorados en nuestro CSS. De esta forma puedes crear una hoja de estilos para navegadores no IE y importarla desde tu CSS principal dejando todos los navegadores IE fuera de este diseño.


@import "stylesheet.css" all;
  • body[class|=»page-body»]

La especificación CSS 2.1 no es muy clara aobre este tema o no hay un guión sobre este selector. Muchos navegadores, incluido Firefox e Internet Explorer 7, permiten el uso de body[class|="page-body"] como selector para un tag así: <body class="page-body">. Encambio Opera interpreta esta especificación de diferente manera. El corta el valor del atributo y solo selecciona la primera pieza del selector. Ovbiamente si el atributo se corta no obtenemos el valor deseado. Por lo tanto este selector parece no funcionar en las versiones de Opera, aunque se espera que en versiones 8 y 9 deberían funcionar.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
	<head>
		<title>Test</title>
		<style type="text/css">
			p
			{
				background: red; /* Esto se aplica a todos los navegadores */
			}

			body[class|="page-body"] p
			{
				background: green; /* Esto se aplica a IE7 y el resto de navegadores modernos excepto Opera. */
			}
		</style>
	</head>
	<body class="page-body">
		<p>Test</p>
	</body>
</html>

Hacks no recomendados

Debido a la dictadura que Internet Explorer nos ha tenido sometidos, disponemos de una serie de hacks que el validador de CSS de la W3C no soporta, pero que Internet Explorer 6 (y versiones inferiores) aún permite.

_propiedad: valor y -propiedad: valor

El uso de caracteres no alfanuméricos delante del nombre del atributo es algo que IE6 y anteriores si permite, menos mal que IE7 ya corrige este «problema». Aunque gracias a él muchos años se han usado estos «fallos» para diferenciar aspectos entre IE y el resto de navegadores.

Una buena alternativa es usar !important.

_propiedad: valor y -propiedad: valor se aplica a IE6 y anteriores.  

CSS no válido. 

*propiedad: value

Este método es similar al anterior pero en este caso tambien tenemos que tener en cuenta a Internet Explorer 7, que pese a ser un caracter no alfanumérico lo trata como si del operador * se tratara.

*propiedad: valor funciona para todos los navegadore Internet Explorer, pero en futuras versiones no debería seguir funcionando.

CSS no válido.

body:empty

:empty es una pseudo-clase propuesta por la W3C para el CSS3 y debería hacer referencia a un elemento que no tiene en su interior otros elementos o nodos de texto. Sin embargo cuando lo usamos con el elemento body, Firefox 1.5 y 2.0 siempre lo selecciona pese a tener contenido.

Aunque parece que este hack será valido para la CSS3 las recomendaciones de la W3C es no usarlo, ya que para la especificación 2.x lo considera inválido. Sin embargo es probablemente la mejor manera de diferenciar Firefox en tus CSS.

body:empty selecciona el body únicamente en navegadores Gecko (Firefox 1.5 y 2.0).

CSS 2.x: CSS no válido.

CSS 3: CSS válido.

a:link:visited, a:visited:link

De acuerdo con el estandard CSS :link y :visited son estados que no pueden darse a la vez. Parece ser que IE7 y versiones anteriores ignoran una de ellas y lo trata como un simple selector. Si tienes un enlace <a href="ejemplo.html" id="enlace"> podrás usar #enlace:link:visited{} o #enlace:visited:link {} para selecionar el elemento en Internet Explorer 7 y anteriores. Aunque se espera que en versiones futuras no funcione.

a:link:visited, a:visited:link {} selecciona un elemento <a></a> en Internet Explorer 7 y anteriores.

>body

Pese a ser un selector simple que nos indicaría el hijo de … (>) úbicado sin un elemento padre al que referenciar únicamente IE7 parece que lo interpreta. Aunque en futuras revisiones parece ser que van a solucionar este fallo.

>body {} Solo para Internet Explorer 7

CSS no válido.

html*

Internet Explorer 7 y todas las versiones anteriores, interpretan este hack como un intento de hacer referencia a todos los descendientes de html.

html* {} en Internet Explorer 7 y anteriores selecciona todos los nodos hijos de <html></html>.

CSS no válido.

!ie 

Internet Explorer 7 soluciona uno de las cuestriones con !important pero tiene problemas cuando el identificador tiene un error. Si se usa en lugar de !important, Internet Explorer manejará la propiedad correctamente en lugar de fallar. Por lo tanto en cualquier declaración de estilo puedes incluir las características prevista para aplicarse solamente en Internet Explorer y agregar !ie, cualquier palabra puede ser utilizada en lugar de ie.

CSS no válido.

!important!

Otro problema con el identificador !important que no han solucionado en IE7 es el uso de caracteres no alfanumérico detrás del identificador. Normalmente usarlo debería fallar, pero Internet Explorer 7 y anteriores ignoran el caracter final y lo aplica como si de !important se tratara.

!important! permite que la propiedad sea aplicada con la importancia requerida en IE7 y anteriores, aunque no será tratado por lo otros navegador. En futuras versiones dejará de funcionar.

CSS no válido.

Comentar

#

Me reservo el derecho de eliminar y/o modificar los comentarios que contengan lenguaje inapropiado, spam u otras conductas no apropiadas en una comunidad civilizada. Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar. Siento las molestias.