Perfection or Vanity

Project: Terminated

Blog nie jest już dalej prowadzony ani aktualizowany. Mimo tego, wpisy i komentarze są dalej dostępne. Możesz przeczytać pożegnalny wpis albo przejść do archiwum.

Cień tekstu w CSS

31 stycznia 2007

Cień tekstu

Bardzo ładnym i subtelnym efektem używanym na stronach internetowych jest zaaplikowanie cienia tekstowi, w celu jego wyróżnienia bądź poprawienia kontrastu. Udało mi się przetestować kilka sposobów jego dodania. Każda metoda ma swoje plusy i minusy oraz różni się znacznie od pozostałych. Aby ujednolicić przykłady będziemy operować na zwyczajnym jednopikselowym cieniu rzucanym od góry z lewej.

Czysty CSS

Najlepiej użyć odpowiedniej własności CSS2 - text-shadow. Działa ona na razie tylko na Safari i innych przeglądarkach używających Webkitu (Konqueror, iCab).

Text-shadow
  1. text-shadow: 2px 2px 1px #2f6a34;

Pierwsze dwie wartości odpowiadają za odsunięcie cienia w poziomie i pionie (można stosować ujemne wartości i stworzyć np.: świecący tekst). Następna za jego rozmiar, a ostatnia to kolor.

Warto też wiedzieć, że zerowy text-shadow dodany dla jasnego tekstu na ciemnym tle w Safari sprawi, że font będzie cieńszy. Poprawia to widoczność niektórych elementów strony. A zobaczyć jak nasza strona wygląda z zaaplikowanym text-shadow można na BrowsrCamp.

Filtry IE

Internet Explorer został rozszerzony o zestaw filtrów generujące różne efekty. Aby pomyślnie użyć filtru należy zaaplikować elementowi layout. Składnia:

  1. filter: progid:DXImageTransform.Microsoft.NazwaFiltru(opcje)
  2. progid:DXImageTransform.Microsoft.NazwaFiltru2(opcje)

Kolejne filtry dodajemy po spacji albo w nowym wierszu, wszystko w obrębie filter.

Co jednak oferują w konteście tekstu? Nic wartościowego - nie chcielibyśmy zaaplikować żadnego z efektów na naszej stronie. Paskudna jakość, tekst staje się rozmyty, a krawędzie postrzępione. Nijak się mają do text-shadow, oto próbki:

Shadow Filter
  1. filter: progid:DXImageTransform.Microsoft.Shadow(color=#2f6a34, direction=120, strength=1)
DropShadow Filter
  1. filter: progid:DXImageTransform.Microsoft.DropShadow(color=#2f6a34, offX=1, offY=1, positive=true)

Wyglądają identycznie kiepsko, prawda?

Pozycjonowanie duplikatu

Ta metoda wykorzystuje dodatkowy element umieszczony wewnątrz tego, któremu zaaplikujemy cień. Dodać możemy go ręcznie albo przez JavaScript. Preferuję drugie rozwiązanie, bo dzięki temu przenoszę prezentację do warstwy zachowania (a to lepsze niż prezentacja w strukturze). Ponadto jesteśmy w stanie ustawić kolor tekstu w CSS odpowiednio kontrastujący z tłem, a następnie podmienic go w JS i dodać cień niwelujący niedostateczną widoczność.

Potrzebujemy takiego kodu:

  1. <h1 id="pos">
  2. Text duplicate
  3. <span>Text duplicate</span>
  4. </h1>

Identyfikator dodałem na potrzeby JavaScriptu:

  1. function applyShadow() {
  2. var pos = document.getElementById('pos');
  3. var span = document.createElement('span');
  4. span.appendChild(document.createTextNode(pos.firstChild.nodeValue));
  5. pos.appendChild(span);
  6. }

Następnie odpowiedni CSS. Musimy tekst w spanie przesunąć pod oryginał. Pozycjonujemy więc span względem nagłówka z przesunięciem 1px w dół i prawo i dajemy odpowiednie z-index.

  1. h1#pos {
  2. position: relative;
  3. z-index: 10;
  4. }
  5. h1#pos span {
  6. position: absolute;
  7. left: 1px;
  8. top: 1px;
  9. z-index: -1;
  10. }

