Star Rating / Youtube

System oceny gwiazdkami

Cześć! Cieszę się, że tu trafiłeś. Jak zapewne wiesz, jakiś czas temu na kanale YT koduje nagrałem film "Star Rating - system oceny gwiazdkami w samym CSS".

Jeśli chcesz, w prawym dolnym rogu strony znajdziesz wideo z oryginalnym nagraniem prezentującym dany przykład.

To, co tutaj widzisz jest tylko przedsmakiem tego, co szykujemy - nowej platformy do nauki front-endu, która, mamy nadzieję, zmieni sposób postrzegania kursów online. Rozgość się i poeksperymentuj z interfejsem użytkownika. Warto też wyłączyć adblocka na tej stronie - nie wyświetlamy żadnych reklam, natomiast oprogramowanie tego typu blokuje niektóre funkcjonalności przeglądarki, na których polega nasza interaktywna książka.

Pamiętaj, że jest to wersja alfa i z chęcią przyjmiemy opinie bądź raporty o błędach na naszej grupie koduje: after hours.

A więc do rzeczy!

Zaczniemy od stworzenia kontenera na nasze gwiazdki, któremu nadamy klasę stars. Będzie to tzw. wrapper na cały nasz widget, w którym umieścimy pozostałe potrzebne znaczniki HTML.

Poniżej znajdziesz nasz własny edytor tekstowy. Możesz śmiało edytować wybrane fragmenty kodu, a po prawej, na żywo, zobaczysz efekt swojej pracy. Możesz też otworzyć okienko podglądu w nowym oknie oraz wejść w tryb edytora pełnoekranowego (jak? - to pierwsze wyzwanie dla Ciebie :) )

Mamy już pojemnik na cały nasz element - następnie chcielibyśmy, aby każda gwiazdka była znacznikiem input o typie radio, tak, by zaznaczenie jednej z nich skutkowało odznaczeniem pozostałych.

Aby grupa przycisków radio działała, musimy każdemu z nich podać tę samą nazwę oraz unikalną wartość, żeby móc rozróżnić poszczególne inputy od siebie. Stworzymy pięć gwiazdek, każdej z nich nadając atrybut name o wartości star.

Moglibyśmy przejść już do ostylowania naszej struktury, natomiast w przypadku inputow o typie radio nie jest to najprostsze. Aby nasza strona była bardziej dostępna dla czytników ekranowych oraz prosta w stylowaniu, dla każdego inputa stworzymy odpowiadającą mu etykietkę, czyli znacznik label.

Musimy oczywiście zdefiniować dla jakiego znacznika przeznaczona jest konkretna etykietka. Wykorzystamy do tego atrybut for, który jako wartość przyjmie nazwę identyfikatora elementu, do którego etykietka się odnosi. Nadajmy więc inputom identyfikatory o prefiksie "star" oraz sufiksie odpowiadającym kolejnej wartości gwiazdki, tak by pasowały do naszych atrybutow for w labelkach.

Treść etykietek ustawimy na "One Star", "Two stars" i tak dalej dla każdej naszej gwiazdki.

Stylowanie struktury HTML

Załadujmy plik styles.css do naszego pliku index.html za pomocą znacznika link. Pamiętajmy, że style powinniśmy umieszczać w znaczniku head naszej strony WWW.

Nadajmy naszej strukturze odpowiedni wygląd, zaczynając od zdefiniowania reguł stylowania dla kontenera .stars Ustawmy mu tło na kolor biały, wysokość na 30 pikseli i szerokość na 200 pikseli.

Dodatkowo, ustalimy margines wewnętrzny na 10px. Zaokrąglimy też boki o połowę wysokości dla bardziej estetycznego efektu.

Wyrównajmy nasze elementy w poziomie i w pionie przy pomocy flexboxa, czyli ustawiając wartość display na flex oraz justify-content i align-items na center

Jak widzisz, nasz element zaczyna wyglądać coraz lepiej. Przejdźmy więc do stylowania samych inputów.

Nie chcemy, aby te radio buttony były widoczne w naszym komponencie (docelowo użytkownik ma przecież klikać gwiazdki!). Dlatego przeniesiemy je poza obszar, który widzi użytkownik. Dlaczego po prostu nie ukryjemy znaczników input przy pomocy CSSa?

Nadanie elementom reguł stylowania takich jak czy jest złą praktyką, jeśli chodzi o dostępność i wsparcie dla czytników ekranowych, o których wspomniałem wcześniej.

