Ostatnie wiadomości
Słowem wstępu - wiem, LESS to nic nowego, ale jak już pisałem wcześniej chcę pisać tylko o tym, czego sam używam i co mogę z czystym sumieniem polecić.
CSS i jego niedoskonałości
Każdy kto para się webdeveloperką wie co to CSS i chociażby standard 2.0 ma w małym palcu. Jeżeli tak, to doskonale też wie, czego w CSS brakuje - zagnieżdżania reguł, możliwości definiowania zmiennych, możliwości wykorzystywania tego samego kodu w wielu miejscach etc. Jak wiadomo - przyroda nie toleruje pustki, na skutek czego powstawały rozwiązania pozwalające na stosowanie w/w rozwiązań - działające zarówno po stronie serwera (np. stosowanie plików PHP do generowania CSS) lub po stronie klienta (wykonane w JS).
Światełko w tunelu - LESS
Aktualnie najpopularniejszym rozwiązaniem z grupy tych drugich jest LESS. Jego stosowanie ogranicza się do zmiany nazwy arkusza stylów z .css na .less oraz dodanie samej biblioteki do strony. Po tych zabiegach możemy korzystać już z pełnych dobrodziejstw, jakie oferuje skrypt. Popularną alternatywą jest SASS. Oba z tych języków są bardzo podobne zarówno pod wzg. możliwości jak i składni, więc wybór sprowadza się do osobistych preferencji programisty.
Zmienne
Podstawową funkcjonalnością, jaką oferują nam biblioteki tego typu, jest możliwość stosowania zmiennych. Dzięki temu możemy szybko np. zmienić kolor wielu elementów czy przesunąć serię bloków na stronie. Zmienne są też najłatwiejszym do opanowania elementem, przykładowy dokument .less:
@red: #ff0000;
@blue: #00ff00;
#naglowek {
color: @red;
background: @blue;
font-size: 1.2em;
}
zostanie zinterpretowany jako:
#naglowek {
color: #ff0000;
background: #00ff00;
font-size: 1.2em;
}
Reguły osadzone
Kolejną z często używanych funkcjonalności, która jednocześnie pomaga nam zapanować nad bałaganem, który może pojawić się w rozbudowanych arkuszach jest osadzanie reguł. Przykładowo:
.news {
margin-top: 10px;
font-size: 1em;
&.lead {
font-size: 1.1em;
}
.title {
font-weight: bold;
font-size: 1.2em;
}
p {
line-height: 1.2em;
code {
font-style: italic;
}
}
}
przekształcony zostanie na:
.news {
margin-top: 10px;
font-size: 1em;
.news.lead {
font-size: 1.1em;
}
.news .title {
font-weight: bold;
font-size: 1.2em;
}
.news p {
line-height: 1.2em;
}
.news p code {
font-style: italic;
}
W przykładowym kodzie LESS pojawia się zapis &.news, na który należy zwrócić uwagę - w miejsce znaku & podstawiany jest selektor elementu nadrzędnego, dzięki czemu możemy wybierać tagi oznaczone wieloma klasami.
Uwaga - rozwiązanie to wydaje się być na tyle przyjemne, że czasem możemy dać się ponieść i zacząć w LESS odtwarzać (prawie) pełną strukturę HTML elementu - należy jednak mieć na uwadze, że wraz ze wzrostem długości reguły wzrasta też złożoność wyszukania elementu, którego dotyczy. Dzieje się tak ponieważ selektory CSS interpretowane są od strony prawej. Starajmy się zatem tworzyć reguły zawierające nie więcej niż 2-3 poziomy zagłębienia!
Specjalną pod-grupę reguł osadzonych stanowią grupy osadzone z parametrem. Zapis ten pozwala nam na stworzenie jednej zbiorczej reguły, różniącej się tylko niektórymi wartościami. Jako przykład dokumentacja podaje zaokrąglanie rogów:
@niebieski: #00ff00;
.zaokragl (@promien: 10px) {
border-radius: @promien;
}
.widget {
background: @niebieski;
border: 1px solid @niebieski;
.zaokragl(5px);
.badge{
.zaokragl();
}
}
przekształcony zostanie na
.widget {
background: #00ff00;
border: 1px solid #00ff00;
border-radius: 5px;
.widget .badge{
border-radius: 10px;
}
Co więcej?
Dużo, dużo więcej - LESS pozwala nam na operowanie na zmiennych za pomocą reguł matematycznych (width: (10px + 20px) * 2; przekształcimy na width: 60px;), definiuje funkcje operujące na kolorach (a:hover { darken(@color, 20%);} pozwoli nam na ściemnienie koloru linku o 20% po najechaniu). Pełną dokumentację znajdziecie oczywiście na stronie projektu, zdecydowanie wykracza on poza zakres tej notki.
Uwagi przy stosowaniu
Podczas stosowania LESS należy pamiętać o kilku sprawach:
- używanie plików .less i kompilowanie ich za pomocą JS przydatne jest tylko w procesie projektowania strony i zdecydowanie polecam stosowanie albo prekompilowanych (wygenerowanych ręcznie po każdej zmianie) plików CSS po uruchomieniu oficjalnie strony, albo stosowanie skryptów po stronie serwera, które będą kompilować plik .less jeżeli zajdzie taka potrzeba
- Internet Explorer (testowane w wersji 9) przechowuje plik .less w pamięci tymczasowej i zmiany mogą być nie widoczne po odświeżeniu strony - jeżeli bardzo zależy nam na testowaniu w IE, najłatwiej będzie dodać jakiś losowy parametr do adresu pliku
- wszelkie zapisy LESS muszą znajdować się w plikach .less, skrypt nie parsuje plików .css
Każdy z nas zapewne niejednokrotnie otrzymał od klienta / grafika projekt strony w którym zastosowano czcionki z poza grupy tzw. "web safe". Czcionki "web safe" to takie, co do których mamy pewność, że posiada je u siebie odwiedzający i wyświetlą się one poprawnie - najczęściej jest to Arial, Verdana czy Tahoma. Zwykle w przypadku kiedy konieczne było zastosowanie jakiejś "nietypowej" czcionki aby mieć pewność, że będzie ona wyglądać poprawnie wstawialiśmy obrazki.
Początek rewolucji
Mimo, że większość przeglądarek (w tym nawet archaiczne IE6) pozwalało w ten czy inny sposób używać czcionek zdefiniowanych przez programistę nie było to ani proste ani skuteczne. Jako pierwszy problem pozwolił nieco zniwelować skrypt zwany sIFR (ang. Scalable Inman Flash Replacement). Jak można się domyśleć po nazwie - było to rozwiązanie oparte na technologii Flash. Za pomocą kilku magicznych linijek nasz tekst zamieniany był na elementy Flash i wyświetlany zdefiniowanym przez nas krojem tekstu. Minusem rozwiązania było oczywiście poleganie na Flash, ale bardziej przeszkadzał efekt "podmiany" tekstu na element Flash, który dało się zauważyć gołym okiem. Ten sam problem dotykał także kolejnego rozwiązania - Cufón. Tym razem zamiast generować pliki SWF skrypt generował dane w postaci ścieżek wektorów i wyświetlał tekst jako <canvas> lub VML (ang. Vector Markup Language) (dla przeglądarek IE). Poza wspomnianym wcześniej problemem ze "Wskakiwaniem" nowej czcionki Cufón posiada inne ograniczenia (tj. brak poprawnej obsługi text-align czy text-decoration).
Nadejście (użytecznego) @font-face
Z biegiem czasu oraz coraz lepszą implementacją standardów rzeczy zaczęły się zmieniać. Coraz więcej osób zaczęło dostrzegać możliwości i potencjał jakie niesie ze sobą @font-face Za pomocą tego elementu CSS możemy w "prosty sposób" definiować własne czcionki:
@font-face {
font-family: Delicious;
font-weight: bold;
src: url('http://example.com/Delicious-Bold.ttf');
}
b.delic {
font-family: 'Delicious';
}
I już - jeżeli nasza przeglądarka obsługuje @font-face wskazany tekst zostanie wyrenderowany pogrubioną wersją czcionki 'Delicious'. Oczywiście nic w naszym życiu nie jest aż tak proste. Powyższy kod zadziała tylko dla przeglądarek obsługujących standard TrueType (.ttf). Żeby mieć pewność, że tekst wyświetli się poprawnie pod IE, Firefox, Opera, Chrome ... i to jeszcze w każdej "w miarę" popularnej wersji musimy zastosować format odpowiedni dla każdej z tych przeglądarek:
@font-face {
font-family: Delicious;
font-weight: bold;
src: url('http://example.com/Delicious-Bold.eot'); /* IE9 w trybie kompatybilności */
src: url('http://example.com/Delicious-Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
url('http://example.com/Delicious-Bold.woff') format('woff'), /* Nowoczesne przeglądarki */
url('http://example.com/Delicious-Bold.ttf') format('truetype'), /* Przeglądarki oparte na Webkit */
url('http://example.com/Delicious-Bold.svg#EASSansRegular') format('svg'); /* Starse wersje iOS */
}
Tak przygotowany kod wymaga oczywiście wygenerowania czcionek w każdym z tych formatów. Z pomocą przychodzi nam tu doskonały serwis Font Squirrel. W serwisie tym znajdziemy setki czcionek gotowych do pobrania i użycia na naszej stronie. Domyślnie każda czcionka dostępna jest w standardzie TTF, EOT, SVG i WOFF. Dodatkowo, za pomocą generatora możemy wygenerować paczkę dla naszej wyjątkowej czcionki. W takim wypadku należy jednak upewnić się, że zezwala na to licencja na jakiej rozpowszechniana jest dana czcionka (pamiętaj - jeżeli nie chcesz być stratnym, nigdy ślepo nie akceptuj czcionki od klienta, a i grafik nie zawsze musi wiedzieć, czego używa).
Alternatywą dla generowania czcionek jest skorzystanie z platformy udostępniającej gotowe czcionki w odpowiednim formacie. Najpopularniejszą z których jest Google Web Fonts. W przypadku tej usługi dobieranie i wysyłanie odpowiedniego formatu czcionki leży po stronie
Google - my ograniczamy się do dodania jednej linijki HTML:
<link href='http://fonts.googleapis.com/css?family=Enriqueta' rel='stylesheet' type='text/css'>
I już możemy w naszym CSS użyć zapisu font-fmily: 'Enriqueta; by wyświetlić tekst odpowiednim krojem. Zaletą Google Web Font jest niewątliwie przekazanie obowiązku serwowania czcionki na serwery CDN firmy Google, co skutkuje zwiększeniem prędkości ładowania strony i zmniejszeniem transferu. Minusem jest niewątpliwie niewielki wybór czcionek, który zmniejsza się jeszcze bardziej gdy zależy nam na czcionce posiadającej polskie znaki diakrytyczne.
Czy @font-face jest rozwiązaniem doskonałym?
Chociaż @font-face może wydawać się idealnym sposobem na zakończenie zabawy w wyświetlanie tekstu jako grafiki na skutek kilku szczegółów nie jest nim (a przynajmniej nie dziś). Do minusów @font-face zaliczyć można na pewno:
- niejednolite renderowanie tekstu w różnych przeglądarkach, systemach operacyjnych - czcionka może być renderowana z odpowiednim wygładzeniem krawędzi i nie mamy na to większego wpływu
- zablokowana obsługa pobierania i wyświetlania czcionek w przeglądarce użytkownika
- brak obsługi kerningu (odległości pomiędzy poszczególnymi glifami -
letter-spacing zmienia odległości pomiędzy każdym ze znaków, kerning pozwala na ustalenie jej dla pojedynczego znaku w tekście)
- konieczność generowania odpowiednich plików czcionki dla:
- różnych przeglądarek
- różnych typów kroju (oddzielna dla zwykłego, oddzielna dla pogrubionego, kolejna dla tekstu pochylonego)
Kiedy więc najlepiej stosować @font-face? Wszędzie tam, gdzie tekst jest dynamiczny - w treści stron, pozycjach menu etc. Elementy, co do których mamy pewność, że nie będą zmieniane przez długi czas od umieszczenia na stronie (np. nagłówki sekcji) najlepiej wciąż umieszczać jako grafika.
Nie ważne czy wierzysz w badania nad przyzwyczajeniami i skojarzeniami, chcesz by Twoja strona była przyjemna dla oka odwiedzających, czy też po prostu chcesz by użytkownicy mogli szybko dowiedzieć się do czego służy dany element - w tej czy innej postaci na Twojej stronie pewnie znajdują się jakieś ikonki.
Moje logo musi być większe!
Każdy kto tworzył kiedykolwiek stronę internetową wie ile wiąże się z tym problemów - często koncepcja zmienia się parokrotnie, raz zmieniamy kształt, raz kolor, innym razem dodajemy cień. Dla polepszenia wydajności strony montujemy nasze ikonki w sprite by przeglądarka nie musiała pobierać dziesiątek obrazków. W takim wypadku zmiana ciągnie za sobą konieczność zmiany sprite, a nie daj Bóg klient wymyśli sobie, by ikonka była większa - nasz idealnie wykalkulowany sprite wziął w łeb i dopychamy kolejny symbol. No i nie wspominajmy już o problemie skalowania - często obrazki wykorzystane w tle po prostu nie chcą skalować się tak, jak byśmy tego oczekiwali.
Z pomocą przychodzi nam stosowanie czcionek, w których zamiast liter (pozwolę sobie na takie uproszczenie) autorzy osadzili różne często wykorzystywane ikony czy logotypy. Jedną z takich czcionek jest WebSymbols.
Jeżeli zajrzymy na stronę projektu - a nasza przeglądarka obsługuje @font-face - ujrzymy zestawienie symboli i logotypów. Nie są to jednak obrazki, ale glify (znowu upraszczam) ze wspomnianej czcionki - każdy zastępuje jedną literę, znak czy cyfrę.
Ok, ale po co mi kolejny "sprite"?
Dzięki takiemu rozwiązaniu możemy utworzyć coś na kształt spritu obrazków, jednak zawierać będzie on tylko symbole. Co ciekawsze, możemy zmieniać ich rozmiar (font-size), kolor (color) oraz tło (background). Możemy także pójść na całość - dodać cień, albo proste animacje (na powyższej stronie animacja "ładowania" to po prostu element, którego zawartość zamieniana jest na kolejne cyfry z zestawu 1 - 7). Oto przykład ze strony powyżej:
Każdy z tych elementów wyświetlony został bez użycia obrazków - dodatkowy efekt wygładzenia zależny jest od konfiguracji przeglądarki i systemu operacyjnego.
Dodatkowo, czcionka w najpopularniejszym (pod wzg. obsługi przez przeglądarki) formacie - TTF - to jedyne 12kb - dużo mniej niż umieszczenie wszystkich tych symboli jako grafika.
Jedno ale ...
Niestety, jeżeli czcionka nie zawiera interesującego nas elementu mamy 3 wyjścia:
- znaleźć inną, która będzie go zawierać (np. Fico, rozwiązanie płatne)
- zastosować element graficzny
- przygotować własny zestaw glifów i stworzyć własną czcionkę
Przyznam, że osobiście nie miałem jeszcze okazji wykorzystać tego rozwiązania w większym projekcie, ale podczas testów wewnątrz firmy nie napotkałem żadnych problemów ze stosowaniem tej techniki.
Każdy, kto kiedykolwiek korzystał z internetu doskonale zdaje sobie sprawę, że strony, które ładują się długo odstraszają potencjalnych odwiedzających. Wyszukany w Google link nie ładuje się w ciągu 5 sekund? Pewnie strona nie działa - wracamy na wyniki wyszukiwania i sprawdzamy kolejną.
Często za wolne ładowanie się strony nie odpowiada zły kod silnika na którym stoi, czy też wolne łącze serwera, ale duża ilość ładowanych skryptów JavaScript. W tym miejscu z pomocą przychodzi nam skrypt nazwany head.js. Za pomocą tego prostego skryptu możemy oddelegować ładowanie dziesiątek oddzielnych plików JS w tło i zmniejszyć czas, jaki upłynie do wyświetlenia zawartości strony. head.js ma też kilka innych, przydatnych funkcji, o których wspomnę jeszcze poniżej.
Podstawowa funkcjonalność - równoległe, nie blokujące pobieranie w tle.
Standardowe umieszczanie wywołania skryptów JS w sekcji
wiąże się z odczekaniem na pobranie wszystkich dołączonych plików przed rozpoczęciem renderowania strony. Jeżeli ładujemy jeden mały plik może nie stanowić to problemu, jednak kiedy chcemy korzystać z kilku bibliotek, skryptów pomocniczych i innych, które nie daj Bóg znajdują się na wolno odpowiadających serwerach sprawa nieco się komplikuje. Pomocne może być przesunięcie wywołań skryptów na sam koniec części jednak jest to rozwiązanie mało eleganckie i nie intuicyjne.
head.js("http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js", "/assets/scripts.js", function() {
init();
});
Powyższy kod obrazuje podstawowe i chyba najczęstsze wykorzystanie head.js Wywołanie kodu spowoduje pobranie biblioteki jQuery z serwera GoogleAPI, wczytanie lokalnego pliku JS oraz wywołanie funkcji init kiedy tylko przeglądarka zgłosi zdarzenie DOM.ready (czyli załadowano HTML, ale nie pobrano elementów multimedialnych). Jak już wspominałem, pliki pobierane są w tle, jednak wykonywane w kolejności zdefiniowanej przez nas w wywołaniu. Jeżeli nie zależy nam na kolejności ich wykonywania, możemy zmodyfikować nasz kod:
head.js("/assets/scripts.js", function() {
init();
});
head.js("http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js");
// jest to równoznaczne z:
head.js("/assets/scripts.js", function() {init();}).js("http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js");
Teraz skrypty wykonane zostaną w kolejności, w której pobierze je przeglądarka.
Jeżeli nie chcemy używać "wywołań zwrotnych" (ang. callback) możemy także nadać każdemu skryptowi unikalny identyfikator i posłużyć się funkcją head.ready jak na poniższym przykładzie:
head.ready("tools", function() {
init();
});
head.js(
{jquery: "http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"},
{tools: "/assets/scripts"}
);
Dodatkowe możliwości
Jak już wspomniałem, head.js poza swoim podstawowym zadaniem spełnia także kilka innych funkcji. Jak wiadomo starsze przeglądarki nie w pełni wspierają HTML5 - najbardziej uciążliwy jest brak możliwości używania CSS dla nowo wprowadzonych elementów. By obejść ten problem często używamy HTML5shiv - okazuje się jednak, że autor head.js postanowił umieścić te funkcjonalność w swoim skrypcie, więc nie musimy zawracać sobie tym głowy.
Kolejnym udogodnieniem, którym obdarza nas skrypt jest wykrywanie możliwości przeglądarki w zakresie obsługi CSS, podobnie jak ma to w wypadku zastosowania Modernizr. Samo dodanie wywołania skryptu do strony poskutkuje nadaniem elementowi <html> klas określających wsparcie dla poszczególnych elementów. Klasy, jakie może dodać skrypt to:
borderimage, borderradius, boxshadow, cssreflections,
csstransforms, csstransitions, fontface, multiplebgs, opacity, rgba, textshadow
Poza wykrywaniem obsługi CSS skrypt pozwoli nam poznać także rodzinę (ie, webkit, opera, mozilla), wersję (tylko dla IE, lt-ie8, ie6), oraz szerokość okna, w którym wyświetlona jest strona dodając odpowiednie klasy z przedrostkiem w- (dla aktualnej rozdzielczości) i lt- (dla rozdzielczości większych od aktualnej). Przykładowo, oglądając stronę w przeglądarce IE7 i rozdzielczości 1400x768 element <html;> otrzyma klasy (pomijając wykrywanie CSS z powyższego akapitu):
<html class="ie ie7 lt-ie8 lt-ie9 w-1400 lt-1440 lt-1680 lt-1920">
Ostatnią funkcjonalnością jest tzw. "CSS routing" czyli dodawanie klasy na podstawie adresu URL. Najłatwiej zobrazować to na przykładzie. Odwiedzając adres
http://example.com/o-firmie/historia/rok-2011
Element <html;> przyjmie postać (dla uproszczenia, bez powyższych funkcjonalności):
<html class="o-firmie-section historia-section rok-2011-section">
Dzięki czemu możemy wpłynąć np. na zaakcentowanie graficzne aktualnie przeglądanej sekcji witryny (chociaż moim zdaniem zawsze lepiej zrobić to po stronie serwera dodając od razu klasy do odpowiednich elementów).
Podsumowując, head.js to doskonałe narzędzie, które poza zmniejszeniem czasu potrzebnego na załadowanie naszej strony oraz usprawnieniem organizacji kodu HTML posiada także dodatkowe, ułatwiające codzienną prace funkcje. Po więcej informacji nt. skryptu, jego możliwości oraz konfiguracji zapraszam na oficjalną stronę projektu.