Ścieżki, kształty, przycinanie i maskowanie

Renderowanie HTML jest oparte na modelu pudełkowym, ale życie (i projektowanie stron internetowych) to coś więcej niż prostokąty. CSS obsługuje wiele sposobów zmiany obszarów elementu, które są renderowane, co daje deweloperom swobodę tworzenia projektów obsługujących wszystkie kształty i rozmiary. Przycinanie umożliwia stosowanie kształtów geometrycznych, a maskowanie wpływa na widoczność na poziomie pikseli.

Ścieżki i kształty

CSS używa funkcji do definiowania kształtów. Ogólne informacje o funkcjach znajdziesz w module Funkcje CSS. W tej sekcji dowiesz się, jak tworzyć kształty w CSS. Wszystkie podane niżej przykłady korzystają z kształtów utworzonych za pomocą właściwości clip-path, która ogranicza widoczny obszar tylko do tego, co znajduje się wewnątrz kształtu. Dzięki temu elementy mogą wizualnie różnić się od pola elementu. Więcej informacji o przycinaniu znajdziesz w dalszej części tego artykułu.

Kształty zdefiniowane w CSS mogą być kształtami podstawowymi (takimi jak koła, prostokąty i wielokąty) lub ścieżkami (które mogą definiować złożone i złożone kształty).

Kształty podstawowe

circle()ellipse()

Funkcje circle()ellipse() definiują kształty okrągłe i owalne o promieniach względnych względem elementu. Funkcja circle() przyjmuje jako argument pojedynczy rozmiar lub wartość procentową. Domyślnie obie funkcje pozycjonują kształt względem środka elementu. Oba akceptują opcjonalną pozycję po słowie kluczowym at, którą można wyrazić jako długość, procent lub słowo kluczowe określające pozycję.

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: circle(50%);
}

Gdy funkcja circle() przyjmuje argument 50%, renderowane jest idealne koło.

W przykładzie powyżej pokazano okrągłą ścieżkę przycinania utworzoną za pomocą funkcji circle(). Pamiętaj, że promień 50% tworzy okrąg o pełnej szerokości elementu. Funkcja ellipse() przyjmuje 2 argumenty reprezentujące promienie poziomy i pionowy kształtu.

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: ellipse(50% 25%);
}

Funkcja ellipse() tworzy elipsę na podstawie argumentów procentowych. Argumenty 50% i 25% tworzą elipsę, która rozciąga się na osi X na podwójną długość promienia w porównaniu z osią Y.

W poprzednim przykładzie pokazano eliptyczną ścieżkę przycinania za pomocą funkcji ellipse(). Pamiętaj, że promień 50% tworzy elipsę o pełnej szerokości elementu. Poniższy przykład przedstawia tę samą elipsę, której środek znajduje się u góry elementu.

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: ellipse(50% 25% at center top);
}

rect()inset()

Funkcje rect()inset() umożliwiają zdefiniowanie prostokąta na różne sposoby przez określenie położenia jego boków względem boków elementu. Dzięki temu możesz tworzyć prostokąty, które wizualnie różnią się od domyślnego pola elementu. Opcjonalnie akceptują słowo kluczowe round, aby utworzyć prostokąt z zaokrąglonymi rogami, używając tej samej składni co właściwość skrócona border-radius.

Funkcja rect() określa położenie górnej i dolnej krawędzi prostokąta względem górnej krawędzi elementu oraz lewej i prawej krawędzi względem lewej krawędzi elementu. Ta funkcja przyjmuje 4 argumenty w jednostkach rozmiaru lub procentowych, które określają górną, prawą, dolną i lewą stronę. Funkcji rect() możesz użyć, gdy chcesz utworzyć prostokąt, którego rozmiar nie zmienia się wraz ze zmianą rozmiaru elementu lub którego proporcje pozostają takie same, gdy zmienia się rozmiar elementu.

.my-element {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: rect(15px 75px 45px 10px);
}

Funkcja rect() przyjmuje 4 argumenty określające rozmiar prostokąta. W tym przypadku argumenty to 15 pikseli, 75 pikseli, 45 pikseli i 10 pikseli.

W poprzednim przykładzie pokazano prostokątną ścieżkę przycinania zdefiniowaną za pomocą funkcji rect(). Wymiary są podawane względem górnej i lewej krawędzi elementu, jak pokazano na diagramie.

