Pierwsze kroki z kształtami CSS

Zawijanie treści wokół niestandardowych ścieżek

Razvan Caliman
Razvan Caliman

Przez długi czas projektanci stron internetowych musieli tworzyć w ramach ograniczeń prostokąta. Większość treści w internecie jest nadal uwięziona w prostych polach, ponieważ większość prób stworzenia niestandardowego układu kończy się frustracją. To się jednak zmieni wraz z wprowadzeniem kształtów CSS, które są dostępne od wersji Chrome 37. Kształty CSS umożliwiają projektantom stron internetowych zawijanie treści wokół niestandardowych ścieżek, takich jak okręgi, elipsy i wielokąty, co pozwala im uwolnić się od ograniczeń prostokąta.

Kształty można definiować ręcznie lub wnioskować na podstawie obrazów.

Przeanalizujmy bardzo prosty przykład.

Być może zdarzyło Ci się, tak jak mi, naiwnie oczekiwać, że po umieszczeniu obrazu z przezroczystymi elementami treść zawinie się i wypełni luki, a potem rozczarować się, gdy wokół elementu pozostał prostokątny kształt zawijania. Aby rozwiązać ten problem, możesz użyć kształtów CSS.

Wyodrębnianie kształtu z obrazu
<img class="element" src="image.png" />
<p>Lorem ipsum…</p>

<style>
.element{
  shape-outside: url(image.png);
  shape-image-threshold: 0.5;
  float: left;
}
</style>

Deklaracja CSS shape-outside: url(image.png) informuje przeglądarkę, że ma wyodrębnić kształt z obrazu.

Właściwość shape-image-threshold określa minimalny poziom przezroczystości pikseli, które zostaną użyte do utworzenia kształtu. Wartość musi mieścić się w zakresie od 0.0 (pełna przezroczystość) do 1.0 (pełna nieprzezroczystość). Wartość shape-image-threshold: 0.5 oznacza, że do utworzenia kształtu zostaną użyte tylko piksele o kryciu wynoszącym co najmniej 50%.

Kluczowa jest tu właściwość float. Właściwość shape-outside określa kształt obszaru, wokół którego będzie zawijana treść, ale bez właściwości float nie zobaczysz efektów kształtu.

Elementy mają obszar pływający po przeciwnej stronie wartości float. Jeśli na przykład element z obrazem filiżanki kawy jest przesunięty w lewo, obszar przesunięcia zostanie utworzony po prawej stronie filiżanki. Nawet jeśli utworzysz obraz z odstępami po obu stronach, treść będzie opływać kształt tylko po przeciwnej stronie określonej przez właściwość float (po lewej lub po prawej stronie, nigdy po obu).

W przyszłości, po wprowadzeniu wykluczeń CSS, będzie można używać właściwości shape-outside w elementach, które nie są pływające.

Ręczne tworzenie kształtów

Oprócz wyodrębniania kształtów z obrazów możesz też kodować je ręcznie. Do tworzenia kształtów możesz wybrać kilka wartości funkcjonalnych: circle(), ellipse(), inset() i polygon(). Każda funkcja kształtu akceptuje zestaw współrzędnych i jest sparowana z polem referencyjnym, które określa układ współrzędnych. Za chwilę dowiesz się więcej o polach referencyjnych.

Funkcja circle()

Ilustracja przedstawiająca wartość kształtu circle()

Pełny zapis wartości kształtu koła to circle(r at cx cy), gdzie r to promień koła, a cx i cy to współrzędne środka koła na osiach X i Y. Współrzędne środka okręgu są opcjonalne. Jeśli je pominiesz, domyślnie zostanie użyty środek elementu (punkt przecięcia jego przekątnych).

.element{
  shape-outside: circle(50%);
  width: 300px;
  height: 300px;
  float: left;
}

W przykładzie powyżej treść będzie zawijać się wokół zewnętrznej krawędzi okrągłej ścieżki. Pojedynczy argument 50% określa promień okręgu, który w tym konkretnym przypadku wynosi połowę szerokości lub wysokości elementu. Zmiana wymiarów elementu wpłynie na promień kształtu koła. To podstawowy przykład tego, jak kształty CSS mogą być elastyczne.

