在Web網頁中主要是以矩形分布的。而平面媒體則傾向于更多不同的形狀。造成這種差異的原因是因為缺少合适的工具去實現我們平面媒體中的内容。這也就造成了很多設計師的創意發揮,就算是有創意,前端實現也将付出巨大的開發成本。
雖然CSS Shapes Module Level 1(CSS形狀模塊标準1)的規範出現,可以打破矩形設計的限制。但仍需要一些不規則的圖形。而早前實現一些不規則的圖形,都需借助其它的元素功能,比如CSS繪制圖形,很多時候就依賴于僞元素,或多個元素。如此一來,CSS Shapes依舊無法發揮其強大的功能,讓我們的Web打破常規的矩形布局。不過值得慶幸的是,CSS的clip-path
出現,它可以幫助我們繪制很多特殊的圖形(不規則的圖形),比如:
那麼這篇文章,我們就一起來了解這個屬性。
基本概念
clip-path
從單詞"clip path"的直譯上來說,表示的就是裁剪路徑。既然有裁剪,咱們就來了解這裡面的幾個簡單的概念。
裁剪就是從某樣東西剪切一塊。比如說,我們在<img>
元素上,根據需要,剪切一部分需要留下的區域。而在整個裁剪中,将會碰到兩個相關的概念:裁剪路徑(Clipping Path)和裁剪區域(Clipping Region)。
裁剪路徑是我們用來裁剪元素的路徑,它标記了我們需要裁剪的區域。它可以是個簡單的形狀(比如Web中常見的矩形),也可以是一個複雜的多邊形(不規則的多邊形)。
裁剪區域是裁剪路徑閉合後所包含的全部區域。
這樣一來,元素分為兩部分,裁剪區域和裁剪區域外。浏覽器會裁剪掉裁剪區域以外的區域,不僅是背景及其它類似的内容,也包括border
、text-shadow
等。更贊的是,浏覽器不會捕獲元素裁剪區域以外的 hover
、click
等事件。
即使如今一些特定元素不受長方形限制,但實際上元素周圍的内容還是會認為元素是原始形狀(長方形)的,并按此進行文檔流的布局。要想使周圍元素根據元素裁剪後的形狀進行布局,可以使用 shape-outside
屬性。有關于shape-outside
相關詳細的介紹,可以閱讀有關于CSS Shapes相關的教程,這裡不做過多闡述。
舊的clip
CSS Masking Module Level 1中也提供了一個clip
屬性。可以說clip
是CSS中出現的第一種裁剪技術。其實了解過clip
的同學都知道,它就是通過overflow:hidden
将裁剪區域外的元素隐藏掉了。可以說它不是真正的裁剪。
clip
屬性到目前為止,僅支持rect()
函數,就是裁剪出一個矩形(其它形狀還無法實現)。
clip: rect(<top>, <right>, <bottom>, <left>);
在CSS2.1中,rect()
和<top>
和<bottom>
指定偏移量是從元素盒子頂部邊緣算起;<left>
和<right>
指定的偏移量是從元素盒子左邊邊緣算起。
更為無奈的是,clip
屬性隻能在元素設置了position:absolute
或者position:fixed
起作用。無法在設置position:relative
和position:static
上工作。
在CSS中,clip
屬性是已過時的,也就是說它已經不再建議被使用,因為有一個更新的、規範的版本,各個浏覽器也将集中努力使用它。
當然,clip
也是有一些優勢的:因為clip
是運行在浏覽器中的,它可能會一直有效。而浏覽器對它的支持是非常強大的:幾乎是有史以來的每一個浏覽器。另外,我也聽說過了,它作出的動畫效果勝過其它的新方法。
但是比起它的優勢,clip
有兩個更為重要的弱點,這也使得它難以被廣泛地使用:
-
clip
隻對絕對定位的元素有效 -
clip
隻能用于矩形,即rect()
函數
這真的是非常大的限制!所以來讓我們接着說接下來更為重要的屬性clip-path
。
如果你是第一次接觸過
clip
屬性,我建議您花點時間閱讀一下這篇文章,它能幫助你對clip
有一個簡單的了解。
clip-path語法
W3C官方規範提供的clip-path
語法:
clip-path: <clip-source> | [ <basic-shape> || <geometry-box> ] | none
其默認值是none
。另外簡單介紹clip-path
幾個屬性值:
-
clip-source
: 可以是内、外部的SVG的<clipPath>
元素的URL引用 -
basic-shape
: 使用一些基本的形狀函數創建的一個形狀。主要包括circle()
、ellipse()
、inset()
和polygon()
。具體的說明可以看CSS Shapes中有關于說明。另外在CSS Shapes 101一文中也有詳細介紹。 -
geometry-box
: 是可選參數。此參數和basic-shape
函數一起使用時,可以為basic-shape
的裁剪工作提供參考盒子。如果geometry-box
由自身指定,那麼它會使用指定盒子形狀作為裁剪的路徑,包括任何(由border-radius
提供的)的角的形狀。
開始使用clip-path
在開始使用clip-path
繪制圖形,或者說裁剪圖形之前,有兩點需要大家注意:
-
使用
clip-path
要從同一個方向繪制,如果順時針繪制就一律順時針,逆時針就一律逆時針,因為polygon
是一個連續線段,若線段彼此有交集,裁剪區域就會有相減的情況發生,當然如果你特意需要這樣的效果除外。 - 如果繪制時采用比例的方式繪制,長寬就必須要先行設定,不然有可能繪制出來的長寬和我們想像的就會有差距,使用像素繪制就不會有這樣的現象。
先來看一個使用polygon()
函數繪制的示例:
img {
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}
這段代碼會将所有的圖片裁剪為菱形。但是為什麼圖片會被裁剪為菱形而不是梯形或平行四邊形之類的呢?這主要取決于函數頂點的值。下圖将說明一切:
每個點的第一個坐标值決定了它在 x
軸上的位置,第二個坐标值指定了它在 y
軸的位置,所有點是順時針繪制的。比如菱形最右邊的點,它位于 y
軸下方一半處,所以它的 y
坐标是 50%
。同時這個點位于 x
軸的最右側,所以它的 x
坐标是 100%
。其它點的坐标同理可得。
最後效果如下所示:
記得以前CSS繪制圖形總得束手束腳,而且還得想法設法,使用clip-path
繪制什麼六邊形、八邊形、五角形、心形等,都不再是難事了。OXXO.STUDIO有一篇文章《運用 clip-path 的純 CSS 形狀變換》詳細介紹了這些圖形是如何繪制的。當然除此之外,在線的CSS clip-path maker提供了很多不規則的圖形案例:
利用 geometry-box 裁剪元素
在具體使用geometry-box
來裁剪元素之前,對geometry-box
做一下相關的了解。
geometry-box
可以是shape-box
、fill
、stroke
或者view-box
。其中shape-box
應用于HTML元素,它具有四種值:margin-box
、border-box
、padding-box
和content-box
。
來看個簡單的示例:
.clip-me {
clip-path: polygon(10% 20%, 20% 30%, 50% 80%) margin-box;
margin: 10%;
}
在上例中,元素的 margin-box
會作為參考,來決定裁剪點的實際位置。點(10%,10%
)是 margin-box
的左上角,所以clip-path
的定位會根據此點進行計算。
其實shape-box
和CSS Shapes中的引用框概念非常類似,有關于這方面的介紹,可以花點時間閱讀《理解CSS Shapes的引用框》一文。
如果geometry-box
和basic-shape
一起使用,可以引用basic-shape
提供的引用框。其作用和shape-outside
屬性類似,更多的細節可以看看shape-outside
的屬性介紹。
如果geometry-box
由自身指定,那麼它會使用指定盒子形狀作為裁剪的路徑,包括任何(由border-radius
提供的)的角的形狀。
除了shape-box
值,還可以運用SVG元素上,它具有另外三個值:fill
、stroke
和view-box
。
clipPath 和clip-path
在SVG中有一個clipPath
元素。<clipPath>
元素不會直接在頁面上呈現,他唯一的作用就是可以通過clip-path
來引用。它和CSS的clip-path
還是有很大的區别。有關于兩者的詳細介紹可以閱讀《CSS和SVG中的剪切:clip-path
屬性和<clipPath>
元素》一文。
而很多時候兩者可以結合一起使用。
你不需要在CSS中定義clip-path
的值,因為它能夠引用SVG中定義的 <clipPath>
标簽元素。下面是它的使用示例:
HTML
<img class="clip-svg" src="harry.jpg" alt="Harry Potter">
<svg width="0" height="0">
<defs>
<clipPath id="myClip">
<circle cx="100" cy="100" r="40" />
<circle cx="60" cy="60" r="40" />
</clipPath>
</defs>
</svg>
CSS
.clip-svg {
clip-path: url(#myClip);
}
clip-path和masking
剪裁和遮罩都是用來隐藏元素的一些部分、顯示其他部分的。當然了,這兩者還是有區别的。區别主要在于這幾方面:他們能做的東西,不同的語法,涉及到的不同技術,是新的還是舊的,以及浏覽器支持的差異。
兩者最主要的區别:遮罩使用的是圖像,剪裁使用的是路徑。
想象一張從左到右、從黑到白漸變的正方形圖像,它可以是一個遮罩。對于應用了這個漸變遮罩圖像的元素,它在遮罩圖像的黑色部分是透明(透視)的,而在遮罩圖像的白色的部分是不透明(正常)的。所以作出的結論是:這個元素是從左到右淡入的。
而剪裁一直都是矢量路徑的。路徑之外的部分是透明的,路徑裡邊的部分是不透明的。
個人覺得有點混亂。因為很多時候可能會碰到某個關于遮罩的教程用的是一個在黑色上有白色矢量形狀的遮罩圖像,這和剪裁基本是同一個原理。但這還好,它隻是混淆了一點東西。
有關于兩者相關的詳細介紹可以點擊這裡閱讀。
clip-path和CSS Shapes
前面已經多次提到CSS Shapes了,是的,因為CSS Shapes可以幫助我們打破常規則的Web排版,讓Web頁面可以像媒體雜志一樣布局,這将是激動人心的一件事情。
而在CSS Shapes中同樣會有clip-path
的身影。
clip-path
接收與basic-shape
相同的形狀函數和值(前面提到過)。如果我們定義相同的多邊形形狀,同時用于shape-outside
與clip-path
屬性上,它将裁掉圖像上你定義的形狀之外的圖像。
img.right {
float: right;
height: 100vh;
width: calc(100vh + 100vh/4);
shape-outside: polygon(40% 0, 100% 0, 100% 100%, 40% 100%, 45% 60%, 45% 40%);
/* clip the image to the defined shape */
clip-path: polygon(40% 0, 100% 0, 100% 100%, 40% 100%, 45% 60%, 45% 40%);
}
結果如下:
看下在線示例:
有關于這方面的詳細介紹,可以點擊這裡。
clip-path示例和工具
前面内容簡單的提到過了,clip-path
是一個強大的屬性,除了自身能實現一些特殊效果之外,還可以和SVG結合在一起。另外還可以和Masking以及CSS Shapes在一起,做出我們意想不到的效果。那麼有關于clip-path
相關的案例,網上已經有大把了。除此之外,clip-path
還有一些在線的工具,可以直接幫助我們做一些事情。比如Chrome插件CSS Shapes 編輯器、Clip Path生成器和CSS clip-path Maker: Clippy。
最後強列建議大家收藏好下面這篇文章,因為這篇文章整理了18個有關于clip-path
的教程、案例和工具:
浏覽器兼容性
看到這裡,大家肯定會問,浏覽器兼容性如何?
IE 和 Edge 不支持這個屬性。Firefox 僅部分支持 clip-path
(它隻支持 url()
語法)。但是 47 以上的版本,激活 Firefox 的 layout.css.clip-path-shapes.enabled
選項就可以支持這個屬性了。
Chrome、Safari 和 Opera 需要使用 -webkit-
前綴支持此屬性。不幸的是,它們還不支持外部的 SVG 形狀。更多浏覽器支持性信息如下:
參考資料
總結
本文介紹了有關 clip-path
的基本内容,可以幫助你入門。學習使用這個屬性并不會花費太多的時間,但是創造性的使用就需要多多練習了。當浏覽器廣泛支持此屬性時,你就可以使用 clip-path
制作出酷炫的效果了。