寫給自己看的CSS shapes佈局教程
byzhangxinxu from https://www.zhangxinxu.com/wordpress/?p=8453
本文可全文轉載,個人網站無需授權,只要保留原作者、出處以及文中連結即可,任何網站均可摘要聚合,商用請聯絡授權。
一、前言&索引
CSS Shapes佈局可以實現不規則的文字環繞效果,需要和浮動配合使用。
相容性如下圖:
還是很不錯的,移動端可用,內部中後臺專案可用。
CSS shapes佈局相關屬性並不多,學習成本比grid佈局,flex佈局小很多。
Shapes佈局相關屬性 |
---|
二、詳細瞭解shape-outside
shape-outside
是不規則形狀環繞佈局的核心,支援的屬性值分為如下四大類:
- none – 預設值
- <shape-box> – 圖形盒子。
- <basic-shape> – 基本圖形函式。
- <image> – 影象類。
其中:
-
none
很好理解,表示就是普通的矩形環繞。 -
<shape-box>
(圖形盒子)是shape相關佈局中的一個名詞,比clip-path
屬性中的<geometry-box>
(幾何盒子)支援的盒子要少一些,就是CSS2.1中的基本盒模型的4種盒子,分別是margin-box
,border-box
,padding-box
和content-box
。要來指定文字環繞的時候是依照哪個盒子的邊緣來計算的。 -
<basic-shape>
指的是基本形狀函式,和CSSclip-path剪裁屬性支援的基本形狀函式一模一樣。 -
<image>
值的是影象類,包括URL連結圖片,漸變影象,cross-fade(),element()等。所有這些影象類,CSS3 mask遮罩屬性也都支援,本文只會介紹常用的URL連結和漸變影象,其他圖片類不介紹,有興趣可以訪問介紹遮罩的這篇文章,有完全展示。
不同型別屬性值使用示意(取自 MDN ):
/* 關鍵字值 */ shape-outside: none; shape-outside: margin-box; shape-outside: content-box; shape-outside: border-box; shape-outside: padding-box; /* 函式值 */ shape-outside: circle(); shape-outside: ellipse(); shape-outside: inset(10px 10px 10px 10px); shape-outside: polygon(10px 10px, 20px 20px, 30px 30px); /* <url>值 */ shape-outside: url(image.png); /* 漸變值 */ shape-outside: linear-gradient(45deg, rgba(255, 255, 255, 0) 150px, red 150px);
我們通過一個一個例項快速瞭解下各個型別屬性值的作用和表現。
1. 關鍵字屬性值
測試HTML和CSS程式碼如下:
<span class="shape"></span> <p>在CSS Shapes問世之前...</p>
.shape { float: left; width: 60px; height: 60px; padding: 10px; margin: 10px; border: 10px solid; border-radius: 50%; background-color: currentColor; background-clip: content-box; color: #cd0000; shape-outside: none;/* 或margin-box,border-box,padding-box,content-box */ }
結果佈局表現如下GIF截圖示意:
可以看到,當 shape-outside
屬性值為 none
以外的其他關鍵字的時候,就算是普通的 border-radius
圓角也能實現環繞效果。
眼見為實,您可以狠狠的點選這裡: CSS shape-outside關鍵字屬性值測試demo
2. 基本的形狀函式
指的是下面這四個基本的形狀函式:
- circle() – 圓
- ellipse() – 橢圓
- inset() – 內矩形(包括圓角矩形)
- polygon() – 多邊形
其中:
circle() – 圓
語法如下:
circle( [<shape-radius>]? [at <position>]? )
其中問號 ?
是正則表示式中的特殊字元,表示 0
和 1
,也就是說 shape-radius
(圓半徑)和 position
(圓心位置)都是可以預設的,表示。因此,下面的寫法都是合法的:
shape-outside: circle(); shape-outside: circle(50%); shape-outside: circle(at 50% 50%); shape-outside: circle(50% at 50% 50%); shape-outside: circle(50px at 50px 50px);
可以實現類似下圖的環繞效果:
和關鍵字屬性值加 border-radius
實現的圓形環繞相比, circle()
得實現相對更加靈活一些,比方說想弄一個半圓的環繞效果,可以:
shape-outside: circle(50% at 0% 50%);
結果如下圖所示:
ellipse() – 橢圓
語法如下:
ellipse( [<shape-radius>{2}]? [at <position>]? )
x軸半徑,y軸半徑,以及橢圓的圓心位置。以下都是合法的:
shape-outside: ellipse(); shape-outside: ellipse(50px 75px); shape-outside: ellipse(at 50% 50%); shape-outside: ellipse(50px 75px at 50% 50%);
x,y半徑除了具體數值,還支援 farthest-side
和 closest-side
這兩個關鍵字,顧名思義,分別表示到最長邊的長度和最短邊的長度。例如:
ellipse(farthest-side closest-side at 25% 25%)
表示在浮動元素 25% 25%
位置,以距離浮動元素最長邊的距離作為橢圓的x座標,以距離浮動元素邊緣最短的距離作為橢圓的y座標。於是,有如下的效果圖(浮動元素尺寸100*100,紅色點標記是 25% 25%
位置,可以看出橢圓的輪廓):
如果我們調換一下順序,把最短邊作為x軸,最長邊作為y軸:
ellipse(closest-side farthest-side at 25% 25%)
則最終的表現如下截圖:
仔細觀察,就不難理解 farthest-side
和 closest-side
的意思了。
inset() – 內矩形(包括圓角矩形)
語法如下:
inset( <shape-arg>{1,4} [round <border-radius>]? )
其中 shape-arg
是必須引數,可以是1~4個值。當提供所有前四個引數時,它們表示從參考框向內的頂部,右側,底部和左側偏移,也就是定義了插入的矩形的邊緣位置。 這些引數遵循邊距縮寫的語法(類似 margin
、 padding
等屬性),我們可以使用1個,2個,3個或4個值。 border-radius
表示圓角大小,可以預設。
因此,下面這些寫法都是合法的:
shape-outside: inset(10px); shape-outside: inset(10px 20px); shape-outside: inset(10px 20px 30px); shape-outside: inset(10px 20px 30px 40px); shape-outside: inset(10px 20px 30px 40px round 10px);
例如上面最後一行程式碼效果為:

控制檯檢視元素盒子可以看到:
polygon() – 多邊形
polygon()
多邊形反而是語法最好理解的:
polygon( [<fill-rule>,]? [<shape-arg> <shape-arg>]# )
fill-rule
表示填充規則,可以是 nonzero
以及 evenodd
,預設值是 nonzero
。這兩個填充規則是圖形領域必須要掌握的基礎知識,可以參見我之前的文章“ 搞懂SVG/Canvas中nonzero和evenodd填充規則 ”進行學習。
場景 polygon
用法就是:
polygon( x1 y1, x2 y2, x3 y3, ... )
就是一個一個多邊形的點座標。
shape-outside: polygon(0 0, 0 100px, 100px 200px); shape-outside: polygon(0 0, 100px 0, 0 50px, 100px 100px, 0 100px);
效果示意:

//zxx: Firefox瀏覽器內建了一個形狀編輯器,你可以在 Inspector 中通過點選多邊形視覺化生成我們需要的 polygon()
座標程式碼。
覆盤彙總
上面提到的所有shape函式都有demo可以體驗,您可以狠狠地點選這裡: CSS shape-outside基本形狀測試demo
紅色的圖形只是為了方便讓大家知道形狀是怎麼樣子的,實際開發的時候可以直接省略,或者換成其他字元或者點陣圖,如照片,風景畫,插畫等。
3. 影象類
影象類只舉URL和漸變的例子,因為這兩種型別最常用。
URL不規則圖形
已知有個國家二級保護動物鸚鵡的PNG圖形,如下:
如下CSS程式碼,就可以實現文字環繞這個鸚鵡輪廓佈局效果:
.shape { float: left; width: 200px; height: 300px; /* 文字環繞這個鸚鵡 */ shape-outside: url(./birds.png); /* 鸚鵡賦色並顯示 */ background-color: #cd0000; -webkit-mask: url(./birds.png) no-repeat; mask: url(./birds.png) no-repeat; }
實現的效果如下截圖所示:
這個效果有專門的demo頁面的,您可以狠狠的點選這裡: CSS shape-outside PNG圖片環繞demo
注意: url()
連結的圖片尺寸無法修改; url()
連結的圖片不能跨域,否則會沒有效果,因為沒有相容CORS,開啟瀏覽器控制檯,會看到類似下圖的報錯效果:
此時需要在伺服器側,或者CDN那裡配置’Access-Control-Allow-Origin’頭包含當前頁面的域名。
gradient漸變與環繞
這裡的漸變可以是線性漸變也可以是徑向漸變,以及repeat漸變。
例如繪製斜向線性漸變,CSS如下:
.shape { float: left; width: 150px; height: 120px; --gradient: linear-gradient(to right bottom, #cd0000, transparent 50%, transparent 90%, #cd0000); shape-outside: var(--gradient); background: var(--gradient); }
結果如下圖所示:
Shape佈局中有個CSS屬性名為 shape-image-threshold
,可以指定文字環繞影象的邊界透明度值。這個後面會介紹。
三、瞭解shape-margin
shape-margin
很好理解,就是文字環繞圖形時候,距離邊界的位置,這個屬性很有用。因為在Shape佈局中,文字環繞有時候是無視 margin
屬性的,想要撐開間距,多半還得用 shape-margin
屬性。
用法示意:
/* 長度值 */ shape-margin: 10px; shape-margin: 20mm; /* 百分比值 */ shape-margin: 60%;
雖然該屬性包含了 margin
,但是行為表現和CSS的 margin
屬性卻有很大的差別。首先, shape-margin
只支援1個值, margin
則1~4個;然後 shape-margin
的有效數值範圍是有限制的,從0到浮動元素的邊界(此時佈局效果表現如同普通浮動佈局)。
拿小鸚鵡案例舉例吧,不同 shape-margin
值的表現分別如下gif動圖所示:
可以看到,當 shape-margin
的值超過一定的數量的時候(超過了浮動元素的盒子的邊界),此時,看不到任何的變化了,也就是, shape-margin
只能控制不規則環繞的間距。
您可以狠狠地點選這裡: CSS shape-margin測試demo
四、瞭解shape-image-threshold
threshold這個單詞是“閾(yu)值”的意思, shape-image-threshold
指影象環繞時候的半透明閾值,預設是 0.0
,也就是影象透明度為 0
的區域邊界才能環繞。同理,如果值是 0.5
表示透明度小於0.5的區域都可以文字環繞。
這個屬性也非常實用,也很好理解,例如,我們寫一個實色到透明的傾斜線性漸變,則從0~1的透明度都覆蓋到了,此時,不同的 shape-image-threshold
值則會產生不同的佈局變化,如下GIF圖示意:
分別展示瞭如下閾值的環繞表現:
shape-image-threshold: 0.0; shape-image-threshold: 0.3; shape-image-threshold: 0.6; shape-image-threshold: 0.8;
眼見為實,您可以狠狠地點選這裡: CSS不同shape-image-threshold值測試demo
五、案例:iPhone X劉海頭
實現環繞iPhone X劉海頭的效果:
這是我2年前的iPhone X剛出來實現介紹的佈局實現,就是藉助CSS Shapes佈局,詳細實現參見這篇文章:“ 藉助CSS Shapes實現元素滾動環繞iPhone X的劉海 ”。
這裡不贅述。
六、結語
至此,CSS3 幾大佈局全部介紹完畢了,分別是Flex佈局,Grid佈局,Columns佈局,以及本文的Shapes佈局,至於CSS Regions佈局,看趨勢,瀏覽器應該放棄支援了,因此,忽略,不做介紹。
本文雖然有些篇幅,但是比Grid佈局學起來要輕鬆多了。
感謝閱讀,歡迎交流!
本文為原創文章,會經常更新知識點以及修正一些錯誤,因此轉載請保留原出處,方便溯源,避免陳舊錯誤知識的誤導,同時有更好的閱讀體驗。
本文地址: https://www.zhangxinxu.com/wordpress/?p=8453
(本篇完)