Zanim przejdziemy dalej, warto przypomnieć, że kształty CSS wpływają tylko na kształt obszaru pływającego wokół elementu. Jeśli element ma tło, nie zostanie ono przycięte przez kształt. Aby uzyskać ten efekt, musisz użyć właściwości z maskowania CSS – clip-path lub mask-image. Właściwość clip-path jest bardzo przydatna, ponieważ używa tej samej notacji co kształty CSS, dzięki czemu można ponownie używać wartości.

Ilustracja przedstawiająca kształt `circle()` i ścieżkę przycinania

Ilustracje w tym dokumencie wykorzystują przycinanie, aby podkreślić kształt i pomóc Ci zrozumieć efekty.

Wróć do kształtu koła.

Gdy używasz wartości procentowych do określenia promienia okręgu, wartość jest obliczana za pomocą nieco bardziej złożonego wzoru: sqrt(szerokość^2 + wysokość^2) / sqrt(2). Warto o tym pamiętać, ponieważ dzięki temu łatwiej wyobrazić sobie, jaki będzie kształt koła, jeśli wymiary elementu nie będą równe.

We współrzędnych funkcji kształtu można używać wszystkich typów jednostek CSS – px, em, rem, vw, vh itd. Możesz wybrać ten, który jest wystarczająco elastyczny lub sztywny, aby spełnić Twoje potrzeby.

Położenie okręgu możesz dostosować, ustawiając dokładne wartości współrzędnych jego środka.

.element{
  shape-outside: circle(50% at 0 0);
}

Spowoduje to umieszczenie środka okręgu w początku układu współrzędnych. Czym jest układ współrzędnych? W tym miejscu wprowadzamy pola referencyjne.

Pola referencyjne kształtów CSS

Pole referencyjne to wirtualne pole wokół elementu, które określa układ współrzędnych używany do rysowania i pozycjonowania kształtu. Punkt początkowy układu współrzędnych znajduje się w lewym górnym rogu, oś X jest skierowana w prawo, a oś Y – w dół.

Układ współrzędnych dla kształtów CSS

Pamiętaj, że shape-outside zmienia kształt obszaru pływającego, wokół którego będzie zawijana treść. Obszar pływający rozciąga się do zewnętrznych krawędzi pola określonego przez właściwość margin. Nazywa się to margin-box i jest domyślnym polem referencyjnym kształtu, jeśli nie określono żadnego innego.

Te 2 deklaracje CSS dają identyczne wyniki:

.element{
  shape-outside: circle(50% at 0 0);
  /* identical to: */
  shape-outside: circle(50% at 0 0) margin-box;
}

Nie ustawiliśmy jeszcze marginesu elementu. W tym momencie można bezpiecznie założyć, że początek układu współrzędnych i środek okręgu znajdują się w lewym górnym rogu obszaru zawartości elementu. Sytuacja zmienia się, gdy ustawisz marżę:

.element{
  shape-outside: circle(50% at 0 0) margin-box;
  margin: 100px;
}

Początek układu współrzędnych znajduje się teraz poza obszarem zawartości elementu (100 pikseli w górę i 100 pikseli w lewo), podobnie jak środek okręgu. Obliczona wartość promienia okręgu również rośnie, aby uwzględnić zwiększoną powierzchnię układu współrzędnych ustanowionego przez pole referencyjne margin-box.

Układ współrzędnych pola marginesu z marginesem i bez niego
Do wyboru jest kilka opcji pola referencyjnego: `margin-box`, `border-box`, `padding-box` i `content-box`. Ich nazwy wskazują na ich granice. Wcześniej wyjaśniliśmy, czym jest `margin-box`. `border-box` jest ograniczony zewnętrznymi krawędziami obramowania elementu, `padding-box` jest ograniczony dopełnieniem elementu, a `content-box` jest identyczny z rzeczywistym obszarem powierzchni używanym przez treść w elemencie.
Ilustracja wszystkich pól referencyjnych

W deklaracji shape-outside można użyć tylko jednego pola referencyjnego naraz. Każde pole referencyjne wpływa na kształt w inny, czasem subtelny sposób. W innym artykule znajdziesz więcej informacji o polach referencyjnych kształtów CSS.

Funkcja ellipse()

Ilustracja przedstawiająca wartość kształtu ellipse()

Elipsy wyglądają jak spłaszczone okręgi. Są one zdefiniowane jako ellipse(rx ry at cx cy), gdzie rx i ry to promienie elipsy na osiach X i Y, a cx i cy to współrzędne środka elipsy.