Funkcja inset() określa położenie boków prostokąta na podstawie odległości od każdego z boków elementu. Ta funkcja przyjmuje od 1 do 4 jednostek rozmiaru lub procentowych jako argumenty, co pozwala zdefiniować wiele boków naraz. Funkcji inset() możesz użyć, gdy chcesz utworzyć prostokąt, który skaluje się wraz z elementem, lub prostokąt, który znajduje się w stałej odległości od krawędzi elementu.

.my-element {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: inset(15px 5px 15px 10px);
}

Funkcja inset() może odejmować od wewnętrznego rozmiaru elementu. Argumenty tej funkcji na tym diagramie to 15 pikseli, 5 pikseli, 15 pikseli i 10 pikseli.

W poprzednim przykładzie pokazano prostokątną ścieżkę przycinania zdefiniowaną za pomocą funkcji inset(). Wymiary są określane względem boków elementu.

Funkcje rect() i inset() opcjonalnie akceptują słowo kluczowe round, aby utworzyć prostokąt z zaokrąglonymi rogami przy użyciu tej samej składni co właściwość skrócona border-radius. Poniższy przykład przedstawia zaokrąglone wersje prostokątów pokazanych wcześniej.

.rounded-rect {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: inset(15px 5px 15px 10px round 5px);
}

.rounded-inset {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: inset(15px 5px 15px 10px round 5px);
}

polygon()

W przypadku innych kształtów, takich jak trójkąty, pięciokąty, gwiazdy itp., funkcja polygon() umożliwia tworzenie kształtów przez łączenie wielu punktów liniami prostymi. Funkcja polygon() akceptuje listę par składających się z 2 jednostek długości lub procentowych. Każda para opisuje punkt na wielokącie: pierwsza wartość to odległość od lewej krawędzi elementu, a druga – odległość od górnej krawędzi elementu. Nie musisz zamykać wielokąta, ponieważ zostanie on ukończony przez połączenie ostatniego punktu z pierwszym.

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: polygon(
    50% 0,
    0 100%,
    100% 100%
  );
}

Funkcja polygon() akceptuje zmienną liczbę argumentów, aby rysować złożone kształty. W tym przypadku argumenty są tak dobrane, aby utworzyć trójkąt.

W poprzednim przykładzie utworzono trójkątną ścieżkę przycinania przez zdefiniowanie 3 punktów.

Domyślnie funkcja polygon() renderuje obszary nakładające się jako wypełnione. Możesz zmienić to zachowanie za pomocą opcjonalnego pierwszego argumentu o nazwie reguła wypełniania. Aby przełączać się między obszarami wypełnionymi i niewypełnionymi, ustaw regułę wypełniania na evenodd. Aby użyć domyślnej reguły wypełniania, ustaw ją na nonzero.

W przykładzie powyżej pokazano funkcję polygon() z funkcjami trygonometrycznymi, które służą do tworzenia wielokątów foremnych i gwiazd. Nie tworzy to największego możliwego wielokąta foremnego, który mieści się w elemencie, ani nie wyśrodkowuje go – pozostawimy to jako ćwiczenie do samodzielnego wykonania. Kształty gwiazd w tym przykładzie pokazują też reguły wypełniania nonzero i evenodd.

Złożone kształty

Gdy podstawowe funkcje kształtu nie wystarczają do opisania złożonego kształtu, CSS udostępnia funkcje, które używają bardziej zaawansowanej składni do opisywania cech takich jak krzywe i linie. Te funkcje są też przydatne w przypadku kształtów złożonych (składających się z wielu kształtów, np. koła z otworem).

path()

Funkcja path() akceptuje ciąg znaków składni ścieżki SVG, aby opisać kształt. Umożliwia to tworzenie złożonych kształtów za pomocą instrukcji opisujących linie i krzywe, z których się składają. Bezpośrednie edytowanie składni SVG może być skomplikowane, dlatego zalecamy używanie specjalnego edytora wizualnego, który może eksportować składnię podczas tworzenia kształtów za pomocą funkcji path().

Funkcja path() nie używa jednostek rozmiaru CSS, a wszystkie wartości są interpretowane jako piksele. Oznacza to, że kształty utworzone za pomocą funkcji ścieżki nie reagują na rozmiar elementu ani kontenera. Zalecamy używanie path() tylko w przypadku kształtów o stałych wymiarach.

shape()

Funkcja shape() używa składni poleceń do opisywania kształtu, podobnie jak funkcja path(). Jednak polecenia funkcji shape() są natywnym kodem CSS i mogą używać jednostek rozmiaru CSS. Umożliwia to zmianę rozmiaru kształtów zdefiniowanych za pomocą funkcji shape().

