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.

CSS outer glow screen

Przygotowując kawałek kodu JavaScript zechciałem wyraźnie zaznaczyć, że pływająca warstwa znajduje się nad resztą strony. Oczywistym wyborem był cień – wyzwanie polegało na tym, że chciałem aby był prawdziwie półprzezroczysty oraz wyglądał inaczej (IMO: lepiej). Od zawsze podobał mi się efekt Outer Glow w Photoshopie, stąd i taki zamierzałem zrobić w CSS.

Na początku zamierzałem podejść jak do zwykłego cienia – siatka ala tabelka, gdzie wymiary rogów pokrywają się z wysokością i szerokością cieni poziomych i pionowych. Problem w tym, że tworząc prawdziwą poświatę, obszar w którym należy zawrzeć róg jest znacznie większy niż reszta efektu.

Photoshop Slices

Z tego powodu odpada rozwiązanie wykorzystujące wysokość zawartości warstwy do rozciągnięcia cieni pionowych – albo powstanie pusta przestrzeń na górze i dole albo cienie będą się nachodzić (ciemniejsze miejsca, jako że używamy PNG z kanałem alpha). Kolejny minus wynikający z takiego rozwiązania to stała szerokość warstwy (aby filtry IE działały)

Postanowiłem umiejscowić każdy fragment poświaty przez pozycjonowanie absolutne, wykorzystując fakt, że łącząc left z right oraz top z bottom, można rozciągnąć element na dowolnej przestrzeni. Jedyną przeglądarką nie potrafiącą tego zrobić jest oczywiście Internet Explorer 6, ale i tym się zajmiemy.

Struktura cienia

HTML jest dość złożony, ale zakładam że wszystkie dodatkowe elementy zostaną wygenerowane w JavaScript.

  1. <div class="layer">
  2. <div class="content">
  3. <p>Lorem…</p>
  4. </div>
  5. <div class="shadow-top">
  6. <div class="left"></div>
  7. <div class="center"></div>
  8. <div class="right"></div>
  9. </div>
  10. <div class="shadow-middle">
  11. <div class="left"></div>
  12. <div class="right"></div>
  13. </div>
  14. <div class="shadow-bottom">
  15. <div class="left"></div>
  16. <div class="center"></div>
  17. <div class="right"></div>
  18. </div>
  19. </div>

Podstawy

Mimo że nie jest to wymagane, na początek ustawiłem szerkość warstwy na 50% oraz dodałem padding równy wymiarom cieni w pionie i poziomie (demo).

  1. .layer {
  2. margin: 20px;
  3. width: 50%;
  4. padding: 23px;
  5. position: relative;
  6. background-color: #fcc;
  7. }
  8. .layer .content {
  9. padding: 10px;
  10. background-color: #fff;
  11. }

Pozycjonowanie

Teraz wypada dodać najprostsze elementy - narożniki. Wszystkie kawałki cienia będą pozycjonowane absolutnie względem div.layer.

  1. .layer {
  2. position: relative;
  3. }
  4. .layer .left,
  5. .layer .right,
  6. .layer .center {
  7. position: absolute;
  8. }
  9. .layer .shadow-top .left,
  10. .layer .shadow-top .right,
  11. .layer .shadow-bottom .left,
  12. .layer .shadow-bottom .right {
  13. width: 45px;
  14. height: 45px;
  15. background-repeat: no-repeat;
  16. background-position: 0 0;
  17. }

Wrzucamy obrazki (demo):

  1. .layer .shadow-top .left { background-image: url(../tl.png); }
  2. .layer .shadow-top .right { background-image: url(../tr.png); }
  3. .layer .shadow-bottom .left { background-image: url(../bl.png); }
  4. .layer .shadow-bottom .right { background-image: url(../br.png); }

Teraz najważniejsza część. Pozostałe divy należy odsunąć z obu stron od krawędzi o szerokość narożnika, co spowoduje rozciągnięcie w poziomie (demo):

  1. .layer .shadow-top .center,
  2. .layer .shadow-bottom .center {
  3. height: 23px;
  4. right: 45px;
  5. left: 45px;
  6. background-repeat: repeat-x;
  7. background-color: #fcc;
  8. }