.element{
  shape-outside: ellipse(150px 300px at 50% 50%);
  width: 300px;
  height: 600px;
}

Wartości procentowe będą obliczane na podstawie wymiarów układu współrzędnych. Nie musisz wykonywać skomplikowanych obliczeń. Możesz pominąć współrzędne środka elipsy, a zostaną one wywnioskowane na podstawie środka układu współrzędnych.

Promienie na osiach X i Y można też zdefiniować za pomocą słów kluczowych: farthest-side daje promień równy odległości między środkiem elipsy a najbardziej oddalonym od niego bokiem pola referencyjnego, natomiast closest-side oznacza dokładne przeciwieństwo – użyj najkrótszej odległości między środkiem a bokiem.

.element{
  shape-outside: ellipse(closest-side farthest-side at 50% 50%);
  /* identical to: */
  shape-outside: ellipse(150px 300px at 50% 50%);
  width: 300px;
  height: 600px;
}

Może to być przydatne, gdy wymiary elementu (lub pole referencyjne) mogą się zmieniać w nieprzewidywalny sposób, ale chcesz, aby kształt elipsy się dostosowywał.

Te same słowa kluczowe farthest-side i closest-side można też stosować w przypadku promienia w funkcji kształtu circle().

Funkcja polygon()

Ilustracja przedstawiająca wartość kształtu polygon()

Jeśli okręgi i elipsy są zbyt ograniczające, funkcja kształtu wielokąta otwiera wiele możliwości. Format to polygon(x1 y1, x2 y2, ...), gdzie podajesz pary współrzędnych x y dla każdego wierzchołka (punktu) wielokąta. Minimalna liczba par do określenia wielokąta to 3 (trójkąt).

.element{
  shape-outside: polygon(0 0, 0 300px, 300px 600px);
  width: 300px;
  height: 600px;
}

Wierzchołki są umieszczone w układzie współrzędnych. W przypadku elastycznych wielokątów możesz używać wartości procentowych dla niektórych lub wszystkich współrzędnych.

.element{
  /* polygon responsive to font-size*/
  shape-outside: polygon(0 0, 0 100%, 100% 100%);
  width: 20em;
  height: 40em;
}

Istnieje opcjonalny parametr fill-rule, zaimportowany z SVG, który instruuje przeglądarkę, jak traktować „wnętrze” wielokąta w przypadku przecinających się ścieżek lub zamkniętych kształtów. Joni Trythall bardzo dobrze wyjaśnia, jak działa właściwość fill-rule w SVG. Jeśli nie jest zdefiniowany, fill-rule domyślnie przyjmuje wartość nonzero.

.element{
  shape-outside: polygon(0 0, 0 100%, 100% 100%);
  /* identical to: */
  shape-outside: polygon(nonzero, 0 0, 0 100%, 100% 100%);
}

Funkcja inset()

Funkcja kształtu inset() umożliwia tworzenie prostokątnych kształtów, wokół których można zawijać treść. Może to brzmieć sprzecznie z intuicją, biorąc pod uwagę początkowe założenie, że kształty CSS uwalniają treści z internetu od prostych pól. Bardzo możliwe. Nie udało mi się jeszcze znaleźć przypadku użycia inset(), którego nie można by było osiągnąć za pomocą elementów pływających i marginesów lub polygon(). Jednak inset() zapewnia bardziej czytelne wyrażenie dla kształtów prostokątnych niż polygon().

Pełny zapis funkcji kształtu wstawki to inset(top right bottom left border-radius). Pierwsze 4 argumenty pozycji to przesunięcia do wewnątrz od krawędzi elementu. Ostatni argument to promień obramowania prostokątnego kształtu. Jest to opcjonalne, więc możesz to pominąć. Jest zgodny ze skróconym zapisem border-radius, którego używasz już w CSS.

.element{
  shape-outside: inset(100px 100px 100px 100px);
  /* yields a rectangular shape which is 100px inset on all sides */
  float: left;
}

Tworzenie kształtów na podstawie pól referencyjnych

Jeśli nie określisz funkcji kształtu we właściwości shape-outside, możesz pozwolić przeglądarce na wygenerowanie kształtu z pola referencyjnego elementu. Domyślne pole referencyjne to margin-box. Na razie nic nadzwyczajnego, tak właśnie działają elementy pływające. Jeśli jednak zastosujesz tę technikę, możesz ponownie użyć geometrii elementu. Przyjrzyjmy się właściwości border-radius.