W powyższym przykładzie użyto funkcji path()shape() do zdefiniowania kształtu serca i okręgu z otworem w środku. W przykładzie w przypadku obu funkcji użyto tej samej wartości w pikselach, ale funkcje shape() mogły też używać innych jednostek rozmiaru CSS, takich jak procenty lub jednostki względne kontenera.

Obcinanie

Przycinanie określa, które obszary elementu są widoczne, podobnie jak przycinanie obrazu z magazynu. Właściwość clip-path ustawia ścieżkę używaną do określania obszaru przycięcia.

Jak widać w przykładach z poprzedniej sekcji, dowolna z podstawowych funkcji kształtu lub ścieżki może być używana jako clip-path. Właściwość clip-path obsługuje też ścieżki zdefiniowane w elemencie SVG clipPath, który może być osadzony lub znajdować się w osobnym pliku.

Jak przycinanie może wpływać na obraz: na tym obrazie zdjęcie kociaka jest przycięte zarówno do kształtu koła, jak i do złożonej ścieżki przycinania, która w całości otacza kociaka.

Na powyższym diagramie widać, jak dodanie atrybutu clip-path do elementu obrazu zmienia widoczny obszar obrazu. Górna ścieżka przycinania korzysta z funkcji circle(), a dolna z elementu SVG clipPath. Pamiętaj, że okrąg utworzony za pomocą funkcji circle() jest domyślnie wyśrodkowany na elemencie.

W przypadku właściwości clip-path można podać tylko jedną ścieżkę. Aby przyciąć element za pomocą wielu kształtów, które się nie nakładają, użyj funkcji path() lub shape(), aby zdefiniować ścieżkę złożoną, albo użyj elementu SVG clipPath. W bardziej złożonych przypadkach zamiast przycinania możesz użyć maskowania, o którym piszemy w dalszej części tego artykułu.

Przycinanie za pomocą kształtów

Aby przyciąć element za pomocą podstawowego kształtu lub funkcji ścieżki, ustaw właściwość clip-path na wartość zwróconą przez funkcję, jak w poprzednich przykładach. Każda funkcja pozycjonuje kształt przycinania inaczej względem elementu, więc zapoznaj się z informacjami o poszczególnych funkcjach.

W powyższym przykładzie 2 elementy mają okrągły kształt clip-path zastosowany za pomocą klasy .clipped. Pamiętaj, że clip-path jest umieszczony względem każdego elementu, a tekst w clip-path nie jest dopasowywany do kształtu.

pole odniesienia ścieżki przycinania,

Domyślnie ścieżka przycinania elementu obejmuje jego obramowanie. Gdy używasz jednej z funkcji kształtu podstawowego, możesz ustawić pole odniesienia przycięcia tak, aby obejmowało tylko obszar elementu w obrębie obramowania. Prawidłowe wartości pola odniesienia to stroke-box (wartość domyślna) i fill-box (aby uwzględnić tylko obszar wewnątrz obramowania).

W przykładzie powyżej widać elementy z szerokim obramowaniem (20px), z których każdy używa funkcji inset() do ustawienia clip-path. Element, który przycina względem obramowania elementu, nadal wyświetla część obramowania. Elementy, które są przycinane względem obszaru wewnątrz obramowania, nie mają obramowania i są mniejsze, nawet przy tej samej wartości wcięcia.

Przycinanie za pomocą grafiki

Ścieżka przycinania może być zdefiniowana w dokumencie SVG, osadzonym w dokumencie HTML lub do którego odwołanie jest zewnętrzne. Może to być przydatne do definiowania złożonych ścieżek przycinania utworzonych w programach graficznych lub ścieżek przycinania, które łączą wiele kształtów.

<img id="kitten" src="kitten.png">

<svg>
  <defs>
    <clipPath id="kitten-clip-shape">
      <circle cx="130" cy="175" r="100" />
    </clipPath>
  </defs>
</svg>

<style>
  #kitten {
    clip-path: url(#kitten-clip-shape);
  }
</style>

