De PNGs transparentes, navegadores y onLoads va la cosa

29 de May, 2008. Escrito por [Q]boss en Flash, Javascript, Navegadores, Recursos, XHTML + CSS, [Q] interactiva

En el estudio he tenido que emplear PNGs transparentes, que como sabeís (y sino, deberíais) no son soportados por versiones de Internet Explorer 6 o anteriores, sino que vienen soportadas desde la versión 7 de nuestro amigo IE.

Hasta aqui no hay gran problema, porque empleando un pngfix de javascript se arregla el entuerto (bonito palabro).

JavaScript:
  1. /*
  2. Correctly handle PNG transparency in Win IE 5.5 & 6.
  3. http://homepage.ntlworld.com/bobosola. Updated 18-Jan-2006.
  4. Use in <HEAD> with DEFER keyword wrapped in conditional comments:
  5. <!--[if lt IE 7]>
  6. <script defer type="text/javascript" src="pngfix.js"></script>
  7. <![endif]-->
  8. */
  9.  
  10. var arVersion = navigator.appVersion.split("MSIE")
  11. var version = parseFloat(arVersion[1])
  12.  
  13. if ((version>= 5.5) && (document.body.filters))
  14. {
  15.    for(var i=0; i<document.images.length; i++)
  16.    {
  17.       var img = document.images[i]
  18.       var imgName = img.src.toUpperCase()
  19.       if (imgName.substring(imgName.length-3, imgName.length) == "PNG")
  20.       {
  21.          var imgID = (img.id) ? "id='" + img.id + "' " : ""
  22.          var imgClass = (img.className) ? "class='" + img.className + "' " : ""
  23.          var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' "
  24.          var imgStyle = "display:inline-block;" + img.style.cssText
  25.          if (img.align == "left") imgStyle = "float:left;" + imgStyle
  26.          if (img.align == "right") imgStyle = "float:right;" + imgStyle
  27.          if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle
  28.          var strNewHTML = "<span " + imgID + imgClass + imgTitle
  29.          + " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
  30.          + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
  31.          + "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>"
  32.          img.outerHTML = strNewHTML
  33.          i = i-1
  34.       }
  35.    }
  36. }

El tema se complicó (no iba a ser todo tan sencillo...) cuando además metía un evento onLoad para el body con la intención de lanzar una función javascript, y paso a describir el caso porque puede ser de ayuda para quien se encuentre en la situación:

LO QUE QUEREMOS LOGRAR
Tenemos una imagen de fondo de un cierto peso en KB (ya que no es una trama, sino una imagen plena de faculades), y sobre esa imagen han de colocarse unos botones que a su vez son imágenes, y que para que quede medianamente bonito han de ser transparentes.

PRIMER PROBLEMA
El primer problema es que la imagen de fondo que se crea por CSS, pesa lo suficiente como para que se dé durante unos segundos la situación de aparecer los botones sin el fondo que les da "sentido", un efecto poco deseable.

SOLUCIÓN PRIMER PROBLEMA
Para solucionarlo buscamos si existía algun método mediante CSS o XHTML para forzar la carga de los elementos de la hoja de estilos antes que se renderizara el HTML, pero..... no lo hemos encontrado. Si algún alma caritativa sabe cómo lograrlo mediante CSS (o de una manera más limpia que la que hemos empleado nosotros) que no dude en contárnosla.
Jorge tuvo la feliz idea de poner la misma imagen con propiedad display:none en el comienzo del body, con lo que la imagen se carga como HTML impidiendo así que se muestre lo que va a continuacion hasta que se completa dicha carga, y luego el CSS no tarda nada de tiempo en cargarla porque está en caché. Mientras esto ocurre, el div con los botones transparentes, permanece oculto también con la propiedad display, para por javascript hacerlo visible en el onLoad de la página.

SEGUNDO PROBLEMA
Cuando ya estábamos pegando saltos de alegría con el trabajo terminado, vemos que nuestro querido IE 6 no muestra los botones, no así en IE 7 o en firefox.... :(

SOLUCIÓN SEGUNDO PROBLEMA
El problema es debido a la mala compatibilidad del pngfix con métodos invocados en el onLoad. La solución pasa por usar una variante del pngfix (que ha salido a la luz porque también da problemas con el swfobject) y que permite mezclar estas dos necesiades: pngfix y onLoad. Lo que hicimos es "googlear" y emplear el citado pngfix adaptado además de colocar la llamada al mismo DESPUÉS (y ojo que esto es necesario para que se dispare el evento onLoad) de la etiqueta de apertura de BODY. Cuando decimos la llamada nos referimos a esto:

HTML:
  1. <!–[if lt IE 7]>
  2. <script defer type=”text/javascript” src=”pngfix.js”></script>
  3. <![endif]>

El resultado lo podéis ver aquí, por cierto, la web está recien salida del horno... diseño por takeone dsgn y programación flash y adaptación del blog por [Q]. :)

Comments

5 Responses to “De PNGs transparentes, navegadores y onLoads va la cosa”

  1. Cmacias on May 29th, 2008 9:31 am

    Llegaste a probar con algo como esto ?
    http://www.cmacias.com/png-transparente-con-css/

  2. [Q]boss on May 29th, 2008 9:47 am

    Pues mira no lo había probado y seguro que no tiene el problema del onLoad :) Me hubiera ahorrado una buena comedura de cabeza..

    El css que indicas en el post, sabes si es compatible con todos los navegadores.. y por otro lado, las imágenes han de tener asociada la clase “png”?

  3. Cmacias on May 29th, 2008 11:21 am

    No es necesario tener asociada la clase.

    Si le pones el condicional del Explorer (
    ) evidentemente no te carga en el resto de navegadores que ya traen soporte para png transparente. En explorer 6 que es donde debería funcionar, lo hace perfectamente, ya que es donde hice las pruebas.

    Aún así y por si quedara alguna duda, te adjunto la url del artículo original

    http://www.komodomedia.com/blog/2007/11/css-png-image-fix-for-ie/

  4. tak on June 4th, 2008 10:44 pm

    Hummm…. y esto?
    .selected .barra_izq{
    background-image:url(grafico.png) !important;
    background-image:none;
    filter: none !important;
    filter:
    progid:DXImageTransform.Microsoft.AlphaImageLoader(src=’grafico.png’);
    overflow:hidden;
    }

    :P

  5. [Q]boss on June 4th, 2008 11:55 pm

    eso para mi tiene una pinta horrible… es que odio las hojas de estilo con “trucos” para que haya cosas que las lean unos navegadores y otros no, ya que a mi modo de ver pueden provocar que con la llegada de nuevos navegadores, se te complique la vida :)

Leave a Reply