Jeśli użyjesz go do zaokrąglenia rogów elementu pływającego, uzyskasz efekt przycięcia, ale obszar pływający pozostanie prostokątny. Dodaj shape-outside: border-box, aby owinąć kontur utworzony przez border-radius.

Wyodrębnianie kształtu z promienia obramowania elementu za pomocą pola referencyjnego obramowania
.element{
  border-radius: 50%;
  shape-outside: border-box;
  float: left;
}

Oczywiście w ten sposób możesz używać wszystkich pól odniesienia. Here's another use for derived shapes - offset pull-quotes.

Tworzenie przesuniętego cytatu za pomocą pola referencyjnego content-box

Efekt przesuniętego cytatu można uzyskać, używając tylko właściwości float i margin. Wymaga to jednak umieszczenia elementu cytatu w drzewie HTML w miejscu, w którym ma on być renderowany.

Oto jak uzyskać ten sam efekt przesunięcia cytatu z dodatkową elastycznością:

.pull-quote{
  shape-outside: content-box;
  margin-top: 200px;
  float: left;
}

Wyraźnie ustawiamy pole referencyjne content-box dla układu współrzędnych kształtu. W tym przypadku ilość treści w cytacie określa kształt, wokół którego zawijana jest treść zewnętrzna. Właściwość margin-top służy tutaj do pozycjonowania (przesunięcia) cytatu niezależnie od jego pozycji w drzewie HTML.

Margines kształtu

Zauważysz, że zawijanie treści wokół kształtu może sprawić, że będzie ona zbyt blisko elementu. Możesz dodać odstępy wokół kształtu za pomocą właściwości shape-margin.

.element{
  shape-outside: circle(40%);
  shape-margin: 1em;
  float: left;
}

Efekt jest podobny do tego, który uzyskujesz, używając zwykłej właściwości margin, ale shape-margin wpływa tylko na przestrzeń wokół wartości shape-outside. Odstępy wokół kształtu zostaną dodane tylko wtedy, gdy w układzie współrzędnych jest na nie miejsce. Dlatego w powyższym przykładzie promień okręgu jest ustawiony na 40%, a nie na 50%. Gdyby promień był ustawiony na 50%, okrąg zajmowałby całą przestrzeń w układzie współrzędnych, nie pozostawiając miejsca na efekt shape-margin. Pamiętaj, że kształt jest ostatecznie ograniczony do margin-box elementu (elementu i otaczającego go margin). Jeśli kształt jest większy i wykracza poza ten obszar, zostanie przycięty do margin-box i będzie miał kształt prostokąta.

Pamiętaj, że shape-margin akceptuje tylko jedną wartość dodatnią. Nie ma zapisu w formie długiej. Czym właściwie jest shape-margin-top w przypadku koła?

Animowanie kształtów

Kształty CSS można łączyć z wieloma innymi funkcjami CSS, takimi jak przejścia i animacje. Muszę jednak podkreślić, że użytkownicy uważają za bardzo irytujące, gdy układ tekstu zmienia się podczas czytania. Jeśli zdecydujesz się na animowanie kształtów, zwróć szczególną uwagę na wrażenia użytkowników.

Możesz animować promienie i środki kształtów circle() i ellipse(), o ile są one zdefiniowane w wartościach, które przeglądarka może interpolować. Możesz przejść z circle(30%) na circle(50%). Jednak animowanie między circle(closest-side) a circle(farthest-side) spowoduje przeciążenie przeglądarki.

.element{
  shape-outside: circle(30%);
  transition: shape-outside 1s;
  float: left;
}

.element:hover{
  shape-outside: circle(50%);
}
GIF z animowanym okręgiem

Bardziej interesujące efekty można uzyskać, animując kształty polygon(), przy czym wielokąt musi mieć taką samą liczbę wierzchołków w obu stanach animacji. Przeglądarka nie może przeprowadzić interpolacji, jeśli dodasz lub usuniesz wierzchołki.

Jednym ze sposobów jest dodanie maksymalnej liczby potrzebnych wierzchołków i umieszczenie ich w skupisku w stanie animacji, w którym chcesz, aby kształt miał mniej widocznych krawędzi.