Efekt:

Text duplicate

Zaobserwowałem dziwny błąd na IE (musisz żartować!) w wersji 6 i 7. Otóż jeśli ustawimy letter-spacing w em-ach dla h1 to w zależności od wielkości tekstu, span będzie potrzebował innych wartości odstępu między literami. Da się metodą prób i błędów dograć jedno i drugie, ale o wiele prościej jest zaaplikować layout dla h1.

Generowana zawartość

Sposób prawie identyczny jak poprzedni - jedyny plus to że przenosimy większość modyfikacji na dokumencie do warstwy prezentacji. Jedyny minus to brak wsparcia dla GC przez IE (choć i to można obejść) oraz błędy w Firefoksie. Opera pięknie sobie radzi. HTML:

  1. <h1 id="gc" title="Generated content">
  2. Generated content
  3. </h1>

Wykorzystujemy dodany atrybut title (znowu - można go dodać w JS i zlikwidować jakiekolwiek zmiany w HTML) zawierający tekst nagłówka w CSS:

  1. h1#gc::before {
  2. content: attr(title);
  3. position: absolute;
  4. margin-top: 1px;
  5. margin-left: 1px;
  6. z-index: -1;
  7. }

Efekt:

Generated Content

Z powyższych testów wynika, że osiągniemy zadowalające rezultaty tylko poprzez powielenie tekstu (ręczne bądź skryptowe), któremu chcemy zaaplikować cień. Możemy jednak zapanować tylko nad jego kolorem i odstępem, efekty rodem z Photoshopa należy zostawić do czasu szerokiego wsparcia dla text-shadow.

A tymczasem Webkit miecie - screen z wszystkich trzech testów. ;-)

Informacje i hiperłącza

Blog o projektowaniu zgodnych ze standardami stron internetowych.

Praktyczne przykłady, sztuczki CSS, sposoby obchodzenia błędów przeglądarek, lekki i nieinwazyjny JavaScript, użyteczny design, dostępność i skrypty użytkownika.

RSS

Informacje o wpisie

Napisał riddle 31 stycznia 2007 o 02:34

Kategorie: CSS, Design, Internet Explorer

Dodaj do:

Wpisy archiwalne

Archiwum miesięczne

Dzięki!

