HTML 算繪是建構在方塊模型之上,但生活 (和網頁設計) 不只有矩形。CSS 支援多種方式來變更元素的算繪區域,開發人員可自由建立支援所有形狀和大小的設計。剪裁可使用幾何形狀,遮罩則會影響像素層級的可視度。
路徑和形狀
CSS 會使用函式定義形狀。我們在 CSS 函式模組中介紹了函式的一般資訊。本節將說明如何使用 CSS 建立形狀。下列所有範例都使用您透過 clip-path
屬性建立的形狀,將可見區域縮減為形狀內的部分。這樣一來,元素在視覺上就會與元素方塊有所不同。我們稍後會詳細說明剪輯功能。
CSS 中定義的形狀可以是基本形狀 (例如圓形、矩形和多邊形),也可以是路徑 (可定義複雜和複合形狀)。
基本形狀
circle()
和ellipse()
circle()
和 ellipse()
函式會定義圓形和橢圓形,半徑與元素相關。circle()
函式接受單一大小或百分比做為引數。根據預設,這兩個函式都會將形狀放置在元素中心。兩者都接受 at
關鍵字後方的選用位置,可以長度、百分比或位置關鍵字表示。
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: circle(50%);
}
上例顯示使用 circle()
函式的圓形剪輯路徑。請注意,50%
的半徑會建立元素全寬的圓形。ellipse()
函式會接受兩個引數,分別代表形狀的水平和垂直半徑。
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: ellipse(50% 25%);
}
上例顯示使用 ellipse()
函式的橢圓形剪輯路徑。請注意,50% 的半徑會建立元素全寬的橢圓。以下範例顯示的橢圓中心位於元素頂端。
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: ellipse(50% 25% at center top);
}
rect()
和inset()
rect()
和 inset()
函式提供不同的方式來定義矩形,方法是設定矩形邊相對於元素邊的位置。您可以建立與元素預設方塊在視覺上不同的矩形。這些函式可選擇性接受 round
關鍵字,使用與 border-radius
簡寫屬性相同的語法,建立圓角矩形。
rect()
函式會定義矩形頂端和底部的相對位置 (相對於元素頂端),以及左右兩側的相對位置 (相對於元素左側)。這個函式會接受四個大小或百分比單位做為引數,分別定義頂端、右側、底部和左側。如果希望矩形在元素大小變更時不會縮放,或是希望矩形在元素變更時維持相同比例,可以選擇 rect()
函式。
.my-element {
width: 80px;
height: 60px;
background: blue;
clip-path: rect(15px 75px 45px 10px);
}
上例顯示使用 rect()
函式定義的矩形剪輯路徑。如圖所示,這些維度是以元素的頂端和左側邊緣為基準。
inset()
函式會根據元素各邊的內縮距離,定義矩形各邊的位置。這個函式接受一到四個大小或百分比單位做為引數,可讓您一次定義多個邊。如要建立隨元素縮放的矩形,或與元素邊緣保持固定距離的矩形,可以選擇 inset()
函式。
.my-element {
width: 80px;
height: 60px;
background: blue;
clip-path: inset(15px 5px 15px 10px);
}
上例顯示使用 inset()
函式定義的矩形剪輯路徑。尺寸是相對於元素兩側。
rect()
和 inset()
函式可選擇接受 round
關鍵字,使用與 border-radius
簡寫屬性相同的語法,建立圓角矩形。以下範例顯示先前矩形的圓角版本。
.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()
如果是三角形、五邊形、星形等其他形狀,您可以使用 polygon()
函式,以直線連接多個點來建立形狀。polygon()
函式接受由兩個長度或百分比單位組成的配對清單。每個配對都描述多邊形上的一個點:第一個值是與元素左側邊緣的距離,第二個值是與元素頂端邊緣的距離。您不必封閉多邊形,因為系統會將最後一個點與第一個點連線,完成多邊形。
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: polygon(
50% 0,
0 100%,
100% 100%
);
}
上例會定義三個點,建立三角形裁剪路徑。
根據預設,polygon()
函式會將重疊區域算為已填入。您可以透過選用的第一個引數 (稱為填滿規則) 變更這項行為。如要在填滿和未填滿的區域之間交替,請將填滿規則設為 evenodd
。如要使用預設填滿規則,請將其設為 nonzero
。
上例顯示如何使用 polygon()
函式和三角函數,建立正多邊形和星形。這不會建立可放入元素內或置中的最大可能正多邊形,我們將這項練習留給您嘗試。本例中的星形也示範了 nonzero
和 evenodd
填滿規則。
複雜形狀
如果基本形狀函式不足以描述複雜形狀,CSS 會提供使用更精細語法的函式,描述曲線和線條等特徵。這些函式也適用於複合形狀 (由多個形狀組成的形狀,例如有洞的圓形)。
path()
path()
函式會接受 SVG 路徑語法字串,用來描述形狀。這樣一來,您就能使用描述構成形狀的線條和曲線的指令,建立複雜形狀。直接編輯 SVG 語法可能很複雜,因此建議您考慮使用專屬的視覺化編輯器,在透過 path()
函式建立形狀時匯出語法。
path()
函式不會使用 CSS 大小單位,所有值都會解讀為像素。也就是說,使用路徑函式建立的形狀不會根據元素或容器大小調整。建議只將 path()
用於尺寸固定的形狀。
shape()
shape()
函式會使用指令語法描述形狀,與 path()
函式類似。不過,shape()
函式指令是原生 CSS,可以使用 CSS 大小單位。這樣一來,使用 shape()
函式定義的形狀就能以回應式方式調整大小。
上例使用 path()
和 shape()
函式定義愛心形狀和中央有洞的圓形。這個範例在兩個函式中都使用相同的像素值,但 shape()
函式也可以使用其他 CSS 大小單位,例如百分比或容器相對單位。
剪輯
剪裁會定義元素的哪些區域可見,類似於從雜誌剪裁圖片。clip-path
屬性會設定用於定義裁剪區域的路徑。
如先前章節的範例所示,任何基本形狀或路徑函式都可以做為 clip-path
。clip-path
屬性也支援在 SVG clipPath
元素中定義的路徑,這些路徑可以內嵌或位於獨立檔案中。
上圖顯示在圖片元素中加入 clip-path
後,圖片的可見區域會如何變化。上方剪輯路徑使用 circle()
函式,下方則使用 SVG clipPath
。請注意,使用 circle()
函式建立的圓圈預設會置中於元素。
clip-path
屬性僅接受單一路徑。如要使用多個不重疊的形狀裁剪元素,請使用 path()
或 shape()
函式定義複合路徑,或使用 SVG clipPath
。在複雜情境中,您也可以使用遮罩而非剪輯,我們會在後續章節中說明。
使用形狀裁剪
如要使用基本形狀或路徑函式裁剪,請將 clip-path
屬性設為函式傳回的值,如上述範例所示。每個函式都會以不同方式相對於元素放置剪裁形狀,因此請參閱每個函式的參照。
在上例中,兩個元素都使用 .clipped
類別套用圓形 clip-path
。請注意,clip-path
是相對於每個元素定位,且 clip-path
內的文字不會重新排版來配合形狀。
裁剪路徑的參照方塊
根據預設,元素的裁剪路徑會包含元素的邊框。使用其中一個基本形狀函式時,您可以將剪輯路徑的參照方塊設為只包含邊框內的元素區域。參考方塊的有效值為 stroke-box
(預設值) 和 fill-box
(僅包含邊界內的區域)。
上例顯示具有大型 (20px
邊框) 的元素,每個元素都使用 inset()
函式設定 clip-path
。相對於元素邊界裁剪的元素仍會顯示部分邊界。相對於邊界內區域裁剪的元素不會顯示任何邊界,而且即使使用相同的插邊值,也會較小。
使用圖形剪裁
剪裁路徑可以在 SVG 文件中定義,並嵌入 HTML 文件或從外部參照。這項功能可用於定義在繪圖程式中建立的複雜剪裁路徑,或合併多個形狀的剪裁路徑。
<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>
在上述範例中,具有 kitten-clip-shape
id
的 clipPath
會套用至 <img>
元素。在本例中,可擴充向量圖形文件會嵌入 HTML。如果 SVG 文件是名為 kitten-clipper.svg
的外部檔案,則 clipPath
會改為參照 url(kitten-clipper.svg#kitten-clip-shape)
。
遮罩
遮罩是另一種方法,可定義要顯示或隱藏元素的哪些區域。裁剪是使用基本形狀或路徑,而遮罩則是使用圖片或漸層的像素來決定可見度。與剪裁不同,遮罩可讓元素區域呈現半透明狀態。您可以對元素套用多張遮罩圖片,產生各種效果。
如要套用遮罩,請設定 mask-image
屬性。這個屬性可接受一或多張圖片、漸層,或 SVG 文件中 <mask>
元素的參照。如要套用多個遮罩圖片,請以半形逗號分隔。
.my-element {
mask-image: url(my-mask.png),
linear-gradient(black 0%, transparent 100%);
}
在上述範例中,.my-element
會使用 PNG 圖片遮蓋,然後套用線性漸層。系統預設會將多個遮罩加在一起,建立最終遮罩。
上例顯示套用一或多個遮罩的圖片。切換各個遮罩,即可查看遮罩如何加總,產生最終效果。
Alpha 遮罩與亮度遮罩
你可以使用圖片的 alpha
或 luminance
套用遮罩。如果根據 alpha
遮蓋,系統會將遮罩圖片中每個像素的透明度套用至元素,並忽略該像素的任何色彩資訊。根據 luminance
遮罩時,系統會將每個像素的透明度和值 (亮度或暗度) 套用至元素。亮度遮罩會將較亮的顏色視為可見,較深的顏色視為不可見。
如要設定遮罩模式,請使用 mask-mode
屬性。根據預設,mask-mode
屬性會設為 match-source
,並根據遮罩圖片類型設定模式。如果是圖片和漸層,這項設定預設為 alpha
。如果是 SVG 遮罩,這項屬性會預設為 <mask>
元素的 mask-type
屬性值,如果沒有定義 mask-type
,則會預設為 luminance
。
在上例中,顯示不同顏色和 Alpha 值的測試模式會做為遮罩。切換 mask-mode
,即可查看 alpha
模式的透明度,以及 luminance
模式的色彩亮度和透明度。
其他遮蓋屬性
CSS 提供額外屬性,可微調遮罩的行為。每個屬性都接受以半形逗號分隔的值清單,這些值會與 mask-image
屬性設定的遮罩清單相符。如果值少於遮罩,系統會重複清單,直到為每個遮罩設定值為止。如果值的數量多於遮罩,系統會捨棄多餘的值。
屬性 | 說明 |
---|---|
mask-clip |
設定要套用元素遮罩的參照方塊。預設值為 |
mask-composite |
設定將多個遮罩套用至同一元素時,遮罩之間的互動。預設值為 |
mask-origin |
設定做為遮罩來源的參照方塊。預設為 |
mask-position |
設定遮罩相對於 |
mask-repeat |
如果遮罩元素大於遮罩,設定遮罩的重複方式。預設為 |
mask-size |
設定遮罩相對於遮罩元素大小的縮放方式。預設為 |
遮罩速記
您可以使用遮罩簡寫,一次設定多個遮罩屬性。將每個遮罩的所有屬性分組在一起,即可簡化多個遮罩的設定。遮罩簡寫相當於依序設定下列屬性:mask-image
、mask-mode
、mask-position
、mask-size
、mask-repeat
、mask-origin
、mask-clip
和 mask-composite
。不一定要納入所有屬性,未納入的屬性會重設為初始值。每個遮罩最多可支援八個屬性,因此建議您備妥完整參考資料。
.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%;
}
在上述範例中,每個類別都套用了兩個遮罩。第一個範例使用個別屬性,第二個範例則使用 mask
簡寫。這兩種樣式彼此等效。
浮動元素周圍的文字重排
裁剪或遮罩元素時,您只會變更方塊內的顯示區域,方塊本身則維持不變。也就是說,浮動元素會根據原始的周框影響文件流程,而不是元素的顯示部分。如要定義元素周圍的流動方式,請使用 shape-outside
屬性和裁剪路徑。
shape-outside
屬性會定義內容在元素周圍流動的形狀。這個形狀可以是任何基本形狀函式,但不能是使用 path()
或 shape()
函式定義的形狀,也不能是 SVG 文件中定義的 clipPath
。
shape-outside
屬性也接受圖片或漸層。與遮罩一樣,形狀的邊界取決於圖片或漸層的透明度。shape-image-threshold
屬性會設定形狀內要考量的透明度等級。
動畫中的形狀
建立 clip-path 動畫
您可以為 clip-path
屬性加入動畫效果,在形狀之間混合。您必須為每個關鍵影格使用相同的形狀函式,才能製作流暢的動畫。使用 polygon()
或 shape()
函式時,每個關鍵影格必須使用相同數量的點。
在上一個範例中,元素的 clip-path
會在五邊形和星形之間轉換,這些形狀是使用 polygon()
函式定義。這個範例使用 evenodd
填滿規則,說明動畫點如何建立重疊區域。
使用 offset-path 製作動畫
您也可以沿著使用這些形狀函式建立的路徑,以動畫呈現元素。offset-path
屬性會設定要用做路徑的形狀,而 offset-distance
則會設定該路徑上的位置。您也可以搭配 offset-path
屬性使用 ray()
函式,沿直線製作動畫。
上例示範如何對 clip-path
和 offset-path
使用相同的多邊形。動畫會使用 offset-distance
,沿著大星星使用的相同多邊形移動較小的星星,做為 clip-path
。
隨堂測驗
下列何者是有效的形狀函式?
circle()
square()
hexagon()
polygon()
rectangle()
inset()
是非題:使用 path()
函式定義的形狀可以使用百分比定義
是非題:設定元素的剪裁路徑不會改變元素周圍的文字流程
下列何者可做為剪裁路徑?
clipMask
元素下列何者可用做遮罩?
circle()
或 rect()