.element{
  /* four vertices (looks like rectangle) */
  shape-outside: polygon(0 0, 100% 0, 100% 100%, 0 100%);
  transition: shape-outside 1s;
}

.element:hover{
  /* four vertices, but second and third overlap (looks like triangle) */
  shape-outside: polygon(0 0, 100% 50%, 100% 50%, 0 100%);
}
GIF z animowanym trójkątem

Zawijanie treści w kształcie

Zrzut ekranu przedstawiający wersję demonstracyjną Alicji w Krainie Czarów, w której do zawijania treści użyto kształtów CSS

Wstępna wersja specyfikacji kształtów CSS zawierała właściwość shape-inside, która umożliwiała zawijanie treści wewnątrz kształtu. Przez pewien czas były nawet implementacje w Chrome i Webkit. Jednak umieszczenie treści o dowolnej pozycji w niestandardowej ścieżce wymaga znacznie więcej wysiłku i analizy, aby uwzględnić wszystkie możliwe scenariusze i uniknąć błędów. Dlatego właściwość shape-inside została przeniesiona do CSS Shapes Level 2, a jej implementacje zostały wycofane.

Jednak przy odrobinie wysiłku i kompromisu możesz uzyskać efekt zawijania treści w niestandardowym kształcie. Sztuczka polega na użyciu 2 elementów pływających z właściwością shape-outside, umieszczonych po przeciwnych stronach kontenera. Kompromis polega na tym, że musisz użyć 1 lub 2 pustych elementów, które nie mają znaczenia semantycznego, ale służą jako podpory do stworzenia iluzji kształtu wewnątrz.

<div>
  <div class='left-shape'></div>
  <div class='right-shape'></div>

  Lorem ipsum...
</div>

Pozycja elementów .left-shape i .right-shape u góry kontenera jest ważna, ponieważ będą one przesuwane w lewo i w prawo, aby otaczać treść.

.left-shape{
  shape-outside: polygon(0 0, ...);
  float: left;
  width: 50%;
  height: 100%;
}

.right-shape{
  shape-outside: polygon(50% 0, ...);
  float: right;
  width: 50%;
  height: 100%;
}
Ilustracja przedstawiająca obejście problemu z shape-inside w wersji demonstracyjnej Alice

Dzięki temu stylowi 2 pływające elementy strut zajmują całą przestrzeń w elemencie, ale właściwości shape-outside wyznaczają miejsce na pozostałą treść.

Jeśli przeglądarka nie obsługuje kształtów CSS, spowoduje to nieestetyczne efekty, ponieważ cała zawartość zostanie przesunięta w dół. Dlatego ważne jest, aby korzystać z tej funkcji w sposób progresywnego ulepszania.

We wcześniejszych przykładach animacji kształtu możesz zauważyć, że przesuwanie się tekstu może być uciążliwe. Nie wszystkie przypadki użycia wymagają animowanego kształtu. Możesz jednak animować inne właściwości, które współdziałają z kształtami CSS, aby dodać efekt tam, gdzie ma to sens.

W demonstracji kształtów CSS Alicja w Krainie Czarów użyliśmy pozycji przewijania, aby zmienić górny margines treści. Tekst jest ściśnięty między 2 elementami pływającymi. Przesuwając się w dół, musi zmienić układ zgodnie z shape-outside 2 elementów pływających. Daje to wrażenie, że tekst wpada do króliczej nory, co wzbogaca narrację. Treści bliskie łamania wytycznych? Być może. Ale wygląda fajnie.

Układ tekstu jest tworzony natywnie przez przeglądarkę, więc wydajność jest lepsza niż w przypadku rozwiązania JavaScript. Jednak zmiana właściwości margin-top podczas przewijania powoduje wywołanie wielu zdarzeń ponownego układu i renderowania, co może zauważalnie obniżyć wydajność. Używaj tej funkcji z rozwagą. Jednak używanie kształtów CSS bez ich animowania nie powoduje zauważalnego spadku wydajności.

Progresywne ulepszanie

Zacznij od założenia, że przeglądarka nie obsługuje kształtów CSS, i rozbuduj tę funkcję, gdy ją wykryjesz. Modernizr to dobre rozwiązanie do wykrywania funkcji, a w sekcji „Non-core detects” (Wykrywanie funkcji niestandardowych) znajduje się test kształtów CSS.

