Uwaga: wyszedł mi "odrobinkę" przydługi wstęp. Zabieganych zapraszam od razu do konkretów.
Nie da się ukryć że frontend developerzy (czy inaczej "ci od cięcia grafiki" :) łatwego życia nie mają. Pierwsza sprawa to niedoskonałości samych języków (CSS, xHTML, Javascript+DOM), druga to różnice i bugi (zwane inaczej ficzerami) w obsłudze przez przeglądarki. Każdy z tych języków na szczęście się rozwija (CSS3, HTML5, ECMAScript 5), a implementacja standardów jest, nawet w Internet Explorerze, sukcesywnie polepszana. Trwa to jednak strasznie długo, dlatego warto pokombinować samemu.
Ostatnio opisałem plugin do edytorów tekstów dzięki któremu można przyspieszyć pisanie HTMLa. Dzisiaj pod lupę chciałbym wziąć CSS. Osobiście na tempo pisania listy właściwości nie narzekam - mam własny zestaw snippetów, który umila mi życie. Inaczej ma się sprawa w stosunku do selektorów. Już w niedużym projekcie potrafią się zrobić cuda typu:
#content .news_list .item .title {...} #content .news_list .item .date {...} #content .news_list .item .date .day {...}
Albo:
.s1 { width:120px; float:left; font-size:1.1em; margin-left:10px; color:#FA0; } /*gdzieś kawałek dalej:*/ .s2 { width:120px; float:left; font-size:1.1em; margin-left:10px; color:#C14; }
Gdzie wypada to połączyć do pary selektorów i dla każdego z osobna jeszcze kolor ustawić. Niestety to najprostszy przypadek z tej rodziny, czasami trzeba znaleźć części wspólne dla kilku reguł po kilkunaście właściwości, albo olać wszystko.
Dalej można wymieniać:
co to był za kod tego pomarańczowego, który używam do podkreśleń?
-moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px;
Co więcej - to są problemy które pojawiają się już na etapie stron o średniej wielkości i kodowania w pojedynkę. W przypadku sporych serwisów (długo i wieloetapowo rozwijanych) i większego zespołu potrafią urosnąć do &*$#$%. To jest jak rzeźba w gównie. Trzeba przepisać cały ten bajzel
. Sam ostatnio tak opisałem jeden commit do bazy.
Jakiś czas temu dostałem od kogoś link do LESS CSS - parsera/kompilatora (nie wiem jak to nazwać) rozszerzającego możliwości CSSa o kilka interesujących rzeczy typu: zmienne, obliczenia, reguły zagnieżdżone, itd. O temacie jednak zapomniałem (mało ostatnio koduję) i przypomniał mi kilka dni temu o nim Occulkot, który podrzucił mi Sassa. Obydwa kompilatory napisane są w Rubym. Zrobiłem mały research i znalazłem jeszcze podobne cudo, tyle że w Pythonie - Clever CSS.
Po krótkim wczytywaniu się w przykłady zdecydowałem się na LESSa. Dodaje do CSSa trochę mniej ficzerów, ale przynajmniej nie zmienia jego składni (plik CSS jest poprawnym plikiem LESS) i nie wymusza na mnie jedynego, właściwego formatowania kodu (Sass i Clever CSS mają składnię czerpiącą z języków w jakich zostały napisane - odpowiednio Ruby i Python - wymagają więc wcięć).
Polecam przeczytać Haml-sass, czyli tragedia w dwóch aktach. Przy okazji tej lektury ja również odradzam Hamla, który jest w teorii cudownym (zen i te sprawy) systemem szablonów HTMLa. Tylko, że kompletnie to nieczytelne, brzydkie i bez sensu.
Po tym przydługim wstępie (chciałem usunąć, ale żal jak się już napisało) przejdźmy do konkretów.
Instalacja, dla posiadających gema (ci nieposiadający najlepiej niech go zainstalują), jest banalna:
$ sudo gem install less
Ewentualnie jeśli ktoś koduje w Railsach, to może go zainteresować ten plugin.Najprostszym sposobem skorzystania z LESSa jest jednak przy pomocy konsoli:
$ lessc style.less
Wykonanie tego polecenia spowoduje utworzenie pliku style.css zawierającego wynik działania kompilatora.
Kompilując taki kod:
@brand_color: #4D926F; #header { color: @brand_color; } h2 { color: @brand_color; }
Otrzymamy:
#header, h2 { color: #4d926f; }
Jak widać, poza podstawieniem zmiennej, LESS połączył też reguły o tej samej liście właściwości. To informacja dla miłośników oszczędzania na bajtach transferu :).
CSSowe DRY :).
.rounded_corners (@radius: 5px) { -moz-border-radius: @radius; -webkit-border-radius: @radius; border-radius: @radius; } h1 .stronger { font-weight:bold; font-size:1.1em; } #header { .rounded_corners; h1 .stronger; } #footer { .rounded_corners(10px); }
Po kompilacji:
h1 .stronger { font-weight: bold; font-size: 1.1em; } #header { -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; font-weight: bold; font-size: 1.1em; } #footer { -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; }
Przy czym definicja reguły musi wystąpić przed jej użyciem. Przykład z wykorzystaniem h1 .stronger nie ma uzasadnienia w praktyce (jest w zasadzie błędny), ale chciałem tylko pokazać, że można wykorzystywać ponownie dowolne reguły.
To chyba mój ulubieniec. Dzięki temu rozszerzeniu unikniemy pisania co chwilę mega długich selektorów. Dziwię się w ogóle, że nie ma tego w oficjalnym CSSie.
#header { color: red; a { font-weight: bold; text-decoration: none; } > p { color: blue; } }
Po kompilacji:
#header { color: red; } #header a { font-weight: bold; text-decoration: none; } #header > p { color: blue; }
Chyba nie muszę tłumaczyć.
@the-border: 1px; @base-color: #111; #header { color: @base-color * 3; border-left: @the-border; border-right: @the-border * 2; } #footer { color: (@base-color + #111) * 2; }
Po kompilacji:
#header { color: #333333; border-left: 1px; border-right: 2px; } #footer { color: #444444; }
To by było na tyle. Jeśli kogoś temat zainteresował to zapraszam do specyfikacji, gdzie autor omawia jeszcze kilka dodatków.
W każdym razie - cztery małe ficzery, a jak cieszą, prawda? :)
Zastanawiałem się tylko jak usprawnić kompilację po wprowadzeniu zmian do pliku LESS. Najfajniej gdyby udało mi się w moim VIMie podłączyć wykonanie $ lessc pod operację zapisania, ale to nie na moje umiejętności. Mcv zaproponował mi takiego Makefile'a:
%.css: %.less lessc $<
Wykonujemy go uruchamiając: $ make plik1.css plik2.css. To już powinno mi się udać podpiąć w VIMie pod zapis pliku. Ewentualnie można spróbować tak:
all: *.css %.css: %.less lessc $<
Co zadziała automatycznie dla wszystkich istniejących już plików CSS po wykonaniu prostego $ make. Przy czym, jeśli się mylę, to proszę mnie poprawić, bo nigdy żadnego makefile'a sam nie napisałem.
EDIT: w komentarzach pojawiły się rozwiązania mojego problemu.
Kompilację fajniej się robi server-side z cacheowaniem ;)
Jak ktoś używa railsów (czy w ogóle rubiego) to droga wolna ;) Plugin pewnie dokładnie to robi.
W innym przypadku nie widzę sensu się wysilania. I tak ręcznie się to kompiluje podczas pisania strony.
Za dużo tego jak dla mnie i zamiast skracać pracę nad tworzeniem CSS znacznie go wydłuży. Najlepsze jest kodowania z palca
Prawda cieszą ;)
@shpyo: Tzn. czego jest za dużo? Bo to tak jakbyś powiedział, że pisanie w Rubym wydłuży pracę w stosunku do pisania w PHP, bo Ruby ma strasznie dużo różnych konstrukcji, skrótów, itp. Co więcej nie tylko pisanie strony jest ważne, ale też jej utrzymanie. Wydaje mi się wręcz. że umiejętne wykorzystanie LESSa da nam największy profit właśnie podczas wprowadzania jakichś większych zmian w istniejących już serwisach.
CSS, HTML/XHTML i JavaScript *nie są* technologiami.
http://sjp.pwn.pl/lista.php?co=technologia
Ciężko mi się spierać, bo chyba rzeczywiście nie są ;) Tylko muszę coś lepszego w takim razie znaleźć. Dzięki za uwagę.
Języki. Formatowania, programowania, ale cały czas języki. Polska Wikipedia ładnie podpowiada czym są poszczególne ustrojstwa.
Hehe :) Pierwsze co teraz zrobiłem to sprawdziłem na wiki. Za chwilę zmienię na "języki", choć słowo to w kontekście CSSa i HTMLa niektórych bawi :P
To użyj 'język opisu' w odróżnieniu od 'języka programowania'. ;-)
Hm. Co do automatyzacji tworzenia pliku CSS z pliku LESS, to zdaje się jest w LESSCSS taka opcja jak -w (watch)...
A tak. Trochę w ogóle faila zaliczyłem, bo wydawało mi się, że na stronie głównej jest wszystko co dotyczy LESSCSS - tzn wszystkie jego możliwości. Przegapiłem zakładkę docs ;) Będę musiał poprawić swój wpis. Nauczka żeby nie pisać na szybko.
Co do watcha, to można niestety tylko jeden plik na raz śledzić (jak wrzuciłem dwa, to jakieś cuda się porobiły). Dopóki pracujemy z jednym, to jest idealne rozwiązanie. Z większą ilością niestety robi się problem.
To wtedy możesz odpalić dwa lessc, nie? ;-)
Od razu mogę też 3. Tylko czy każdy odpalać na osobnej konsoli (bo trzeba śledzić wyniki kompilacji przecież), czy powysyłać je w tło i przywoływać odpowiedni do zmienionego przed chwilą pliku? :P
Ja wiem, że Linux jest systemem wielozadaniowym, ale odnosiłem się do wygody tego rozwiązania :P
&
Chociaż można by każde z wywołań przekierować do jednego pliku i patrzeć tylko tam czy pojawiają się jakieś błędy.
Z drugiej strony kiedy używamy @importów, to wystarczy jeden plik obserwować.
W jakim sensie chcesz & wykorzystać?
Jeszcze spytam: po co chcesz „przywoływać” lessc? Przecież on niby sam ma modyfikować .css, po tym jak wykryje zmiany.
Jeśli zmodyfikuję plik i pojawią się błędy, to wiem, że te co się pojawiły są z tego pliku, który właśnie zapisałem.
lessc -w dupa.less&
"Jeszcze spytam: po co chcesz „przywoływać” lessc? Przecież on niby sam ma modyfikować .css, po tym jak wykryje zmiany."
Chyba że zrobisz jakąś literówkę, czy inny błąd składniowy - wypadałoby wiedzieć czemu się nic nie zmienia w przeglądarce.
"Jeśli zmodyfikuję plik i pojawią się błędy, to wiem, że te co się pojawiły są z tego pliku, który właśnie zapisałem.
lessc -w dupa.less&"
Fajne - nie wiedziałem, że można tak z tego skorzystać. Dzięki :)
florek - bardziej neutralny będzie 'język skryptowy', chociaż to też do HTML i CSS się średnio odnosi ;)
Jeśli chodzi o Makefile'a to w przypadku GNU make:
all: $(patsubst %.less,%.css,*.less)
%.css: %.less
exec echo $<
Aż dziwne, że na stronie u siebie nie zrobili formularza z możliwością wklejenia kodu do skompilowania. Przynajmniej mała nisza jest do wypełnienia...
Czy ja wiem. A kto miałby z niego korzystać? Na stronie jest sporo przykładów, a jak ktoś będzie zainteresowany to sobie zainstaluje.
*różnice i bugi (zwane inaczej ficzerami)*
dla mnie ficzer to jakaś funkcja, udogodnienie, dodatkowa opcja, ogólnie - coś dobrego, coś user-friendly (z ang. feature), a nie bug...
Chyba, że jakaś nowa terminologia i coś się pozmieniało. Albo tak było od zawsze, a ja myliłem pojęcia.
To taki żart :P Np. twórcy IE6 tłumaczą, że coś co jest dla wszystkich bugiem oni implementowali jako ficzer :P
Tak poważnie to napisałeś, że nie rozkminiłem ironii ;)