Kawałek Kodu

I choć szeptem opowiadasz koleżance z pracy jaki to nowy kolega jest nieokrzesany, to i tak jakimś cudem okazuje się, że on stoi za Twoimi plecami od minuty i wszystko już usłyszał. Język drętwieje i można się nieźle zmieszać. A skoro jesteśmy przy plotkowaniu, to obgadamy funkcję mało znaną, która potrafi zmieszać podwójnie.

Jak mieszać po staremu?

Mamy kilka opcji zmieszania dwóch teł/obrazów w CSS. Pierwsza z nich, chyba najstarsza, to tzw. rollover, czyli podmiana źródła obrazka po najechaniu myszą. Niestety podmieniająć źródło na nowe obrazek musiał się doczytać, co powodowało efekt migotania w pierwszej chwili. Tu rozwiązaniem był preloading drugiego obrazka, tak aby w momencie potrzeby użycia go (czyli drugiej fazy) był już gotowy. Do tego był używany JavaScript, a kod wyglądał mniej więcej tak:

document.getElementById('mouseover', function() {
  this.src = 'obrazek2.gif';
})

document.getElementById('mouseout', function() {
  this.src = 'obrazek1.gif';
})

Inna metoda, którą można wykorzystać zarówno przy użyciu JavaScript jak i tylko CSS, to użycie dwóch obrazków. Przed najechaniem widoczny jest tylko pierwszy obrazek, drugi po najechaniu. Tu jednak tworzymy nadmiarowe znaczniki HTML. Ale są również i zalety. Mając dwa elementy możemy niezależnie sterować przezroczystością każdego z nich. Czyli oprócz siermiężnego rollover, mamy płynny cross-fade, ale musimy wypozycjonować elementy absolutnie, aby jeden był po drugim, a nie obok siebie lub pod. No i drugi obrazek jest załadowany przed drugą fazą (choć to dodatkowe żądanie do serwera).

Tu ukrywamy po prostu niepotrzebną fazę:

div img:last-child,
div:hover img:first-child {
  display: none;
}

div:hover img:last-child,
div img:first-child {
  display:inline;
}

W przypadku użycia opacity i ewentualnie transition musimy użyć pozycjonowania, bo element z opacity:0 i tak zajmuje przestrzeń.

div img {
  position: absolute;
  left: 0;
  top: 0;
  transition: opacity .25s linear;
}

div img:last-child,
div:hover img:first-child {
  opacity: 0;
}

div:hover img:last-child,
div img:first-child {
  opacity: 1;
}

Jeśli nie chcemy używać transition, czyli stworzyć rollover, to chyba najbardziej optymalne będzie użycie sprite'ów. Czyli dla obydwu faz używamy jednego obrazka, który podstawiamy jako tło elementu. Ale tylko ten fragment (połowę), którą chcemy pokazać.

div {
  background-image: url(obrazek.gif);
  width: 64px;
  height: 32px;
}

/* nasz obrazek ma wysokość 64px,
   więc przesuwamy go w górę
   o wysokość kontenera,
   dzięki temu widzimy
   drugą, dolną połowę 32px
*/
div:hover {
  background-position: 0 100%;
}

Jak mieszać tak jak nikt nie potrafi?

Mamy też inną metodą, która wkracza na salony zamaszystymi krokami jest funkcja cross-fade. Wkracza dopóki się nie rozkraczy, bo jak na razie wsparcie jest średnie i do tego mamy dwie zupełnie inne sposoby implementacji. Jedną dla Firefox, drugą dla Safari, Chrome i Opera. No dobra, ale o co chodzi?

Funkcja cross-fade jest możliwa do użycia w background-image i możemy wskazać dwa lub więcej obrazków (w zależności od implementacji) oraz ich procentowe wymieszanie. Niestety nie jest animowalna, więc raczej do użycia w roli rollover, no chyba, że chcemy stworzyć animację wieloklatkową i w każdej z nich podawać różne wartości procentowe. Ale to chyba traci sens.

Implementacje, jak wspomniałem, są dwie:

  • background-image: cross-fade( url() wartosc_procentowa, url() wartosc_procentowa [,...])
  • background-image: cross-fade( url(), url(), wartosc_procentowa)

W przypadku pierwszej możliwe jest użycie więcej niż dwóch obrazków i co ciekawe wartości procentowe nie muszą sumować się do 100%, czyli możemy pokazać tło sklejone z trzech obrazków o opacity 0.5 (wartosc_procentowa=50%). Jeśli przy jakimkolwiek tle nie użyjemy wskażemy w jakim procencie ma się mieszać, to wartość ta będzie obliczona jako średnia ze wszystkich brakujących wartości. Mając trzy tła bez procentów, każde z nich uzyska 33.33% zmieszania. Przy dwóch tłach i jednym z ustawionymi 75%, drugie uzyska 25%. Jeśli byłyby to trzy tła, to drugie i trzecie miałoby 12.5%.

Druga implementacja (wspierana przez Safari oraz Chrome z prefiksem) pozwala na użycie tylko dwóch teł, a co za tym idzie wartość procentowa jest wskazywana tylko dla pierwszego tła. I musi być wskazana. Zauważ, że obydwie implementacje nawet przy dwóch obrazkach nie są analogiczne.

CSS dla rollover w przypadku użycia pierwszej metody:

div {
  background-image:
    cross-fade(
      url(obrazek1.jpg) 100%,
      url(obrazek2.jpg)
    );
  width: 64px;
  height: 64px;
}

div:hover {
  background-image:
    cross-fade(
      url(obrazek1.jpg) 0%,
      url(obrazek2.jpg)
    );
}

Dla drugiej:

div {
  background-image:
    -webkit-cross-fade(
       url(obrazek1.jpg),
       url(obrazek2.jpg),
       100%);
  width: 64px;
  height: 64px;
}

div:hover {
  background-image:
    -webkit-cross-fade(
       url(obrazek1.jpg),
       url(obrazek2.jpg),
       0%);
}

Działanie nie będzie się różnić od standardowego rollover.

Ale w background-image możemy użyć przecież pełnego koloru lub gradientu. Niestety nie pokażę Ci tej możliwości, bo implementacja numer 2 nie obsługuje gradientów i kolorów, a implementacja numer 1, choć nowsza i opisywana przez Mozillę, nie działa nawet w swojej podstawowej wersji na Firefox.

Chyba jednak trzeba pozostać przy starej metodzie mieszania... Do przeczytania!

 

Przydatne? linki:
Funkcja cross-fade