I pionie (demo):

  1. .layer .shadow-middle div {
  2. width: 23px;
  3. bottom: 45px;
  4. top: 45px;
  5. background-repeat: repeat-y;
  6. background-color: #cff;
  7. }

Pozostało jeszcze przesunąć narożniki pod .content, zwiększając temu ostatniemu z-index (demo).

Poprawki dla IE6. Yeah.

Dla Internet Explorera 6 należy natomiast zemulować rozciągnięcie pozycjonowaniem przez dynamiczne nadawanie width i height na podstawie wymiarów rodzica. Oraz oczywiście ustawić przezroczystość wszystkich PNG przez filtry.

Dodajemy arkusz stylów ie.css, usuwamy tło z wszystkich elementów.

  1. .layer .left,
  2. .layer .right,
  3. .layer .center {
  4. background: none !important;
  5. }

Aby ustawić przezroczystość dla narożników używamy filtru z sizingMethod ustawionym na crop – w odróżnieniu od cieni poziomych i pionowych, gdzie należy wstawić scale.

  1. .layer .shadow-top .left { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../tl.png", sizingMethod="crop"); }
  2. .layer .shadow-top .center { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../t.png", sizingMethod="scale"); }

Dokładny mechanizm tych filtrów jest opisany w podlinkowanym wcześniej artykule. Pamiętajmy też o poprawności ścieżek plików (taka sama reguła jak przy .htc) (demo).

Teraz przychodzi czas na nasze ulubione expressions. Przykładowo dla poziomych elementów:

  1. .layer .shadow-top .center,
  2. .layer .shadow-bottom .center {
  3. height: expression(
  4. x = this.parentNode.parentNode.offsetWidth,
  5. y = parseInt(this.currentStyle.left),
  6. x - (y * 2) + 'px'
  7. )
  8. }

Co tutaj się dzieje? Na początku przypisuję do zmiennych wysokość elementu .layer oraz aktualny odstęp od lewej, aby użyć ich poniżej. To samo powtarzamy dla elementów pionowych, używając offsetHeight oraz top.

Wszystko już jest prawie dobrze – oprócz momentu kiedy cień minimalnie nachodzi na narożniki. Trochę zabawy ze zmianą rozmiaru okna i tekstu (+ debugowanie via element.innerHTML gdy to pierwszy raz zobaczyłem ;)) i widać, że błąd pojawia się co 2 piksel.

Rozszerzyłem więc obliczenie dodając warunek sprawdzający czy nie ma reszty z podzielenia szerokości .layer przez 2 i wtedy odejmuję jeden dodatkowy piksel od wynikowej szerokości cienia. Wygląda to tak:

  1. (x - ((x % 2) ? 1 : 0) - (y * 2)) + 'px'

Tę samą linijkę można dorzucić do pionowych elementów (.layer .shadow-middle div).

I w ten oto sposób mamy upragnioną warstwę z ładnym, estetycznym (także: innym niż się widuje w sieci) i rozciągliwym cieniem działającym na każdej przeglądarce (testowałem w Fx, Operze, Safari i obu IE). A ja teraz muszę wykorzystać to co stworzyłem. :)

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 28 lipca 2007 o 23:54

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. ja zawsze miałem problem z tymi cieniami więc starałem się ich unikać, przeważnie robiłem background-image; z pikseowym paskiem gdzie zawarte były cienie po jego bokach, a potem cień nad polem (img) i cień pod polem (img), ale to dobre było dla stałej szerokości

  2. Dzięki!!! Porządny wpis. Dałbym ci coś, gdybym miał, ale paypal pusty :( Jeszcze raz gratulacje dobrego wpisu.

  3. Nie ma to jak warstwa z cieniem :) Ja z tym tematem walczyłem dość długo, ale z reguły cienie dla boków robiłem o tej samej szerokości co róg – fakt, że wszystko zależy od grubości cienia – im mniejsza tym problem mniejszy :) Swoją drogą preferuję delikatniejsze cienie (czytaj: mniejsze) niż te w prezentowanym przykładzie.

    Jako, że temat mam jako tako rozpracowany to najbardziej z całego opisu chyba spodobała mi się forma przedstawiania kolejnych przykładów :) Przy pierwszym demie jeszcze nie zajarzyłem o co chodzi, ale przy kolejnych pojąłem tą fajną ideę :) Tak trzymać z nią – chociaż pewnie nie zawsze idzie ją zastosować :)

    BTW po jednym z wpisów na Twitterze miałem cichą nadzieję, że ten wpis będzie traktował o jQuery – mam nadzieję, że nie każesz nam (bo myślę, że nie tylko ja oczekuję kursu jQuery) długo czekać na ten kurs ;)

    Przy okazji tematu tego wpisu nasuwa mi się jedno pytanie – czy nie dałoby rady rozwiązać tego jakoś inaczej zamiast tworzenia tej swoistej „tabelki” z cieniem ? W sumie mnie nasuwa się na myśl takie rozwiązanie – wykorzystać kilka divów w stylu spiffy corners z odpowiednim poziomem przezroczystości i koloru tła ułożonych za pomocą z-index. z-index nie zaszkodzi bo te cienie są z reguły używane przy okienkach umieszczanych nad tekstem, a przy mniejszym cieniu ilość potrzebnych divów będzie dość mała i całość nie będzie wymagała grafiki. Jak ilość tych warstw byłaby mała to można też użyć skryptu generującego zaokrąglenia w „locie”. To takie moje teoretyczne rozważanie, bo nigdy tego w praktyce nie stosowałem, ale myślę, że zyskalibyśmy dwie korzyści – brak grafiki i do tego nie powinno być większych problemów z implementacją elastyczności okienka w różnych przeglądarkach.

  4. (Komentarz zmodyfikowany 29.07.2007 o 00:54)

    zachciałem

    Chyba zechciałem :).

  5. Dziudek: Chyba jednak nie doczytałeś wpisu uważnie, bo napisałem że układanie tego wszystkiego w document-flow powoduje przerwę oraz wymusza stałą szerokość .layer. :)

  6. @Riddle – no nie zagłębiałem się we wszystko bo generalnie jestem już trochę zmęczony i tylko przeanalizowałem całą ideę tego patentu ;) W każdym razie moja teoria upadła szybko – ale trzeba szukać ciągle jakichś innych metod rozwiązania tego zagadnienia – a nuż się uda wymyślić coś lepszego :)

  7. Tak czy siak, jakby ktoś chciał sam potworzyć takie cienie, to może zacząć od mojego pliku PSD.

  8. (Komentarz zmodyfikowany 29.07.2007 o 12:34)

    Te linki (demo) to takie ‘Kliknij tutaj’ – zaraza Internetu że tak przypomnę Twój starszy wpis ;)
    A co do merytorycznej części, to teraz jestem zbyt zmęczony na przeczytanie tego ze zrozumieniem, ale temat ciekawy i trochę niewdzięczny dla webmastera

  9. (Komentarz zmodyfikowany 29.07.2007 o 12:35)

    @Taeril – chyba ciut przesadzasz – te linki są moim zdaniem dobrze wplecione w treść wpisu (za pomocą nawiasów)...

  10. Coś takiego na pewno komuś się przyda. Ba, możliwe, że sam niebawem zastosuję, tylko że nie cień :)

  11. Kuba Bogaczewicz 11 29 lipca 2007, 11:08

    A ja się trochę czepię „ulubionych expressions” – moim zdaniem wyciąganie takiej armaty jest tutaj trochę nie tak. Znaczy ok, dla pokazania że się da są spoko, ale na produkcyjnej stronie nie użyłbym ich, szczególnie do uzyskania tak w gruncie rzeczy nieistotnego efektu – dla IE zrobiłbym prostsze cienie byle tylko cały czas trzymać się czystego CSS.

    Dlaczego? A sprawdzałeś dokładnie ile razy takie expression jest wywoływane na stronie? Jest wywoływane przy każdym zdarzeniu na tagu html, np przy… ruchu myszką na stronie.

    Dlatego jak dla mnie to jest rozwiązanie ostateczne i tylko dla rzeczy które są kluczowe dla strony. Stosowanie ich jako fajnej metody obejścia problemów IE może szybko zrobić więcej problemów niż korzyści.

  12. Bardzo ciekawy artykuł, na pewno wykorzystam.

    Bardzo wiele już się nauczyłem dzięki lekturze Twojego bloga, oby więcej takich. Wielkie dzięki! :)

  13. Kuba: Expressions zostały zaprojektowane do wywoływania przy każdym evencie i Explorer nie przerysowywuje layoutu za każdym razem, nawet jeśli nic się nie zmieni (przykładowo mouseover nie zmienia wysokości diva, ani rozmiaru tekstu) – dlatego zarzut o wydajność jest chybiony. Expression nie działa dokładnie tak jak JavaScript – Microsoft dokładnie wiedział do czego będą używane (wystarczy popatrzeć na przykłady z MSDN) i zaręczam Cię, że nie zdarzyło mi się spowolnić nimi strony. Oczywiście – można przesadzić, ale trzeba chyba nie znać się kompletnie na JS, żeby to zrobić.

  14. (Komentarz zmodyfikowany 29.07.2007 o 19:17)

    No fajne, fajne, ale chyba coś jest nie tak na IE6: screen
    IE6 jest najnowsze, JS jest włączony itd..

    PS1. Po kliknięciu na „Podgląd” w formularzu dodawania komentarza po przeładowaniu strony w pole „Kod” wpisywana jest zawartość ze „Strona WWW”.

    PS2. Po co ten śmieszny znaczek w miejsce dnia i roku w dacie dodania wpisu? A jeśli ja chcę od razu wiedzieć którego dnia dany wpis został dodany?

    PS3. Sorki, że tak wcinam się z tymi komentarzami co do designu bloga, ale teraz zauważyłem (O9.22): dlaczego numerki lini w blokach kodu są „wcięte” razem z tekstem?

  15. Jak coś jest przeźroczyste to tego nie widać. Tu chodzi o półprzeźroczystość.

  16. Odnośnie alphy poprzez expressions – zauważyłem, iż pod IE po wstawieniu obrazka z alphą pod tło niemożliwe jest kliknięcie w link umieszczony na tej warstwie. Znasz może metodę na uaktywnienie takiego linka?

  17. Faxe, masz rację.

    Zboczuch, musisz ustawić position: relative dla tego linka. Czasem jednak to nie działa – przeczytaj wtedy bardziej złożoną metodę obejścia.

  18. Dzięki – tego było mi trzeba. :)

  19. Hej. Bardzo fajne rozwiązanie. Akurat w momencie kiedy miałam usiąść i pomyśleć jak zrobić coś podobnego :)

    Ja akurat potrzebowałam nadać cień elementowi, któremu nie można określić szerokości. W IE6 się nie rozjedzie jeśli nada mu się float’a (w przykładzie Riddla .layer). Pozdrawiam.

  20. if i make positioned layers with css-rollovers inside, using alpha-blended .png images does the same effect (?)

  21. I guess it does. Can you provide more detailed explanation of your case?

  22. nie mam pytań do tego rozwiązania. nie mam. gratuluję.

  23. Genialne.

  24. Mam takie pytanie do ciebie o ile masz checi. Probuje wykorzystac twoj sposob na krawedzie w blokach. Oto link do zdjecia: http://www.jezykepbp.user.icpnet.pl/oz/menu.jpg. Czy masz moze jakies propozycje jak podzielic ten obrazek. Chcialem zrobic w dowoch blokach gora i dol ale w IE6 robi mi sie odstep miedzy blokami, i nie wiem co z tym zrobic. Podzielibym obrazek na 6 czesci z czego 2 beda powtarzalne.

    P.S. Jezeli nie zamierzasz wyrazic swojej opinii prosze o usuniecie komentarza.

  25. Lubię korzystać z gotowych rozwiązań, którym mogę ufać, dzięki.
    A tak btw, to żeby uczynić to rozwiązanie bardziej bulletproof, to dorzuć do kodu to (pewno jasne jest po co):
    .layer .left, .layer .right, .layer .center { font-size: 0; }

  26. Używam głównie IE gdyż to ona jest standardem w sieci , niezależnie od ilości przytoczonych argumentów ze strony W3C . Zastanawia mnie jedynie dlaczego CSS tak słabo się rozwija – gdybyście wiedzieli jak mało osób zezwala na działanie skryptów Java to zapewne przestalibyście go się uczyć .
    Microsoft przygotowuje HTML 5 – interaktywny html ! – co na to powie W3C ?

  27. Czy da się zastąpić czymś innym „expression” dla IE?

  28. Czy da się zastąpić czymś innym „expression” dla IE?

  29. @romskey
    „Używam głównie IE”
    Współczujemy ci i łączymy z tobą w bólu :)
    „gdyż to ona jest standardem w sieci , niezależnie od ilości przytoczonych argumentów ze strony W3C”
    Ilość użytkowników nie świadczy o standardzie.
    „Microsoft przygotowuje HTML 5 – interaktywny html ! – co na to powie W3C ?”
    To co wszyscy: „Precz z MS i jego pseudowynalazkami utrudniającymi każdemu życie!”

    Co do rozwiązania: fajne, ale ma błędy. Wstaw w nie jakiś krótki tekst – np. jedno słowo. Raczej powinno być jakoś tak: http://www.2shared.com/file/3636275/923d558d/test.html

    I fajnie by było, gdyby szerokość dopasowywała się do zawartości, i nie trzeba było podawać width:45%.

  30. Współczucie jest zupełnie niepotrzebne . To zwykła logika. Skoro 80% internautów uzywa IE to ona dyktuje warunki . Mozna się z tym zgadzać lub nie ale nazywanie standardem czegoś co jest stosowane przez kilkanaście procent e-ludzkości to dyrdymał na skalę kataklizmu . Tworzycie absurdalną promocję – bo mi na przykład – zależy aby moje strony otwierały się wszędzie tak samo , wam jak widać na tym nie zależy . Dlaczego Opera i Firefox nie stosują tych samych rozmiarów czcionek ? Czyżby standardy były traktowane dowolnie ? Bill odszedł na emeryturę więc macie swoje pięć minut . Życie utrudniają standardy które standardami nie są choć chcą być .
    Jestem zwolennikiem współpracy a nie robienia złego piaru . We wszystkich gazetach piszą o tym że sprowadzane samochody to złomy . Nie jeden dealer jednak chciałby mieć obroty firm które tymi ‘złomami’ się zajmują .
    Rynek ma swoje prawa i potrzeby , nadymanie się w imię jakiejś wydumanej trendowości to przegięcie .

  31. Cześć, próbuję zrobić ten tutorial, nie mówie tu o hack for IE, tylko tej samej podstawie, stworzylem sobie obrazki 45 px X 45 px, uzylem tego cssa, wszystko powpisywalem i niestety moje obrazki nie chca sie rozmiescic po rogach, tylko sa skumulowane pod bialym tlem. Nie wiem o co c'mon moj html to:

    Lorem

    a CSS:

    .layer {
    margin: 20px;
    width: 50%;
    padding: 23px;
    position: relative;
    background-color: #fcc;
    }

    .layer .content {
    padding: 10px;
    background-color: #fff;
    }

    .layer {
    position: relative;
    }

    .layer .left,
    .layer .right,
    .layer .center {
    position: absolute;
    }

    .layer .shadow-top .left,
    .layer .shadow-top .right,
    .layer .shadow-bottom .left,
    .layer .shadow-bottom .right {
    width: 45px;
    height: 45px;
    background-repeat: no-repeat;
    background-position: 0 0;
    }

    .layer .shadow-top .left { background-image: url(tl.png); }
    .layer .shadow-top .right { background-image: url(tr.png); }
    .layer .shadow-bottom .left { background-image: url(bl.png); }
    .layer .shadow-bottom .right { background-image: url(br.png); }

    czy cos zle zrobilem? Odpisz jesli masz czas, bylbym wdzieczny

  32. jeszcze raz ten html :):

    1.<div class="layer">
    2. <div class="content">
    3. <p>Lorem</p>
    4. </div>
    5. <div class="shadow-top">
    6. <div class="left"></div>
    7. <div class="center"></div>
    8. <div class="right"></div>
    9. </div>
    10. <div class="shadow-middle">
    11. <div class="left"></div>
    12. <div class="right"></div>
    13. </div>
    14. <div class="shadow-bottom">
    15. <div class="left"></div>
    16. <div class="center"></div>
    17. <div class="right"></div>
    18. </div>
    19.</div>

    oczywiscie bez tej liczby porzadkowej :)

  33. Sory ze tak nabijam posty, ale jestem ciekawy jak powinien wygladac css w calosci.

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ę.