W poprzednim przykładzie element clipPath z atrybutem id o wartości kitten-clip-shape jest stosowany do elementu <img>. W tym przypadku dokument SVG jest umieszczony w kodzie HTML. Jeśli dokument SVG jest plikiem zewnętrznym o nazwie kitten-clipper.svg, element clipPath będzie odwoływać się do url(kitten-clipper.svg#kitten-clip-shape).

Zamaskowanie

Maskowanie to kolejna metoda określania, które obszary elementu mają być widoczne lub ukryte. Przycinanie wykorzystuje podstawowe kształty lub ścieżki, a maskowanie – piksele z obrazu lub gradientu, aby określić widoczność. W przeciwieństwie do przycinania maskowanie umożliwia częściową przezroczystość obszarów elementu. Do elementu można zastosować wiele obrazów maski, aby uzyskać różne efekty.

Aby zastosować maskę, ustaw właściwość mask-image. Ta właściwość akceptuje co najmniej 1 obraz, gradient lub odwołanie do elementów <mask> w dokumencie SVG. Możesz zastosować wiele obrazów maski, oddzielając je przecinkami.

.my-element {
  mask-image: url(my-mask.png),
              linear-gradient(black 0%, transparent 100%);
}

W powyższym przykładzie element .my-element jest maskowany za pomocą obrazu PNG, a następnie gradientu liniowego. Domyślnie wiele masek jest dodawanych do siebie, aby utworzyć maskę końcową.

W przykładzie powyżej widać obraz z co najmniej jedną zastosowaną maską. Przełączaj poszczególne maski, aby zobaczyć, jak się sumują i tworzą efekt końcowy.

Maskowanie alfa a maskowanie luminancją

Maskę możesz zastosować, używając alpha lub luminance obrazu. Podczas maskowania na podstawie elementu alpha do elementu stosowana jest przezroczystość każdego piksela na obrazie maski, z pominięciem informacji o kolorze tego piksela. Podczas maskowania na podstawie luminance do elementu stosowana jest zarówno przezroczystość, jak i wartość każdego piksela (jasność lub ciemność). Maskowanie według luminancji traktuje jaśniejsze kolory jako widoczne, a ciemniejsze jako niewidoczne.

Aby ustawić tryb maskowania, użyj właściwości mask-mode. Domyślnie właściwość mask-mode ma wartość match-source, która ustawia tryb na podstawie typu obrazu maski. W przypadku obrazów i gradientów domyślnie będzie to alpha. W przypadku masek SVG domyślną wartością będzie wartość właściwości mask-type elementu <mask> lub luminance, jeśli nie zdefiniowano właściwości mask-type.

W powyższym przykładzie jako maski użyto wzorca testowego pokazującego różne wartości koloru i alfa. Przełączając mask-mode, możesz zobaczyć, że tryb alpha opiera się na przejrzystości, a tryb luminance – na jasności koloru i przejrzystości.

Dodatkowe właściwości maskowania

CSS udostępnia dodatkowe właściwości, które pozwalają precyzyjnie dostosować działanie masek. Każda z tych właściwości akceptuje rozdzieloną przecinkami listę wartości, które będą dopasowywane do listy masek ustawionej przez właściwość mask-image. Jeśli wartości jest mniej niż masek, lista będzie powtarzana, dopóki dla każdej maski nie zostanie ustawiona wartość. Jeśli wartości jest więcej niż masek, nadmiarowe wartości są odrzucane.

Właściwość Opis
mask-clip

Określa, do którego pola odniesienia elementu mają być stosowane maski. Domyślna wartość to border-box..

mask-composite

Określa interakcję między maskami, gdy do tego samego elementu zastosowano kilka masek. Domyślna wartość to add.

mask-origin

Ustawia pole odniesienia, które służy jako punkt początkowy maski. Domyślna wartość to border-box. Działa podobnie jak background-origin i akceptuje te same słowa kluczowe.

mask-position

Ustawia pozycję maski względem elementu mask-origin. Akceptuje wartości słów kluczowych pozycji, takie jak top lub center, wartości procentowe, jednostki rozmiaru lub wartości względne w stosunku do słowa kluczowego pozycji. Działa podobnie do funkcji background-position i akceptuje te same typy argumentów.

mask-repeat

Określa, jak maska jest powtarzana, jeśli element zamaskowany jest większy od maski. Domyślna wartość to repeat. Działa podobnie do funkcji background-repeat i akceptuje te same typy argumentów.

mask-size

Określa, jak maska zmienia rozmiar względem rozmiaru maskowanego elementu. Domyślna wartość to auto. Działa podobnie do funkcji background-size i akceptuje te same typy argumentów.

Skrót maski

Za pomocą skrótu maski możesz ustawić jednocześnie wiele właściwości maski. Może to uprościć ustawianie wielu masek, ponieważ wszystkie właściwości każdej maski są zgrupowane. Skrót maski jest równoważny ustawieniu tych właściwości w kolejności: mask-image, mask-mode, mask-position, mask-size, mask-repeat, mask-origin, mask-clipmask-composite. Nie musisz uwzględniać wszystkich właściwości. Te, które nie zostaną uwzględnione, zostaną zresetowane do wartości początkowej. Każda maska może obsługiwać do 8 właściwości, dlatego warto mieć dostęp do pełnej dokumentacji.

.longhand {
  mask-image: linear-gradient(white, black),
              linear-gradient(90deg, black, transparent);
  mask-mode: luminance, alpha;
  mask-position: bottom left, top right;
  mask-size: 50% 50%, 30% 30%;
}

.shorthand {
  mask: linear-gradient(white, black) luminance bottom left / 50% 50%,
        linear-gradient(90deg, black, transparent) alpha top right / 30% 30%;
}

W powyższym przykładzie do każdej klasy zastosowano 2 maski. Pierwszy przykład używa poszczególnych właściwości, a drugi – skrótu mask. Oba style są równoważne.

Tekst ciągły wokół elementów pływających

Przycinając lub maskując element, zmieniasz tylko widoczny obszar w jego polu, ale samo pole pozostaje bez zmian. Oznacza to, że element pływający będzie wpływać na przepływ dokumentu na podstawie oryginalnego pola ograniczającego, a nie widocznych części elementu. Aby zdefiniować przepływ wokół elementu, użyj właściwości shape-outside wraz ze ścieżką przycinania.

Właściwość shape-outside określa kształt, wokół którego będzie przepływać treść elementu. Może to być dowolna z podstawowych funkcji kształtu, ale nie kształty zdefiniowane za pomocą funkcji path() lub shape() ani clipPath zdefiniowany w dokumencie SVG.

Właściwość shape-outside akceptuje też obraz lub gradient. Podobnie jak w przypadku maskowania, granice kształtu będą zależeć od przezroczystości obrazu lub gradientu. Właściwość shape-image-threshold określa, które poziomy przezroczystości są uwzględniane w kształcie.

Kształty w animacji

Animowanie przycinania

Możesz animować właściwość clip-path, płynnie przechodząc od jednego kształtu do drugiego. Aby uzyskać płynne animacje, musisz używać tej samej funkcji kształtu dla każdej klatki kluczowej. Podczas korzystania z funkcji polygon() lub shape() w każdej klatce kluczowej musi być użyta ta sama liczba punktów.

W powyższym przykładzie clip-path elementu zmienia się z pięciokąta na gwiazdę zdefiniowaną za pomocą funkcji polygon(). W przykładzie użyto reguły wypełniania evenodd, aby pokazać, jak animowane punkty tworzą obszary nakładające się na siebie.

Animowanie za pomocą ścieżki przesunięcia

Możesz też animować elementy wzdłuż ścieżek utworzonych za pomocą tych funkcji kształtu. Właściwość offset-path określa kształt, który ma być używany jako ścieżka, a właściwość offset-distance określa pozycję wzdłuż tej ścieżki. Możesz też użyć funkcji ray() z właściwością offset-path, aby animować wzdłuż linii prostej.

W przykładzie powyżej pokazano, jak używać tego samego wielokąta zarówno w przypadku clip-path, jak i offset-path. Animacja wykorzystuje offset-distance do przesuwania mniejszych gwiazd wzdłuż tego samego wielokąta, którego duża gwiazda używa jako clip-path.

Sprawdź swoją wiedzę

Które z poniższych funkcji kształtu są prawidłowe?

circle()
Dobrze!
square()
Źle.
hexagon()
Źle.
polygon()
Dobrze!
rectangle()
Źle.
inset()
Dobrze!

Prawda czy fałsz: kształty zdefiniowane za pomocą funkcji path() można określać za pomocą wartości procentowych.

Prawda
Źle.
Fałsz
Dobrze!

Prawda czy fałsz: ustawienie ścieżki przycinania elementu nie zmieni przepływu tekstu wokół niego.

Prawda
Dobrze!
Fałsz
Źle.

Które z tych elementów mogą być użyte jako ścieżka przycinania?

podstawowy kształt,
Dobrze!
Element SVG clipMask
Dobrze!
obraz bitmapowy,
Źle.
gradient,
Źle.

Które z tych elementów można wykorzystać jako maskę?

obraz bitmapowy,
Dobrze!
gradient,
Dobrze!
Element maski SVG
Dobrze!
podstawowy kształt, np. circle() lub rect();
Źle.