tag:blogger.com,1999:blog-6864629.post-1142918831265065382006-03-21T00:53:00.000-04:002006-03-22T22:32:14.650-04:00Imagen de fondo en las filas de una tablaColocar una imagen de fondo en la fila de una tabla es una tarea engorrosa porque todos (Firefox 1.5, Internet Explorer 6 y Opera 8.2) los navegadores se comportan de diferente forma.<br />A continuación se expondrá el problema y una solución.<br /><br /><span style="font-weight: bold;">Problemática</span><br /><span style="font-weight: bold;"><br /></span>Para analizar el comportamiento de los tres navegadores se usará un simple archivo HTML con una tabla compuesta por una cabecera (thead) y un cuerpo (tbody). En la fila de la cabecera se pone una imagen de fondo, según la especificación CSS2 (REC-CSS2-19980512:http://www.w3.org/TR/REC-CSS2/cover.html), usando la propiedad 'background-image', como se muestra en el siguiente código:<br /><pre><br /><span style="font-size:85%;"><span style="font-family:courier new;">&lt;html></span><br /><span style="font-family:courier new;"> &lt;body></span><br /><span style="font-family:courier new;"> &lt;h1>Imagen de fondo en filas de tablas&lt;/h1></span><br /><span style="font-family:courier new;"> &lt;table width="150px" cellpadding="0" cellspacing="0" border="0"></span><br /><span style="font-family:courier new;"> &lt;thead></span><br /><span style="font-family:courier new;"> &lt;tr style="background-image: url(background.gif);"></span><br /><span style="font-family:courier new;"> &lt;th>Firefox&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th>Internet Explorer&lt;/th></span></span><span style="font-size:85%;"><br /><span style="font-family:courier new;"> &lt;th>Opera&lt;/th></span><br /><span style="font-family:courier new;"> &lt;/tr></span><br /><span style="font-family:courier new;"> &lt;/thead></span><br /><span style="font-family:courier new;"> &lt;tbody></span><br /><span style="font-family:courier new;"> &lt;tr></span><br /><span style="font-family:courier new;"> &lt;td>Mozilla fundation&lt;/td></span><br /><span style="font-family:courier new;"> &lt;td>Microsoft Corporation&lt;/td></span><br /><span style="font-family:courier new;"> &lt;td>Opera Software&lt;/td></span></span><span style="font-size:85%;"><br /><span style="font-family:courier new;"> &lt;/tr></span><br /><span style="font-family:courier new;"> &lt;/tbody></span><br /><span style="font-family:courier new;"> &lt;/table></span><br /><span style="font-family:courier new;">&lt;/body></span><br /><span style="font-family:courier new;">&lt;/html></span></span></pre><br /><span style="font-weight: bold;">Comportamiento esperado<br /><br /></span>La especificación CSS2 dice claramente que las propiedades de fondo no deben ser heredadas:<br /><br /><blockquote>Background properties are not inherited, but the parent box's background will shine through by default because of the initial 'transparent' value on 'background-color'.</blockquote><br />Al especificar una imagen de fondo en la fila se espera que esta se vea en su totalidad a través de las celdas, siempre y cuando estas no especifiquen ningun color de fondo.<br />El resultado esperado es el siguiente:<br /><div style="text-align: center;"><img src="http://static.flickr.com/56/116224767_315549b8b8_o.jpg" style="margin: 5px;" /><br /><br /></div><span style="font-weight: bold;">Comportamiento real<br /></span><br />Estos pantallazos muestran el comportamiento de cada nevegador.<br /><div style="text-align: center;"><img src="http://static.flickr.com/46/116231973_fc8e021a8a_o.jpg" style="margin: 5px;" title="Firefox 1.5" /><br /></div><div style="text-align: center;"><img src="http://static.flickr.com/46/116231974_39971ae453_o.jpg" style="margin: 5px;" title="Internet Explorer 6" /><br /></div><div style="text-align: center;"><img src="http://static.flickr.com/55/116231975_be31b87e20_o.jpg" style="margin: 5px;" title="Opera 8.2" /><br /></div><br />Firefox es el único que entrega el resultado esperado, mostrando la imagen en todo el fondo de la fila. Internet Explorer y Opera muestran un comportamiento similiar, en que cada celda hereda la imagen de fondo de la fila, por lo que se obtiene ese efecto de repetición de la imagen en cada celda en vez de una sola imagen de fondo en la fila.<br />Además del caso de estudio se realizaron más pruebas con distintas combinaciones de estilos y ubicaciones de estos.<br /><br />Ejemplo:<br /><pre><span style="font-size:85%;"><span style="font-family:courier new;">[...]</span><br /><span style="font-family:courier new;">&lt;thead></span><br /><span style="font-family:courier new;">&lt;tr style="bakcground-image: url(background.gif);"></span><br /><span style="font-family:courier new;"> &lt;th>Firefox&lt;/th><br />&lt;!-- aqui se agrega la propiedad 'background-position' a una celda --><br /></span><span style="font-family:courier new;"> &lt;th style="background-position: 50% 0%;">Internet Explorer&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th>Opera&lt;/th></span><br /><span style="font-family:courier new;">&lt;/tr></span><br /><span style="font-family:courier new;">&lt;/thead></span><br /><span style="font-family:courier new;">[...]</span></span><br /></pre><div style="text-align: center;"><img src="http://static.flickr.com/46/116231973_fc8e021a8a_o.jpg" style="margin: 5px;" title="Firefox 1.5" /><br /></div>Firefox no se muestra fectado por la aplicación de 'background-position' en una celda, lo que confirma que efectivamente las celdas no heredan el fondo de la fila.<br /><div style="text-align: center;"><img src="http://static.flickr.com/55/116402996_ab4fdacdae_o.jpg" style="margin: 5px;" title="Internet Explorer 6" /><br /></div> En Internet Explorer cada celda hereda el atributo 'background-image', esto se confirmó al aplicar un 'background-position' a la celda, que resultó en un desplazamiento de la imagen en la celda.<br /><div style="text-align: center;"><img src="http://static.flickr.com/55/116231975_be31b87e20_o.jpg" style="margin: 5px;" title="Opera 8.2" /><br /></div> Opera por su parte se comporta de otra forma, si bien parece que las celdas heredan la imagen de fondo, esto es solo un efecto visual e internamente las celdas no tienen imagen de fondo. Esto se verificó aplicando 'background-image' a las celda sin obtener algún efecto.<br /><br />Por lo tanto Internet Explorer 6 y Opera 8.2 no se están comportando de acuerdo a la especificación CSS2.<br /><br /><span style="font-weight: bold;">Solución (workaround)<br /><br /></span>La solución debe ser simple, no intrusiva, sin necesidad de despedazar la imagen y no debe tener efectos secundarios en Firefox. Dependiendo de la compatibilidad entre navegadores que se quiera, existen dos posibles soluciones:<br /><br /><span style="font-style: italic;">Compatibilidad con Firefox e Internet Explorer.<br /><br /></span>Dado que en Internet Explorer las celdas heredan el atributo 'background-image' de la fila, para lograr una imagen continuada en el fondo, basta con especificar adecuadamente el atributo 'background-image' en cada celda de la fila.<br />'background-image' acepta distintos formatos, aquí solo se usarán dos de ellos: &lt;porcentaje> &lt;porcentaje> y &lt;distancia> &lt;distancia>; el uso de uno u otro formato depende principalmente de la imagen de fondo.<br />Para una imagen sin trama o formas, el formato porcentual es más que suficiente, pero para una imagen con tramas o textos que deben aparecer en ubicaciones especificas de la fila es necesario el uso del formato &lt;distancia> &lt;distancia> para obtener un posicionamiento preciso.<br /><br />Formato &lt;porcentual><br /><pre><span style="font-size:85%;"><span style="font-family:courier new;">[...]</span><br /><span style="font-family:courier new;">&lt;thead></span><br /><span style="font-family:courier new;">&lt;tr style="bakcground-image: url(background.gif);"></span><br /><span style="font-family:courier new;"> &lt;th style="background-position: 0% 0%;">Firefox&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th style="background-position: 50% 0%;">Internet Explorer&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th style="background-position: 100% 0%;">Opera&lt;/th></span><br /><span style="font-family:courier new;"> &lt;/tr></span><br /><span style="font-family:courier new;">&lt;/thead></span><br /><span style="font-family:courier new;">[...]</span></span><br /></pre>Formato &lt;distancia><br /><pre><span style="font-size:85%;"><span style="font-family:courier new;">[...]</span><br /><span style="font-family:courier new;">&lt;thead></span><br /><span style="font-family:courier new;">&lt;tr style="bakcground-image: url(background.gif);"></span><br /><span style="font-family:courier new;"> &lt;th style="background-position: 0px px;">Firefox&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th style="background-position: -50px 0px;">Internet Explorer&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th style="background-position: -100px 0px;">Opera&lt;/th></span><br /><span style="font-family:courier new;">&lt;/tr></span><br /><span style="font-family:courier new;">&lt;/thead></span><br /><span style="font-family:courier new;">[...]</span></span><br /></pre><div style="text-align: center;"><img src="http://static.flickr.com/54/116407328_1f576e87db_o.jpg" style="margin: 5px;" title="Solución para FF e IE" /><br /></div><br /><span style="font-style: italic;">Compatibilidad con Firefox, Internet Explorer y Opera.<br /><br /></span>Para que funcione en Opera es necesario especificar la imagen de fondo en cada celda además de especificar 'background-position'. Esto porque en Opera las celdas no heredan el atributo 'background-image' por lo que 'background-position' por si solo no tendría algún efecto. Esta solución tambien funciona en Internet Explorer y Firefox.<br /><br />Formato &lt;porcentual><br /><pre><span style="font-size:85%;"><span style="font-family:courier new;">[...]</span><br /><span style="font-family:courier new;">&lt;thead></span><br /><span style="font-family:courier new;">&lt;tr>&lt;-- aquí se quitó la propiedad 'background-image' de la fila--></span><br /><span style="font-family:courier new;"> &lt;th style="bakcground-image: url(background.gif); background-position: 0% 0%;">Firefox&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th style="bakcground-image: url(background.gif); background-position: 50% 0%;">Internet Explorer&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th style="bakcground-image: url(background.gif); background-position: 100% 0%;">Opera&lt;/th></span><br /><span style="font-family:courier new;">&lt;/tr></span><br /><span style="font-family:courier new;">&lt;/thead></span><br /><span style="font-family:courier new;">[...]</span></span><br /></pre>Formato &lt;distancia><br /><pre><span style="font-size:85%;"><span style="font-family:courier new;">[...]</span><br /><span style="font-family:courier new;">&lt;thead></span><br /><span style="font-family:courier new;"> &lt;tr></span></span><span style="font-size:85%;"><span style="font-family:courier new;">&lt;-- aquí se quitó la propiedad 'background-image' de la fila--></span></span><span style="font-size:85%;"><br /><span style="font-family:courier new;"> &lt;th style="bakcground-image: url(background.gif); background-position: 0px px;">Firefox&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th style="bakcground-image: url(background.gif); background-position: -50px 0px;">Internet Explorer&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th style="bakcground-image: url(background.gif); background-position: -100px 0px;">Opera&lt;/th></span><br /><span style="font-family:courier new;"> &lt;/tr></span><br /><span style="font-family:courier new;">&lt;/thead></span><br /><span style="font-family:courier new;">[...]</span></span><br /></pre><div style="text-align: center;"><img src="http://static.flickr.com/36/116406397_20a50da08d_o.jpg" style="margin: 5px;" title="Solución para FF, IE y Opera" /><br /></div><br />Ambas soluciones no usan nada fuera de HTML y CSS; son simples, no se necesita seccionar ninguna imagen y funcionan correctamente en Firefox.<br />Pero son un poco intrusivas porque agregan bastante código que es incomodo de mantener y si además en una página se tienen muchas tablas con distintas imagenes de fondo o tablas generadas dinámicamente, se vuelve un poco engorroso configurar apropiadamente los parametros en cada celda.<br />Por esto escribí una función en javascript que se encarga de configurar todo lo necesario para que la imagen de fondo aparezca correctamente en los tres navegadores.<br /><pre><br /><span style="font-size:85%;"><span style="font-family:courier new;"><span style="font-weight: bold; color: rgb(51, 51, 153);">function</span> <span style="color: rgb(102, 0, 204);">setTableRowBackgroundImagePosition</span>(table){</span><br /><span style="font-family:courier new;"><span style="color: rgb(51, 51, 153);"> var</span> all_tablesRows;</span><br /><span style="font-family:courier new;"><span style="color: rgb(51, 51, 153);"> if</span> (table) all_tablesRows = table.<span style="color: rgb(102, 0, 204);">getElementsByTagName</span><span style="color: rgb(102, 0, 204);">(</span><span style="color: rgb(204, 51, 204);">"tr"</span>);</span><br /><span style="font-family:courier new;"><span style="color: rgb(51, 51, 153);"> else</span> all_tablesRows = document.<span style="color: rgb(102, 0, 204);">getElementsByTagName</span>(<span style="color: rgb(204, 51, 204);">"tr"</span>);</span><br /><br /><span style="font-family:courier new;"><span style="color: rgb(51, 51, 153);"> for</span> (<span style="color: rgb(51, 51, 153);">var</span> i = <span style="color: rgb(255, 102, 102);">0</span>; i &lt; all_tablesRows.length; i++){</span><br /><span style="font-family:courier new;"> <span style="color: rgb(0, 0, 153);">if</span>(all_tablesRows[i].style.backgroundImage == <span style="color: rgb(204, 51, 204);">''</span>) continue;<span style="color: rgb(255, 153, 0);">//No background-image here, go on.</span></span><br /><span style="font-family:courier new;"> <span style="color: rgb(0, 0, 153);">var</span> cells = all_tablesRows[i].cells;</span><br /><span style="font-family:courier new;"> <span style="color: rgb(0, 0, 153);">var</span> previousWidth = <span style="color: rgb(255, 102, 102);">0</span>;</span><br /><span style="font-family:courier new;"> for (<span style="color: rgb(0, 0, 153);">var</span> j = <span style="color: rgb(255, 102, 102);">0</span>; j &lt; cells.length - <span style="color: rgb(255, 102, 102);">1</span> ; j++){<span style="color: rgb(255, 153, 0);">//The last cell is processed after the for.</span></span><br /><span style="font-family:courier new;"> cells[j].style.backgroundPosition = <span style="color: rgb(204, 51, 204);">'-'</span> + previousWidth.<span style="color: rgb(102, 0, 204);">toString</span>() + <span style="color: rgb(204, 51, 204);">"px 0px"</span>;</span><br /><span style="font-family:courier new;"> <span style="color: rgb(0, 0, 153);">if</span>(navigator.userAgent.<span style="color: rgb(102, 0, 204);">indexOf</span>(<span style="color: rgb(204, 51, 204);">"Opera"</span>)!=-<span style="color: rgb(255, 102, 102);">1</span>){<span style="color: rgb(255, 153, 0);">//mmm...Opera</span></span><br /><span style="font-family:courier new;"> cells[j].style.backgroundImage = all_tablesRows[i].style.backgroundImage;</span><br /><span style="font-family:courier new;"> }</span><br /><span style="font-family:courier new;"> previousWidth += cells[j].clientWidth;</span><br /><span style="font-family:courier new;"> }</span><br /><span style="font-family:courier new;"> cells[cells.length-<span style="color: rgb(255, 102, 102);">1</span>].style.backgroundImage = all_tablesRows[i].style.backgroundImage;</span><br /><span style="font-family:courier new;"> cells[cells.length-<span style="color: rgb(255, 102, 102);">1</span>].style.backgroundPosition = <span style="color: rgb(204, 51, 204);">"100% 0%"</span>;</span><br /><span style="font-family:courier new;"> }</span><br /><span style="font-family:courier new;">}</span></span><br /></pre>Su uso es muy sencillo, solamente se debe escribir la tabla de forma correcta indicando la imagen de fondo solo en la fila (tr) y luego con una llamada a la función todo queda configurado. La función revisa todas las filas de todas las tablas presentes en el documento y en las que se haya indicado una imagen arreglará las celdas configurando la propiedad 'background-position' y en caso de estar en Opera también la propiedad 'background-image'.<br />La función tambien da la posibilidad de especificar que tabla se quiere arreglar, para evitar pasar por todas las tablas del documento.<br /><br />En concreto, se debe escribir la tabla:<br /><pre><span style="font-size:85%;"><span style="font-family:courier new;">&lt;table width="150px" cellpadding="0" cellspacing="0" border="0"></span><br /><span style="font-family:courier new;"> &lt;thead></span><br /><span style="font-family:courier new;"> &lt;tr style="background-image: url(background.gif);"></span><br /><span style="font-family:courier new;"> &lt;th>Firefox&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th>Internet Explorer&lt;/th></span><br /><span style="font-family:courier new;"> &lt;th>Opera&lt;/th></span><br /><span style="font-family:courier new;"> &lt;/tr></span><br /><span style="font-family:courier new;"> &lt;/thead></span><br /><span style="font-family:courier new;"> &lt;tbody></span><br /><span style="font-family:courier new;"> &lt;tr></span><br /><span style="font-family:courier new;"> &lt;td>Mozilla fundation&lt;/td></span><br /><span style="font-family:courier new;"> &lt;td>Microsoft Corporation&lt;/td></span><br /><span style="font-family:courier new;"> &lt;td>Opera Software&lt;/td></span><br /><span style="font-family:courier new;"> &lt;/tr></span><br /><span style="font-family:courier new;"> &lt;/tbody></span><br /><span style="font-family:courier new;">&lt;/table></span></span><br /></pre>Y luego llamar la función, ya sea desde window.onload o como parte de otra función que genera una tabla.<br />El uso de la función tiene además la ventaja que si el diseño de la imagen no tiene directa correspondecia al tamaño de la tabla, se puede hacer una imagen larga como el máximo ancho de la tabla y si ella resulta más corta se verá bien de todas formas, porque la última celda siempre se configura de modo que muestre el extremo derecho de la imagen.Francesco Barresihttp://www.blogger.com/profile/07396417056716676216noreply@blogger.com