Zmierzyłem się kiedyś z obrazkiem, któremu chciałem wyłączyć możliwość łatwego, prawoklikowego zapisu. O ile wtedy wyczyniałem cyrki z linkami, tak teraz mam przyjemność Wam przedstawić wersję elegancką - nie dość że zlikwidujemy pozycję w menu pozwalającą zapisać plik to jeszcze dodamy transparentny znak wodny. Do dzieła. :-)
Na początku jak zwykle trzeba napisać kawałek HTML-a. Wybrałem listę definicji - jako definicję mamy obrazek, opisem jest link - wspomniany znak wodny.
<dl class="img"><dt><img src="soo-gothic.jpg" height="119" alt="My Picture" /></dt><dd><a href="">Copyright © Riddle</a></dd></dl>
Obrazek ma ustawioną wysokość w HTML - dowiedz się dlaczego. Po prostym ostylowaiu kolorami otrzymujemy taki oto wynik.
Teraz chcę przesunąć element <dd/> nad obrazek w elemencie <dt/>. Korzystam z pozycjonowania relatywnego:
dl.img {position: relative;}dl.img dd {position: absolute;top: 0;left: 0;}
Tekst ładnie przesuwa się na górę, nad obrazek.
Następnie, czego można było się domyślić, rozciągnąłem <dd/> na całą szerokość i wysokość. W ten sposób przykryłem obrazek nowym elementem - każdy klik prawym przyciskiem będzie się odbywał na <dd/> a nie <img/> - a w menu nie pojawi się żadna opcja dotycząca grafiki.
dl.img dd {...width: 100%;height: 100%;}
I byłoby tak w istocie, gdyby nie kaprysy przeglądarek. Zajmijmy się najpierw Internet Explorerem 6. Nie czuje się on zobligowany do rozciągnięcia <dd/> na 100% wysokości, trzeba go więc zmusić. Po raz kolejny skorzystałem z dobrodziejstw expressions.
W komentarzu warunkowym dla IE6 (<!--[if lte IE 6]><![endif]-->):
dl.img dd {height: expression(this.parentNode.offsetHeight - 6);}
Co tu się wydarzyło? Odwołałem się do elementu <dd/> przez this. Następnie wybrałem jego rodzica - <dl.img/> - przez parentNode. Wreszcie pobrałem wysokość zrenderowanego elementu za pomocą offsetHeight. Jako, że zależy mi na 100% eleganckim rozwiązaniu, odjąłem od wartości 6 pikseli, przypadających na podwójne obramowanie <dt/> (border: 3px double…). W ten sposób do height <dd/> przyporządkowałem wysokość zawartości elementu <dl/>.
Czy działa? Niewątpliwie rozciągnąłem i przykryłem cały obrazek elementem <dd/>, ale nadal w IE6 pod prawym przyciskiem myszki mamy możliwość zapisu obrazka. W Operze 9 jest tak samo, zdaje się że kopiuje zachowanie Explorera. Rozwiązanie tego problemu wydaje się bardzo trudne, ale takie nie jest - jeśli ma się informacje z dobrej ręki. ;)
Explorer posiada pewien bug, który objawia się skracaniem pola aktywnego elementu poza tekstem. Najbardziej uciążliwy jest w niektórych odmianach menu rollover. Nie chcę oczywiście powiedzieć, że Opera powiela błędne zachowanie - po prostu wydaje się tutaj nie respektować całkowitego przykrywania elementu (a raczej jego konsekwencji). Do czego zmierzam. Wystarczy przypomnieć tym przeglądarkom o obszarze jaki ten element zajmuje - i problem znika.
Uczynić to można aplikując elementowi tło. Kolor u nas odpada - musimy widzieć obrazek. Transparent nie działa (wszakże to domyślne ustawienie). Działa za to obrazek tła. Co więcej - żeby nie wracać do epoki przezroczystych GIF-ów wystarczy podać dowolny ciąg tekstowy jako URL:
dl.img dd {...background: url("opera&ie.hack");}
Proszę pamiętać, że nie wydzielałem tej linijki do stylów dla IE z powodu Opery. Jednak ten kod się spokojnie waliduje, więc bez obaw. Mankamentem tego rozwiązania jest denerwowanie ludzi próbą wyświetlenia pliku opera&ie.hack. Można więc zrobić ten przezroczysty GIF, dla świętego spokoju - jak wolisz.
Doszliśmy więc do efektu, który obiecywałem - obrazka nie da się zapisać w standardowy sposób. Oczywiście przypomnę, co już pisałem wtedy - sprytny i tak znajdzie wyjście (dużo mądrości plemiennych w komentarzach poprzedniego wpisu). Jednak zwykły kradziej-zółtodziób sobie nie poradzi. A Prt Scr odpadnie ze względu na kolejny krok ulepszania mojej metody.
Teraz pozostaje zrobić znak wodny. Poszedłem na żywioł i zrobiłem przezroczysty plik PNG z kanałem Alpha - będziemy walczyć, aby IE to pokazał - bo umie, tylko się wstydzi. ;)
Na początku zmieniamy link w element blokowy, nadajemy mu wymiary i przycinamy wystający tekst. Standard.
dl.img a {display: block;height: 25px;width: 25px;overflow: hidden;}
Następnie pozycjonujemy go relatywnie do kontenera dt.img z prawej i na dole.
dl.img a {...position: absolute;right: 0;bottom: 0;}
Wreszie korzystamy z najpopularniejszej metody zamiany tekstu na obrazek i odsuwamy literki w lewo oraz ustawiamy tło ze znakiem wodnym.
dl.img a {...text-indent: -1000px;background: url(wmark.png);}
Otrzymujemy pożądany efekt, ale nie na IE. Tam należy skorzystać z filtra MS, włączającego obsługę kanału Alpha. Aby użyć filtru element musiałby mieć layout (hasLayout), ale tak się składa, że już go nadałem poprzez ustawienie wymiarów.
Najpierw należy wyłączyć tło - filtr tak naprawdę dodaje zwykły obrazek za tekstem, a nie zmienia zachowanie poprzedniego obrazka tła. Następnie wpisujemy magiczne znaczki w CSS dla IE6:
dl.img a {background: none;filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="wmark.png", sizingMethod="crop");cursor: hand;}
W parametrze src podałem ten sam obrazek użyty wcześniej w tle. SizingMethod ustawione na crop powoduje ucięcie wystających części obrazka - u nas i tak nic nie wystaje. Wreszcie naprawiłem błąd z kursorem nad tym linkiem - nie wyświetlała się łapka. Działa.
Także całe trio - Firefox, Opera i Misio zostało obsłużone. Explorer 7 poradził sobie równie dobrze jak Opera - najlepiej zrobił to Firefox.
Przygotowałem też małą galeryjkę umożliwiającą sprawdzenie mojego kodu i przetestowanie przezroczystości (czy aby nie oszukiwałem). Zmieniarka jest w JavaScript, ale udostępniłem fallback do zwykłych stron HTML - i na marginesie - tak powinno się to właśnie robić. :)
Update: znalazłem rozwiązanie na ten plik opera&ie.hack. Jeśli nie zdecydujesz się umieszczać znaku wodnego, to po prostu ustaw czarne tło background: #000 i ustaw opacity: 0 - efekt będzie doskonały! IE też może uzyskać przezroczystość (filtry), więc wszystko zadziała wszędzie.