Niektóre przeglądarki umożliwiają wykrywanie funkcji w CSS za pomocą reguły @supports bez konieczności korzystania z zewnętrznych bibliotek. Google Chrome, która również obsługuje kształty CSS, rozumie regułę @supports. Oto jak używać go do progresywnego ulepszania:

.element{
  /* styles for all browsers */
}

@supports (shape-outside: circle(50%)){
  /* styles only for browsers which support CSS Shapes */
  .element{
    shape-outside: circle(50%);
  }
}

Lea Verou napisała więcej o używaniu reguły CSS @supports.

Uściślanie wykluczeń usług porównywania cen

To, co dziś znamy jako kształty CSS, na początku nazywało się wykluczeniami i kształtami CSS. Zmiana nazwy może wydawać się niuansem, ale w rzeczywistości jest bardzo ważna. Wykluczenia CSS, które są teraz osobną specyfikacją, umożliwiają zawijanie treści wokół elementów umieszczonych w dowolny sposób, bez konieczności stosowania właściwości float. Wyobraź sobie, że chcesz zawinąć treść wokół elementu o bezwzględnej pozycji – to właśnie przypadek użycia wykluczeń CSS. Kształty CSS definiują tylko ścieżkę, wokół której będzie zawijana treść.

Kształty i wykluczenia to nie to samo, ale uzupełniają się nawzajem. Kształty CSS są obecnie dostępne w przeglądarkach, ale wykluczenia CSS nie zostały jeszcze zaimplementowane w interakcji z kształtami.

Narzędzia do pracy z kształtami CSS

Ścieżki możesz tworzyć w klasycznych narzędziach do tworzenia obrazów, ale w momencie pisania tego artykułu żadne z nich nie eksportuje wymaganej składni wartości kształtów CSS. Nawet gdyby tak było, praca w ten sposób nie byłaby zbyt praktyczna.

Kształty CSS są przeznaczone do użycia w przeglądarce, gdzie reagują na inne elementy na stronie. Bardzo przydatne jest wizualizowanie efektów edytowania kształtu na treści, które go otaczają. W tym procesie mogą Ci pomóc te narzędzia:

Brackets: rozszerzenie CSS Shapes Editor dla Brackets używa trybu podglądu na żywo edytora kodu, aby nakładać interaktywny edytor do edytowania wartości kształtów.

Google Chrome: rozszerzenie CSS Shapes Editor do Google Chrome dodaje do narzędzi dla programistów w przeglądarce elementy sterujące do tworzenia i edytowania kształtów. Umieszcza interaktywny edytor nad wybranym elementem.

Inspektor w Google Chrome ma wbudowaną obsługę wyróżniania kształtów. Najedź kursorem na element z właściwością shape-outside, a zostanie on podświetlony, aby zilustrować kształt.

Kształty z obrazów: jeśli wolisz generować obrazy i pozwolić przeglądarce na wyodrębnianie z nich kształtów, Rebecca Hauck napisała dobry samouczek dotyczący Photoshopa.

Polyfill: Google Chrome to pierwsza popularna przeglądarka, która obsługuje kształty CSS. Wkrótce funkcja ta będzie obsługiwana w systemie Apple iOS 8 i przeglądarce Safari 8. Inni dostawcy przeglądarek mogą rozważyć tę opcję w przyszłości. Do tego czasu podstawową obsługę zapewnia polyfill kształtów CSS.

Podsumowanie

W internecie, gdzie treści są najczęściej zamknięte w prostych polach, kształty CSS umożliwiają tworzenie wyrazistych układów, co pozwala zmniejszyć różnicę w jakości między projektami stron internetowych i materiałów drukowanych. Oczywiście kształty mogą być nadużywane i rozpraszać uwagę. Jednak gdy są stosowane z wyczuciem i dobrym smakiem, kształty mogą ulepszyć prezentację treści i skupić uwagę użytkownika w unikalny sposób.

Na koniec zostawiam Cię z kolekcją prac innych osób, głównie z materiałów drukowanych, które pokazują ciekawe zastosowania układu nieprostokątnego. Mamy nadzieję, że zainspiruje Cię to do wypróbowania kształtów CSS i eksperymentowania z nowymi pomysłami na projekty.

Dziękujemy Pearl Chen, Alanowi Stearnsowi i Zoltanowi Horvathowi za sprawdzenie tego artykułu i podzielenie się cennymi spostrzeżeniami.