Franchu's blog

Problemas de renderizado sub-pixel en CSS

Cuando me encontré el artículo de John Resig titulado Sub-Pixel Problems in CSS pensaba que había leido mal. Para mi los pixels eran unidades indivisibles, algo así como cuando de pequeño te dicen que el átomo es la parte más pequeña de la materia y luego te das cuenta que hay más cosas dentro... pues así me he sentido cuando he entendido lo que quería decir. Por eso he decidido traducir su artículo para que más gente lo pueda entender. :)

Para ilustrar el problema, basta pensar qué ocurre cuando tenemos 4 divs flotados, cada uno de ellos con una anchura del 25%, contenidos en un div padre de 50px de ancho. ¿Qué anchura tiene cada div?

El problema es que cada div debería de tener 12.5px de anchura, pero como no se pueden renderizar fracciones de pixeles los navegadores tienen que redondear el número. Entonces el problema se convierte en saber, cómo redondear el número. ¿Redondeamos hacia arriba, hacia abajo, aleatoriamente? Los resultados son sin duda sorprendentes!

Se pueden ver tres formas diferentes de hacerlo y los efectos que tienen sobre el resultado final:

  • Redondear hacia abajo - Tanto Opera como Safari redondean hacia abajo las anchuras de los divs. En este caso el redondeo convierte los divs a una anchura de 12px, dejando un hueco de 2px (se puede apreciar la zona verde) a la derecha de todos los divs. Si alguna vez te has planteado porqué tu página cuidadosamente alineada no llena el contenedor en estos navegadores, esta es la respuesta. La ventaja es que por lo menos sabes que la anchura de estos contenedores será siempre la misma, independientemente del valor que pongas.
  • Redondear hacia arriba - Tanto Internet Explorer 6 como Internet Explorer 7 redondean las anchuras de todos los divs hacia arriba, pasando en este caso a tener 13px. Haciendo esto hacen que los divs flotados no quepan a lo ancho y se coloquen debajo, destrozando la maquetación. Esto es obviamente incorrecto y es la causa de que muchas veces la maquetación se vaya al traste sin motivo aparente.
  • Redondear algunos números hacia arriba y otros hacia abajo - Tanto Firefox 2 como Firefox 3 mezclan la política de redondeo apareciendo divs con 12px y otros con 13px. La mezcla se hace de tal forma que la anchura final encaje con la del contenedor, haciendo que se ajuste correctamente a los bordes externos. El efecto colateral es que los divs ya no tienen una anchura consistente (aunque esta hubiese sido definida como tal en el CSS!). Además, cuando se pregunta al navegador la anchura del div devuelve 12.5px constantemente no permitiendo al usuario saber cómo se ha realizado el redondeo a la hora de renderizar el div. Para añadir más confusión todavía, el orden en el cual se asignan los anchos de 12px y 13px se ha cambiado entre las versiones 2 y 3 de Firefox teóricamente para mejorar la eficiencia y la velocidad, aunque en la realidad parece que tiene un efecto mínimo (si es que lo tiene!)

David Baron, uno de los desarrolladores de Mozilla, explica la situación muy bien:

Estamos intentando ajustarnos a muchos requisitos que no pueden ser satisfechos simultáneamente:

  1. 4 objetos adyacentes con alturas/anchuras de 25% (por ejemplo) empezando en un borde de un contendor tiene que terminar exactamente en el borde del otro; no debería haber en ningún caso pixeles extra en el contenedor y nunca deberían descolocarse por ser demasiado ancho.
  2. Los objetos adyacentes lógicamente, deberían siempre tocarse visualmente; no debería haber huecos de un pixel o superposiciones de un pixel debido a errores de redondeo.
  3. Los objetos con la misma anchura deberían de ocupar el mismo número de pixels.

La que Mozilla sacrifica normalmente es la tercera, excepto en los bordes en la que se sacrifica la primera al redondear las anchuras a pixeles enteros mucho antes.

Lo más curioso es que no existe una forma de hacerlo bien o mal. La especificación de CSS no define cómo se tienen que renderizar estos casos. Las restricciones de arriba podrían ser utilizadas en todos los navegadores, pero hay que sacrificar alguna de ellas para que sean consistentes y se puedan llevar a la práctica.

Es bastante frustrante, pero tenerlo en cuenta seguro que nos salva de muchas horas de frustración!