Esta tarde he pasado por una de las etapas de frustración más alarmantes de mi vida como diseñador web en mis ratos libres.
El problema es sencillo de explicar: resulta que yo disponía de este sencillo código:
<!DOCTYPE html > <html> <head> <title>Title of the document</title> <style type="text/css"> * { margin:0; padding:0; } </style> </head> <body> <p>The content of the document......</p> </body> </html>
Este código HTML es un ejemplo de documento HTML5 válido. La sección estilo elimina todos los márgenes y rellenos de forma que el contenido debería aparecer pegado a la esquina superior izquierda de la página y de hecho, cuando probaba la página en mi ordenador de sobremesa, con Windows 7, así era; sin embargo, al usarlo en el servidor de pruebas con Linux, editando con vim, el párrafo de prueba aparecía desplazado una línea hacia abajo.
Este inexplicable comportamiento está relacionado con el modelo de objetos del documento (DOM). El DOM es una interfaz que presenta un documento HTML o XML como un árbol de objetos anidados. Herramientas como Firebug o Chrome permiten inspeccionar el DOM de la página web. Por alguna extraña razón (que he tardado una hora en descubrir), el DOM de la versión en Windows era correcta mientras que la versión en el servidor Linux no lo era: todo el contenido de la cabecera web (etiqueta <head>) aparecía insertado dentro del cuerpo (etiqueta <body>).
Al usar la herramienta de validación HTML de la W3 con el documento del servidor, recibía la siguiente advertencia:
Byte-Order Mark found in UTF-8 File.
The Unicode Byte-Order Mark (BOM) in UTF-8 encoded files is known to cause problems for some text editors and older browsers. You may want to consider avoiding its use until it is better supported.
Que viene a indicar que el documento cargado incluye la marca de orden de bytes o BOM y que esta podría causar problemas con algunos editores de texto o navegadores viejos. Bien, tengo Firefox 4. No pensé en él como en un navegador viejo. Además también probé con Chrome y obtenía los mismos resultados. El BOM es una marca que indica cuáles son los bytes más significativos de un carácter codificado en UTF-8.
¿Qué quiere decir esto? Pues que, por ejemplo, la «ñ» tiene el símbolo UTF (en hexadecimal) ‘F1′ pero como UTF puede codificarse en 8, 16 o 32bits, podríamos encontrarlo también como ’00 F1′ (16bits) o ’00 00 00 F1’ (32bits). Y lo que es peor, podemos encontrarnos estas dos últimas codificaciones al revés: ‘F1 00’ y ‘F1 00 00 00’. Para evitar confusiones existe el BOM que indica si debemos leer los caracteres de izquierda a derecha o de derecha a izquierda.
En el caso del BOM para UTF de 8 bits, la existencia de la marca o su contenido debería ser irrelevante (sólo es 1byte, no importa el orden) pero no es así. Y este era el problema: la existencia del BOM confundía a Firefox y a Chrome (aun presiento que a quien confundía realmente era al servidor Apache pero no estoy seguro), lo que llevaba a malinterpretar los símbolos del documento, errar las etiquetas y corromper el DOM lo que a su vez arruinaba el aspecto de la página.
En fin, un brainfuck considerable. Así que ya sabéis:
contenido para web en UTF-8, sin BOM
Desde vim, podeis deshabilitar el BOM introduciendo los comandos:
:set nobomb :w
Fácil cuando lo sabes, xP.
EDIT: He encontrado informaicón muy útil y en Español en la W3 acerca de la marca de BOM