PNG: Egy böngészőfüggetlen módszer
A PNG képek túllépnek a szokásos képformátumokon (jpg, gif), azzal, hogy lehetsőget adnak az alpha csatorna, azaz az áttetszőség használatára. Átlátszóságot ugyan kínáltak már GIF képek is, ami ugyan megállta a helyét a '90es években, de az emberek manapság már nem szeretnének képpontokat látni a képernyőn, ezért is az eltérő szóhasználat.
A GIF csak átlátszóságot kínált, azaz egy képpont (pixel) helyén vagy a háttér színét, vagy a kép színét láttuk, átmenet nem volt. Ezért a GIF-ek szélei ügyetlenül reszelték a képernyőt. Ezt némileg áthidalni próbálták azzal, hogy a képeknek készítettek sötét és világos háttér elé szánt változatot is (pl. a Powered by PHP logo változatai), de ez csak alig-alig csökkenti a pixeles hatást.
Ezek szerint a válasz egyszerű: használjunk PNG képeket! Sajnos mégsem ilyen egyszerű. Egy kivételével az összes böngésző képes a PNG képek összemosására a háttérrel, és ez az egy véletlenül a netezők 80 százaléka által haznált Internet Explorer. Innentől javaslom, az oldalt Explórerben és egy alternatív böngészőben (pl. Firefox) is megtekinteni.
PNG beillesztése a gyakorlatban
A következő kódrészlet egy egyszerű PNG kép beillesztését tartalmazza:
<img src="kepek/ie_alpha.png">
A képet az Explorer (legalább is a hatos verzióig biztosan) szürke háttérrel jeleníti meg (ami nem az oldal háttérszíne). Nyoma sincs áttetszőségnek, de még átlátszóságnak sem. Most pedi jöjjön sz Explórer-módszer:
<img src="kepek/spacer.gif" style="filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='kepek/ie_alpha.png', sizingMethod=image);">
Ez a második példa gyönyörű Explórerben, de a többi böngésző nem lát itt semmit. Ennek oka, hogy a kép forrása (src) egy üres kép, és a tényleges képünk (ie_alpha.png) megjelenítését a style (CSS) paraméterben elhelyezett filter stílus végzi. Ez természetesen teljesen ismeretlen a többi böngészőnek, úgyhogy a kép nem jelenhet meg. A src attribútumban pedig nem használhatjuk a valódi képet, mert akkor a felsővel egyező (szürke keretes) képet kapnánk.
A spacer.gif nem más, mint egy 1x1 pixel méretű teljesen átlátszó gif. Ennek semmi szerepe, csak az, hogy egy semleges alapot jelentsen, amire a filter megrajzolhatja a valódi képet.
Ennek utána világossá vállik, hogy a két módszer nemigen kombinálható. Ha a src-ben van a kép, akkor az Explórer hátteret fest neki, ha pedig a filter-ben, akkor a többi böngésző nem tud mit kezdeni vele.
És a megoldás: Javascript
A megoldás vagy egy reverse proxy szerver lenne, ami minden IE számára átírja a html kódot (ami plusz munkát jelent a szervernek), vagy hagyjuk a klienseket dolgozni, és egy szkriptet írunk a feladatra.
A DOM egjelenése óta játszi könnyedséggel manipulálhatjuk a HTML dokumentumunk tartalmát. Nincs más dolgunk tehát, mint az oldal betöltése után lefuttatni kis szkriptünket, ami (IE esetén) végigmegy a dokumentum összes képén majd a src attribútum tartalmát ügyesen átírjuk a filter-be.
A következő kód Internet Explorer-re készült:
function alphaImages() {
var els = document.getElementsByTagName("IMG");
var s, w, h;
for (var i=0; i<els.length; i++) {
s = els[i].src;
if (s.toLowerCase().indexOf(".png") != -1) {
els[i].src = "spacer.gif";
els[i].style.filter += "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + s + "', sizingMethod=image);";
}
}
}
if (navigator.userAgent.indexOf("MSIE") != -1 && navigator.userAgent.indexOf("Windows") != -1)
window.attachEvent("onload", alphaImages);
Ez nem egy DOM okató cikk, de azért egy kis magyarázat álljon itt a szkripthez. Az alphaImages() függvény lekérdezi az összes IMG tag-et a dokumentumból, majd egy ciklussal végighalad rajtuk. Ha a src attribútum értéke (megyarul a filenév) tartalmazza a .png sztringet (tehát nagy valószínűséggel png képről van szó), akkor azt beállítjuk átlátszó gif-ünkre, amjd a filter stílus beállítása következik, ahol az eredeti src értéket használjuk fel.
Az utlsó két sor ellenőrzi, hogy IE-t hazsnálunk-e, pontosabban az IE Windows-os verzióját. Ha igen akkor beállítja a függvényünket, hogy fusson le az oldal betöltődésekor (amikor már mindne kép rendelkezésre áll, amivel dolgozhat).
PNG, mint CSS background
Az Explórer természetesen ezt az esetet sem úgy kezeli, ahogy várnánk. A CSS background paramétereként használt képet is konvertálnunk kell, hogy a filter segítségével éjük el a kívánt hatást.
Az IE az 5-ös változat óta támogatja a CSS elérését Javascript segítségével. E kiválló CSS manipuláció (QuirksMode) cikk összefoglalja az ehhez szükséges tulajdonságokat és metódusokat.
Amit kiemelnék az annyi, hogy amíg a background a kép fájlok elérési útját a CSS fájltól számítja, addig a filter a relatív eléréseket a html dokumentum helyéhez viszonyítja. Ezt a problémát úgy oldjuk meg, hogy az összes relatív background hivatkozásból abszolút URL-t számítunk a cssDir változó segítségével és az így kapott elérési utakat hazsnáljuk a filter paramétereként.
A következő kód magában foglalja a fenti (IMG tagekre működő) megoldást is.
// png képek átalakítása Internet Explorer számára
function alphaFixIE() {
var s, i, j;
// IMG
var els = document.getElementsByTagName("IMG");
for (i=0; i<els.length; i++) {
s = els[i].src;
if (s.toLowerCase().indexOf(".png") != -1) {
els[i].src = "spacer.gif";
els[i].style.filter += "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + s + "', sizingMethod=image);";
}
}
// CSS: background
for (i=0; i<document.styleSheets.length; i++) {
var pos = document.styleSheets[i].href.lastIndexOf("/");
var cssDir = (pos != -1) ? document.styleSheets[i].href.substring(0, pos + 1) : "";
for (j=0; j<document.styleSheets[i].rules.length; j++) {
var style = document.styleSheets[i].rules[j].style;
if (style.backgroundImage.toLowerCase().indexOf(".png") != -1) {
var filename = style.backgroundImage.substring(4, style.backgroundImage.length - 1);
if (filename.indexOf("http://") != 0 && filename.indexOf("/") != 0)
filename = cssDir + filename;
style.backgroundImage = "none";
style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + filename + "', sizingMethod='crop');";
}
}
}
}
if (navigator.userAgent.indexOf("MSIE") != -1 && navigator.userAgent.indexOf("Windows") != -1)
window.attachEvent("onload", alphaFixIE);
Az IE néha furcsán viselkedhet ha linkeknek adunk hátteret a fenti megoldás (AplhaImageLoader) segítségével. Ha a kurzor nem akarna kézre váltani a következő CSS részlet (nálam mindig bent van) orvoslja a problémát:
a {
cursor: hand;
position: relative;
}
Nyissuk ki a konzervet: a kód hazsnálata
A kedves olvasónak nincs más dolga, mint készíteni egy üres javascript fájlt, például alphaimages.js, majd az itt található kódot beilleszteni. Ha ezzel megvagyunk, már csak az aktuális HTML lapokon kell egy hivatkozást elhelyezni a szkriptre (például az oldal HEAD részében).
<script language="Javascript" src="alphaimages.js"></script>
Már csak egy dolog maradt: keresni a google-lel egy spacer.gif-et :)