Przesuńmy więc inputy, które znajdują się wewnątrz naszego kontenera .stars poprzez nadanie im position: absolute oraz left na powiedzmy -9999px. Upewniamy się dzięki temu, że element ten nie jest widoczny dla użytkownika, zachowując jednocześnie reguły dostępności.

Dla każdej z naszych labelek ustawmy szerokość i wysokość na 30px, padding na 5px i poglądowo border, by widzieć jak te labelki są ułożone w tym momencie. Te prostokąty docelowo będą naszymi gwiazdkami.

Ale jak zrobić gwiazdki? Wykorzystamy do tego pseudoelement before na każdej naszej etykietce. Nie będziemy sami rysowali kształtu gwiazdki, wykorzystamy do tego natomiast znak . Ustawiony jako wartość parametru content wyświetli nam naszą pożądaną gwiazdkę. Jest to o wiele szybsza i wygodniejsza metoda niż tworzenie wielu trojkatow i ich obracanie w CSS bądź ładowanie obrazków SVG, chociaż oczywiście moglibyśmy rozwiązać to w ten sposób.

Ustawmy, aby nasze gwiazdki były domyślnie srebrne oraz były wysokie na rozmiar swojego kontenera. Zrobimy to przy pomocy właściwości , jako że ta nasza gwiazdka jest tak naprawdę tekstem. Wycentrujemy ją w pionie przy użyciu line-height, również ustawione na 30px.

Jak widzisz, obecnie gwiazdka wypchnęła nam treść labelki, jako że pseudoelement ::before dodawany jest przed treścią elementu, na którym sie znajduje. Na potrzeby przykładu wykorzystamy ujemny prawy margines o wartości ustawionej na szerokość kontenera, aby gwiazdki nachodziły na tekst oraz zmienimy jego kolor na przezroczysty.

Oczywiście - jest dużo alternatywnych rozwiązań tego problemu. Możemy też ukryć border na elementach label (śmiało eksperymentuj z kodem w naszym edytorze, jeśli nie jesteś czegoś pewien! :) )

Podświetlanie gwiazdek

Przejdźmy do faktycznego podświetlania gwiazdek. Stworzymy selektor, który będzie mowił, że jeśli najedziemy myszką na jakąkolwiek labelkę, to chcielibyśmy, aby zmieniła ona kolor na pomarańczowy. Tworzymy więc selektor label:hover i nadajemy w nim odpowiednie reguły.

Zobacz, że gdy najedziemy myszką na wybraną etykietkę, to nie podświetla się gwiazdka, tylko sam tekst. Dzieje się tak, ponieważ chcemy zmienić kolor samego pseudoelementu, który znajduje sie na labelce, na którym jest myszka - czyli label:hover::before, a nie całego znacznika label.

Teraz, jak widzimy, nasze gwiazdki podświetlają się poprawnie. Hura!

Co dalej - dobrze byłoby, jeśli w momencie, gdy najeżdżamy na gwiazdkę nr 4 to trzy poprzednie gwiazdki rownież się świeciły - w końcu oceniamy dany byt na 4 gwiazdki, prawda? Jeśli wybieramy czwartą gwiazdkę to zakładamy, że wszystkie poprzednie również powinny się świecić. A więc jak zrobić taki selektor w samym CSSie?

Ponownie pobierzmy labelkę, na której znajduje sie kursor myszy i biorąc go jako nasz punkt odniesienia znajdziemy wszystkie następne elementy, które znajdują się na tym samym poziomie - czyli mają tego samego rodzica.

Elementy takie są względem siebie rodzeństwem, stąd też nazwa selektora - . Używając sibling selektora znajdziemy wszystkie before'y na naszych elementach label.

Jak widzimy - uzyskaliśmy odwrotny efekt. Czyli jeśli podświetlamy drugą gwiazdkę to wszystkie oprócz pierwszej się podświetlają. Dlaczego tak się dzieje? Ponieważ pobraliśmy wszystkie następne elementy ::before na znaczniku label, a niestety w CSSie nie ma czegoś takiego jak previous sibling selector. Jak możemy to obejść? Możemy użyć do tego flexa i ustawić na naszym kontenerze flex-direction na wartość row-reverse, tak, by gwiazdki były rysowane w odwrotnej kolejności - od tyłu.

