概覽
使用單個div做css繪圖,會充分利用到:
- before、after偽元素
- 使用
border-radius
、border
來控制圖形的形狀。 - 使用疊加的
box-shadow
來創建多個相同的形狀(可以有不同的大小、位置、顏色、模糊)。 - 在
background-image
、border-image
屬性上疊加使用漸變(線性、徑向、圓錐、重復),疊加的漸變可以有不同的位置、大小顏色。
這幾個屬性配合起來就可以繪制出許多物體了。
當我們充分利用好了單個div,再用多個div來繪圖就更加容易了。
常用屬性
1.border與偽元素
bofore、after偽元素會創建一些不在文檔樹中的元素,並為其添加樣式。注意區分偽元素與偽類的區別,看本小節后面的代碼示例。
border是分為top、left、right、bottom四個方向的,它們是怎么划分勢力范圍的呢?答案是平分,像這樣:
div {
position: absolute;
height: 0em;
width: 0em;
background-color: aquamarine;
border-right: 2em solid red;
border-bottom: 2em solid blue;
border-top: 2em solid green;
border-left: 2em solid yellow;
/* border-radius: 50%; */
}
給它加一個border-radius:
設置一下height、weight:
把border-bottom改成透明色transparent吧:
所以使用四個方向的border結合透明色transparent、border-radius可以輕松畫出矩形、三角形、梯形(直角、等腰、不等腰)、弧形、環形。
好,改一改畫個羽毛球吧
好吧,不怎么像,去掉border-radius再改一改就是喇叭了:
再給喇叭加一點音浪,像上面那樣利用after、before在喇叭右邊畫兩個1/4圓環吧!
使用rotate旋轉的話,元素和它的before、after偽元素是作為整體一起的
我們給喇叭的音浪加一點震動的動畫吧
這里要把音波的box-sizing設置為border-box,以免動畫中改變border-width而使元素不對齊。
音波小喇叭的完整css代碼在下面,也可以在我的codepen里面找到。
@keyframes shock {
from{
border-width: 0.1em;
}
to{
border-width: 0.6em;
}
}
div {
position: relative;
height: 2em;
width: 2em;
background-color: aquamarine;
border-right: 2em solid transparent;
border-bottom: 2em solid white;
border-top: 2em solid white;
border-left: 2em solid white;
border-radius: 0;
}
div:after,div:before{
position: absolute;
content: '';
box-sizing: border-box;
border-radius: 50%;
border-right: 0.5em solid aquamarine;
border-bottom: 0.5em solid transparent;
border-top: 0.5em solid transparent;
}
div::after{
top: -0.5em;
right:-3.5em;
height:3em;
width:3em;
animation: shock 1s linear 0s infinite alternate;
}
div:before{
top: -2em;
right:-4.5em;
height: 6em;
width: 6em;
animation: shock 1s linear 0s infinite alternate;
}
2.border-radius
border-radius用於設置元素外邊框圓角,本質上是設置4個圓角對應橢圓的長軸、短軸(共8個軸),軸長可以是百分數或者長度,負值無效。
你可以這樣統一設置8個軸為一樣的長度:
border-radius: 20px;
當然長軸和短軸是可以分開設置的,形如長軸(水平軸) / 短軸(豎軸),后面的同理:
border-radius:20px / 50%;
也可以設置2個值(分別對應左上與右下、右上與左下,其其長軸=短軸=對應值):
border-radius: 20px 60px ;
也可以分別設置4個值(分別對應左上、右上、右下、左下的圓角,其長軸=短軸=對應值):
border-radius: 20px 40px 60px 80px ;
綜上所訴,你還可以這樣寫:
border-radius: 20px 80px / 50%;
border-radius: 20px 40px 60px 80px / 50%;
border-radius: 20px 40px 60px 80px / 50% 10% 20% 30%;
3.box-shadow
box-shadow以多個逗號分隔的列表來描述一個或多個陰影,陰影和原元素的形狀相同,位置、大小、顏色、模糊可以不同。
box-shadow: h-shadow v-shadow blur spread color inset , ... ;
值 | 說明 |
---|---|
h-shadow | 必需的。水平陰影的相對位置。允許負值 |
v-shadow | 必需的。垂直陰影的相對位置。允許負值 |
blur | 可選。模糊距離 |
spread | 可選。陰影的相對大小 |
color | 可選。陰影的顏色,默認黑色 |
inset | 可選。從外層的陰影(開始時)改變陰影內側陰影 |
陰影們按列表順序渲染,后面的陰影被前面的陰影遮擋覆蓋
給出幾個栗子🌰:
外側陰影:
box-shadow: -10px -10px 10px 0px black;
內側陰影:
box-shadow: -10px -10px 10px 0px black inset;
具象的來區分外側陰影和內側陰影大概是這樣子:
來自靈魂畫手這幅畫的意思就是:
inset是將元素視為凹進去的物體,沒有inset的元素視為凸出來的物體。同一個方向的光線,會使inset的元素陰影打在元素內部,非inset的元素陰影打在元素外部。
我們利用box-shadow可以產生任意個形狀相同的陰影,而且陰影可以重疊。
box-shadow: -10px -10px 10px 0px gold inset,
-10px 10px 20px 0.5em greenyellow inset,
-20px -20px 10px 1em lightblue inset,
10em 0 0 0 lightblue,
5em -10px 10px 0px black ,
11em -10px 10px 0px black;
足夠有耐心的話,你還可以用box-shadow來畫像素畫,不過沒多大必要就是了,像下面這樣:
要注意的是box-shadow是盒子模型的陰影,border-radius會改變盒子模型的形狀,而border改變的不是盒子模型的形狀,所以即使你用border畫了個三角形,你的盒子並不是三角形,自然也得不到三角形的陰影。
4.漸變
漸變有linear-gradient、radial-gradient、conic-gradient、reapeating-linear-gradient、repeating-radial-gradient。
漸變可以在任何使用 <image>
的地方使用,例如background-image
、border-image
。
利用背景漸變可以實現條紋、格子、波點以及各種東西。
線性漸變就是沿着一條漸變線,根據給出的若干色點,構建的一系列垂直於漸變色的着色線。
所以一個線性漸變定義為:
linear-gradient(
[| to ,]? [, ]+ ) where
= [left | right] || [top | bottom]
and= [ | ]?
such as= 45deg | 0.25turn
色點列表的規則
色點是描述了顏色、位置的點,兩個色點中間的區域的顏色是介於這兩個顏色中間的漸變色。
當兩個色點處於同一位置時,就不會有漸變區域,形成鮮明的顏色分界線,這樣就可以用來畫條紋了。如果是3色以上的條紋,中間的色點可以重復一下,就能保證相鄰不同顏色的色點位置相同,像下面這樣:
background:linear-gradient(to right,violet 33%,rgb(37, 88, 228) 33%,rgb(37, 88, 228) 66%,#fb3 0%);
background-repeat: repeat-x;
background-size: 2.5em;
還有一個常用的規范:
如果某個色標的位置值比整個列表中在它之前的色標的位置值都要小, 則該色標的位置值會被設置為它前面所有色標位置值的最大值。
也就是說:#58a 33%, #fb3 0, #fb3 66%, #e45b5a 0 等價於 #58a 33%, #fb3 0, #fb3 66%, #e45b5a 66%。
除了線性漸變之外,還有徑向漸變、圓錐漸變、重復漸變,使用規則也差不多,后面會結合例子來講解,更詳細的文檔可以去MDN上查閱。
一個漸變可以有多個色點(繪圖時透明色點很有用),一個background-image
或border-image
可以疊加多個漸變,有時再配合其他屬性(如background-repeat、background-size、border-image-repeat、border-image-width等)來分區域重復繪制,就可以畫出很多東西。
那下面就讓我也來畫一只綠色的蠟筆吧!
終稿如下,同樣可以在codepen上嘗試一下。
筆頭的陰影有點違和,是用radial-gradient畫的,在只有div、:before、:after三個元素的情況下我也想不到其他什么了...
懶得碼字,解釋就交給代碼注釋了。
.div4{
position:relative;
height: 3rem;
width: 16rem;
margin:4rem;
box-sizing: border-box;
background: #237449;
background-image: linear-gradient(178deg,transparent 0,rgba(0, 0, 0, 0.4) 100%), /*筆身的漸變*/
linear-gradient(to right,transparent 6% ,rgba(41,237,133,.6) 0,
rgba(41,237,133,.6) 12%,rgba(0,0,0,0.3) 0,rgba(0,0,0,0.3) 14%, rgba(41,237,133,.6) 0, /*從左到右四個細條紋*/
rgba(41,237,133,.6) 16%,rgba(0,0,0,0.3) 0,rgba(0,0,0,0.3) 18%, rgba(41,237,133,.6) 0,
rgba(41,237,133,.6) 82%,rgba(0,0,0,0.3) 0,rgba(0,0,0,0.3) 84%, rgba(41,237,133,.6) 0,
rgba(41,237,133,.6) 86%,rgba(0,0,0,0.3) 0,rgba(0,0,0,0.3) 88%, rgba(41,237,133,.6) 0,
rgba(41,237,133,.6) 94%, transparent 0),
radial-gradient(ellipse at top, rgba(2, 37, 18, 0.9) 30%,transparent 0); /*筆身上半橢圓花紋*/
border-radius:4px;
box-shadow:2px 3px 3px 0 gray;
}
.div4::before{
position: absolute;
left:-3rem;
top:0.1rem;
content: '';
box-sizing: border-box;
height: 2.8rem;
width: 1rem;
border-radius:2px;
/*梯形的筆頭,實際看到的是border部分,所以不能在當前元素直接用backgroung-image來做漸變*/
border-right: 3rem solid #237449;
border-bottom: 1.1rem solid transparent;
border-top: 1.1rem solid transparent;
}
.div4::after{
position: absolute;
left: -3rem;
right: 0;
content: 'green';
box-sizing: border-box;
height: 3.5rem;
width: 19rem;
background-image: linear-gradient(to bottom,transparent 25%,rgba(112, 182, 142, 0.3) 40%,transparent 60%), /*整只筆中間的反光*/
radial-gradient(ellipse at 2.2rem 3rem,gray,transparent 1.8rem); /*筆頭下方的陰影*/
/*green字*/
font-family: Arial, sans-serif;
font-size: 12px;
font-weight: bold;
color: rgba(255,255,255,0.3);
text-align: right;
padding: 1.5rem 4rem 0 0 ;
}
參考文章
在不考慮成本的情況下,css是能畫出許多有簡單幾何圖形並、補、差得到的圖畫的。css是潛力十足的,或者應該說,使用css的人們是有無窮潛力的。
不過實際工程中也不需要用css來畫很復雜的圖像,直接用圖片就好了,但用文中的一些技巧也能開發出一些簡單、實用、美觀的元素效果。
下面的參考文章中還有一些有趣的東西,不妨去看看,看一看別人的神仙操作。