Dodaj bloga do Technorati Favorites Dodaj bloga do Del.icio.us Blog należy do sieci 10przykazań.com

  1. Czyli czekamy na Cairo i Fx 3.0 :)

  2. Wow? Szkoda, że wciąż odbija się na nas wojna przeglądarek…
    Btw. pierwszy raz widzę coś takiego jak: attr(title) :-)

  3. Webkit ogólnie wymiata ze swoimi cieniami, pornel już nawet o tym pisał i dał nawet fajnego screena

  4. Wewnętrzna wersja Opery (Peregrine) też obsługuje text-shadow. Wspominał o tym quiris.

  5. Istnieje tez juz (prawie: alpha) webkitowa przeglądarka dla Win32 – Swift ;)
    http://try.swift.ws/index.php/Main_Page

    PS. Riddle, nie poprawiles tego zaslonietego obrazka z kodem ;)

  6. Dla ścisłości: Konqueror używa KHTML, Webkit to jego pochodna; KHTML po jakimś czasie zasymilował część zmian Webkitu.

  7. Cienie w przeglądarce Mac OS X wykorzystują systemowy efekt, więc Swift nie wyświetli text-shadow pod Windowsem. Prędzie zrobi to Konqueror, którego już teraz można spróbować instalować na Windowsie (wraz z KDE).

    Poza tym text-shadow ma jeszcze fantastyczną opcję rozmycia, której żadne sztuczki CSS/JS nie osiągną.

  8. (Komentarz zmodyfikowany 31.01.2007 o 13:22)

    Ostatni przykład w FF 2.0.0.1 nie działa

  9. Mam Swifta, ale nie za bardzo się jeszcze nadaje do testów.

    Warum: A no właśnie, coś mi się o uszy obiło. Miło słyszeć. :-)
    mcv: Racja.

  10. Zdaje się, że w ostatnim przykładzie powinien wystarczyć jeden dwukropek: h1#gc:before { /* ... */ }

    Nie orientujesz się, kiedy w Firefox’ie (Gecko) pojawi się obsługa text-shadow?

  11. (Komentarz zmodyfikowany 31.01.2007 o 13:52)

    Riddle: to że u mnie nie działa, to jest powód, żeby moderować to co napisałem?

  12. Pala: U mnie też nie działa. Nie przeczytałeś uważnie tego co tam napisałem.
    Speedy: Pseudoelementy mają dwa ::

  13. Riddle: Ano napisałeś – błędy w Firefoxie, ale nie pomyślałem, że aż takie ;)

    Mi się marzy, żebym mógł napisać:

    text-shadow: 2px 2px 1px #2f6a34;

    i żeby wszędzie działało ;]

  14. @Riddle – dwa dwukropki to do wywołań statycznych przy programowaniu obiektowym się między innymi stosuje, a nie w CSS’ie No chyba, że używasz innej wersji niż ja. ;)

    http://pl.wikibooks.org/wiki/CSS#Pseudoelementy

  15. Speedy: Tak właśnie jest, ja używam notacji CSS3 dla pseudoelementów. ::before, ::selection, etc…

  16. Speedy: Chyba w C++ ;þ
    W CSS3 jeden dwukropek jest do pseudoklas, dwa dwukropki do pseudoelementów. Nie wiem czy przypadkiem jakieś CSS2-revision-ileśtam też nie używa dla pseudoelementów dwóch dwukropków.

  17. całkiem miły efekt, ale możliwy do osiągnięcia również w programach graficznych

  18. obserwator, chodzi o to, aby nie ich w tym wypadku nie dotykać...

    Ale na chwilę obecną, to chyba jest jedyne rozwiązanie, żeby wszędzie działało jak należy…

  19. @obserwator:
    Przy treści generowanej po stronie serwera będę robił osobny obrazek dla każdej literki?

  20. Mi się marzy, żebym mógł napisać: text-shadow: 2px 2px 1px #2f6a34; i żeby wszędzie działało ;]

    x,y i rozmycie?
    Do tego dodałbym jeszcze 8bitową alfę dla cienia.
    Bardziej wymagający zażyczyliby sobie do tego parametru definiującego prędkość przenikania, maniacy już będą się domagać cienia perspektywicznego, bo izometria ich nie zadowala. W ostateczności dojdzie do momentu, że łatwiej byłoby zdefiniować już w 3wymiarowej przestrzeni pozycję tekstu i wszystkich źródeł światła, co zresztą rozwiązałoby problem kształtu krawędzi cienia zależnie od powierzchni pod tekstem, odczytanej za pomocą osobnej mapy :)

    Aaa! Omal bym zapomniał o „multimedialistach”. Wszystkie te elementy mogą się zmieniać i przemieszczać, a zmiany mają być widoczne w czasie rzeczywistym.

    Każdemu się marzy, ale niestety to nie jest takie proste. Już na samą myśl o tym, jak tęgie głowy próbują sprecyzować wszystko, przykro mi się ich robi.

  21. (Komentarz zmodyfikowany 19.08.2007 o 15:06)

    Witam,

    prosimy o pilny kontakt. Jesteś finalistą konkursu Bloger Roku 2006. Chcielibyśmy podesłać Ci kilka niezbędnych informacji organizacyjnych. Niestety, dostajemy zwrotki przy wysyłaniu maili na skrzynkę w googlach.

    Pozdrawiam,
    Adam Plona

  22. (Komentarz zmodyfikowany 19.08.2007 o 15:06)

    Riddle: W związku z powyższym, gratuluję ;)

  23. Normalnie aż szkoda, że nie ma pełnego portu WebKita dla Windowsa, przynajmniej mógłbym też coś potestować. Ten silnik nieźle się ostatnimi czasy rozwija, szczególnie w dziedzinie CSS implementuje sporo „bajerów”, których jeszcze nie mają inne przeglądarki, typu text-shadow, box-shadow, czy ostatniej nowości – layoutu wielokolumnowego (czy jak tam to poprawnie po polsku nazwać. Ogólnie chodzi o CSS Columns), który AFAIK obecnie implementuje tylko Gecko 1.8+

    Trudność w portowaniu Webkita polega między innymi na tym, że w niektórych miejscach wykorzystywane są natywne możliwości samego systemu operacyjnego MacOS.

  24. Rafael:
    Ze starszymi Gecko da się coś tam wykombinować, używając -moz-column-width, -moz-column-gap oraz -moz-column-rule.

    A poza tym box-shadow i wygładzone border-radius… uch, przydało by się w innych silnikach, przydało. ;-)

  25. Jeśli możesz Riddle’u, to powiedz mi, w jakim celu w notacji CSS3 pseudoelementy posiadają dwa dwukropki? Nie wystarczyło pozostawić jednego?

    Żeby nie zostać oskarżonym o paplanie nie na temat, napiszę coś na temat omawianego tematu. :-)

    Cień dla tekstu to – dla mnie – jeden z ciekawszych efektów wchodzących w skład CSS3. Nie mogę się doczekać, aż najlepsze przeglądarki dla Windows zaczną wspierać ten styl. Wymienione w tym temacie sposoby na otrzymanie efektu w podobnego do text-shadow są bardzo ciekawe. Szczególnie fajny, choć trochę nieprzydatny, jest numer z Generowaną zawartością. Pokazuje on jak zmyślną rzeczą jest CSS. :-)

  26. WebKit sobie radzi i jest szybki, ale… na JS muli :( .

  27. Opera/9.50 ma text-shadow :D

  28. Nasz ulubiony IE chyba ma „odpowiedni filtr” cienia i nazywa się on Shadow?

  29. We wpisie masz przykład użycia takiego filtru i jego wynik. Jest za brzydki, żeby można było go używać. :(

  30. Mój błąd, przepraszam. Choć przyznam że to screeny z IE mnie zmyliły. Nie wiem która to wersja wynalazku Microsoftu, ale w IE6 (cóż nie ma już wsparcia ze strony MS dla mojego systemu – Windows 2000, dlatego nie przejmuję się IE7, co z resztą przy ilości użytkowników ma stosunkowo niewielkie znaczenie) oba filtry działają „poprawnie”.
    Odnośnik do dokumentu HTML
    Odnośnik do screena z IE

  31. Wydaje mi się, że nie masz włączonego ClearType. Dodam, że na przykład IE7 ma domyślnie. Generalnie więc te filtry są bezużyteczne.

  32. Stąd mój błąd, gdyż dopiero Windows XP był pierwszym Windowsem zawierającym ClearType. Choć warto pamiętać, iż nawet użytkownicy WinXP zwykle używają IE6 i zwykle nie mają włączonego ClearType.

Dodaj komentarz

Do formatowania komentarzy używaj Textile (HTML nie działa). Szczególnie jeśli wklejasz większe fragmenty kodu. W razie niepewności użyj podglądu komentarza.

Wypowiedzi obraźliwe, infantylne oraz nie na temat będą moderowane – pisząc postaraj się zwiększyć wartość dyskusji.

Komentarze nie służą do wysyłania wiadomości albo informowania o błędach, itd. Chcesz coś mi napisać – skontaktuj się.