Zobacz, że wszystko wyświetla się prawidłowo. Jeśli zaznaczymy, że chcemy trzecią gwiazdkę, to wszystkie trzy się nam podświetlą. Natomiast jest jeszcze jeden problem, który może nie będzie taki oczywisty.

Jeśli pokażemy tekst naszej etykiety, to zobaczymy, że użytkownik myśli, że zaznacza dwie gwiazdki, a tak naprawdę zaznacza cztery. To wynika z tego, że nasz markup jest w takiej kolejności i niezależnie czy flex będzie nam to rysował od prawej do lewej, to i tak kolejność markupu musimy odwrocić.

Teraz, kiedy użytkownik zaznaczył 4 gwiazdki, to jesteśmy pewni, że klika input o wartości 4. Ponownie ustawmy kolor napisów wewnątrz etykietek na przeźroczysty. Natomiast w momencie kliknięcia dowolnej gwiazdki, gdy opuścimy jej obszar kursorem myszy, to nie ma żadnego indykatora wizualnego, który pokazywałby, że faktycznie coś kliknęliśmy.

Chcielibyśmy, by po kliknięciu na gwiazdkę nr 4, wszystkie poprzednie rownież się podświetliły oraz aby stan ten został utrzymany, jeśli zabierzemy kursor myszy z naszego komponentu. Dopiszmy kolejny selektor do naszej reguły wymieniając je po przecinku.

Tym razem pobierzemy wszystkie inputy, które znajdują się w kontenerze .stars i które są zaznaczone. Jako że wszystkie inputy w tym kontenerze mają typ radio oraz taką samą wartość atrybutu name, to jesteśmy pewni, że ten selektor zawsze wybierze nam jeden element. Jeśli mielibyśmy tutaj inputy o innym typie bądź o różnych wartościach atrybutów name, wtedy ten selektor może wskazać więcej niż jeden element.

Pobraliśmy więc tego inputa i chcielibyśmy znaleźć wszystkie następne gwiazdki, czyli pseudoelementy na etykietkach. Stąd selektor .stars input:checked ~ label::before. Czytamy go w ten sposób: Wewnątrz kontenera stars znajdź , i od ich pozycji pobierz każdy , który pasuje do selektora label::before. Zobaczmy jaki będzie tego efekt.

Po kliknięciu w czwartą gwiazdkę, wszystkie pozostałe nam się podświetliły, oprócz tej czwartej i tak samo dzieje się z pozostałymi gwiazdkami. Czyli jeśli klikniemy sobie pierwszą, to nie widzimy, że cokolwiek jest kliknięte. Dlaczego tak się dzieje? Najlepiej zrozumiecie to oglądając fragment wideo (08:58). Powinniśmy przenieść nasze etykietki poniżej inputów o typie radio w naszej strukturze strony, tak aby ten selektor mógł zadziałać.

W tym momencie gdy klikniemy 3 gwiazdki to widzimy, że ten stan został zapisany i wszystkie 3 gwiazdki świecą się na pomarańczowo. Oczywiście nasz selektor obsługujący najeżdżanie kursorem myszki również działa.

Jak widzisz, bez użycia nawet jednej linijki JavaScriptu stworzyliśmy komponent do oceny np. produktów na sklepie internetowym. Jaka z tego korzyść? Np. do naszych klientów, możemy zamieścić tam taki komponent i zbierać interesujące nas dane w sposób przystępny dla naszego użytkownika.

To wszystko, co przygotowałem dla Ciebie w kwestii tego komponentu. Pamiętaj, że korzystając z takiego rozwiązania "na produkcji" musisz zwrócić też uwagę na wiele innych czynników oraz sprawdzić wsparcie dla wykorzystanych właściwości w przeglądarkach, które zamierzasz wspierać.

Jako dodatek - doładowaliśmy do pliku index.html plik script.js tak, abyś mógł drogi Widzu poeksperymentować z dodaniem obsługi JavaScript do naszego komponentu, jeśli tylko chcesz.

To wszystko o Star Rating!

Drogi czytelniku, dziękuję Ci, że dotrwałeś do końca. Mam nadzieje, że podobała Ci się ta forma przekazywania wiedzy. Koniecznie podziel się swoimi przemyśleniami na kontakt@kodu.je bądź facebookowej grupie koduje: after hours.

Poza tym zachęcam Cię gorąco do subskrypcji naszego kanału na youtube.

Pozdrawiam Cię serdecznie, Wojtek Połowniak

W sprawach biznesowych prosimy o kontakt na kontakt@kodu.je