1.寫在前面
在CSS3中,可以使用box-shadow屬性來建立陰影效果來給二維平面增加深度效果,這個屬性在前端開發中使用的非常多,例如segmentfault的首頁就是使用了box-shadow屬性來增加深度效果,今天我們就一起來看看這個屬性。
2.box-shadow的基本語法
box-shadow: [x-offset y-offset blur-radius spread-radius color,inset ]+
其中,+在正規表示式中表示一次或者多次的意思,也就是說box-shadow可以支援同時設定多個陰影。
首先我們來看下基本引數的含義:
- none:預設值,設定後表示沒有陰影效果;
- inset:該值後表示內陰影,如果不設定,則預設表示外陰影;
- x-offset/y-offset:分別表示陰影在水平方向和垂直方向上的偏移量,支援正值和負值的設定,正值表示向右下方偏移,負值表示向左上方偏移;
- blur-radius:陰影的模糊距離,只能設定0或者正值,值越大則表明陰影的邊緣越模糊;
- spread-radius:陰影的擴充套件半徑(可省略,預設為0),支援正值和負值,正值表示陰影擴充套件,負值表示陰影縮小。這個屬性在box-shadow中是相對比較難理解的一個屬性,在文章後面會詳細講到這個屬性的意義;
- color:陰影的顏色,如果不設定,則會使用瀏覽器預設的顏色 。
在對box-shadow的每一個引數進行說明後,可能大家還是一點概念沒有,不知道該怎麼用。那麼首先讓我們來看一個大家經常使用box-shadow的方法:指定三個長度值和一個顏色值來實現陰影效果,如下所示:
box-shadow: 2px 3px 4px rgba(0,0,0,.5);
複製程式碼
在瀏覽器中的效果如下:
最終,我們實現實現了左側和底部邊框陰影的效果,但是大家有沒有想過box-shadow繪製陰影的原理是什麼嗎?繪製原理請看下一節。
3.box-shadow繪製陰影的原理
下圖以圖形化的形式說明了陰影是如何繪製的,以下面的程式碼為例:
.box{
width: 200px;
height: 200px;
background-color: #fb3;
box-shadow: 2px 3px 4px rgba(0,0,0,.5);
}
複製程式碼
那麼繪製陰影的步驟會以下面的步驟進行:
(1)以該元素相同的尺寸和位置,畫一個rgb(0,0,0,.5)
的矩形,如下圖1所示;
(2)把圖1的矩形向右移2px,向下移3px,如下圖2所示;
(3)使用高斯模糊演算法(或者類似的演算法)將它進行4px的模糊處理,本質上表示在陰影邊緣發生陰影色和純透明色之間的顏色過渡長度近似於模糊半徑的兩倍,如下圖3所示;
(4)模糊後矩形與原始元素的交集部分會被切除掉,因此,最後看到的陰影效果如下圖4所示,也就是我們最終看到的陰影效果。
準確的說,我們將在頂部看到1px的陰影(4px-3px)、在左側看到2px(4px-2px)、在右側看到6px(4px+2px)、在底部看到7px(4px+3px)。在實踐中,投影看起來會比這些值稍小,因為投影的顏色在邊緣處的過渡不是線性的。
說完了box-shadow的繪製原理,下面將結合例子對box-shadow的每一個屬性做詳細的說明
4.box-shadow屬性詳解
4.1 x-offset
x-offset用來宣告陰影在水平方向上的偏移量。如果為正數,則陰影在元素的右側;如果為負數,則陰影在元素的左側。如下程式碼所示:
box-shadow: 10px 0 5px 0 rgba(0,0,0,.5);
複製程式碼
box-shadow: -10px 0 5px 0 rgba(0,0,0,.5);
複製程式碼
在瀏覽器中的效果如下所示:
第一幅圖中,設定x-offset為10px,在右側產生了陰影;第二幅圖中,設定x-offset為-10px,則在左側產生了陰影。
4.2 y-offset
y-offset用來宣告陰影在垂直方向上的偏移量。如果為正數,則陰影在元素的方側;如果為負數,則陰影在元素的上方。如下程式碼所示:
box-shadow: 0 10px 5px 0 rgba(0,0,0,.5);
複製程式碼
box-shadow: 0 -10px 5px 0 rgba(0,0,0,.5);
複製程式碼
在瀏覽器中的效果如下所示:
第一幅圖中,設定y-offset為10px,在底部產生了陰影;第二幅圖中,設定y-offset為-10px,則在頂部產生了陰影。
4.3 blur-radius
blur-radius 表示陰影的模糊半徑,值越大,則陰影越模糊,該屬性不支援負值。如下程式碼所示:
box-shadow: 0 0 0 0 rgba(0,0,0,.5);
複製程式碼
box-shadow: 0 0 20px 0 rgba(0,0,0,.5);
複製程式碼
box-shadow: 0 0 50px 0 rgba(0,0,0,.5);
複製程式碼
第一幅圖中,設定x-offset、y-offset、blur-radius為0px,即不位移,不模糊,則沒有任何陰影的效果;第二幅圖中,設定blur-radius為20px,第三幅圖中社會組blur-radius為50px,可以看到,blur-radius值越大,則陰影越模糊。
4.4 spread-radius
這個屬性是box-sizing中最難理解的。我們先來看以下的例子:
box-shadow: 0px 0px 0px 20px deeppink;
複製程式碼
可以看到20px的邊框效果:
然後,我們動態更改blur-radius,可以看到模糊的是邊框部分,也是顏色為deeppink
的邊框。
其實,我們可以將spread-radius理解成元素blur的“margin”,為正的時候漸變向外擴張、為負的時候漸變向內收縮。
4.5 color
color表示陰影的顏色,支援css中任意的顏色。如下程式碼所示:
.box1{
box-shadow: 0 0 50px 0 darkgreen;
}
.box2{
box-shadow: 0 0 50px 0 deeppink;
}
.box3{
box-shadow: 0 0 50px 0 blue;
}
複製程式碼
在瀏覽器中的效果如下所示:
三幅圖中,設定陰影的顏色各不相同,則會產生相應的陰影效果。
4.6 inset
陰影預設是外陰影,可以使用inset
關鍵字指定陰影為外陰影。如下程式碼所示:
.box1{
box-shadow: 0 0 50px 0 darkgreen inset;
}
.box2{
box-shadow: 0 0 50px 0 deeppink inset;
}
.box3{
box-shadow: 0 0 50px 0 blue inset;
}
複製程式碼
在瀏覽器中的效果如下所示:
三幅圖中,設定陰影為內陰影,最終陰影是在元素內部生成的。
5.box-shadow屬性之案例
5.1 單側投影
程式碼如下:
box-shadow: 0 5px 4px -4px blue;
複製程式碼
這個例子比較好理解,在瀏覽器中的效果如下:
5.2 雙側投影
當我們只想設定在元素的兩條邊上的陰影時,好像比較麻煩。因為擴張半徑在四個方向上的作用是均等的(也就是說,我們無法指定投影在水平方向上的放大,在垂直方向上縮小),唯一的辦法是用兩塊投影(每邊各一塊)來達到目的。基本上就是將單側投影中的技巧運用兩次,以如下所示:
box-shadow: 5px 0 5px -5px blue,
-5px 0 5px -5px blue;
複製程式碼
在瀏覽器中的效果如下:
5.3 模擬邊框
使用box-shadow屬性可以模擬border的效果,以如下所示:
<div class="box box6"></div>
<div class="box box7"></div>
複製程式碼
.box{
display: inline-block;
width: 200px;
height: 200px;
background-color: #fb3;
}
.box6 {
box-shadow: 0px 0px 0px 40px deeppink;
}
.box7 {
box-shadow: 20px 20px 0px 20px blue,
-20px -20px 0px 20px deeppink,
0px 0px 0px 40px darkgreen;
}
複製程式碼
在瀏覽器中的效果如下:
我們可以看到利用box-shadow屬性模擬了border的效果,但是與border不同的是,使用box-shadow建立的邊框效果並不會影響元素的尺寸。我們指定了元素的尺寸為200*200
,然後利用box-shadow模擬出border的效果,但是在瀏覽器中可以看到元素的尺寸依然是200*200
,如下圖所示:
5.4 模擬靠近和遠離使用者的效果
利用box-shadow和動畫屬性,可以模擬靠近和遠離使用者的效果,以如下所示:
<div class="box popup"></div>
複製程式碼
.box{
display: inline-block;
width: 200px;
height: 200px;
background-color: #fb3;
}
.popup {
transform: scale(1);
box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.3);
transition: box-shadow 0.5s, transform 0.5s;
}
.popup:hover {
transform: scale(1.3);
box-shadow: 0px 0px 50px 10px rgba(0, 0, 0, 0.3);
transition: box-shadow 0.5s, transform 0.5s;
}
複製程式碼
在瀏覽器中的效果如下:
5.5 模擬浮動效果
配合使用box-shadow和動畫屬性,可以模擬靠近和遠離使用者的效果,以如下所示:
<div class="box easy"></div>
複製程式碼
.easy {
position: relative;
transform: translateY(0);
transition: transform 1s;
}
.easy:after {
content: "";
display: block;
position: absolute;
bottom: -30px;
left: 50%;
height: 8px;
width: 100%;
box-shadow: 0px 0px 20px 0px deeppink;
border-radius: 50%;
background-color: deeppink;
transform: translate(-50%, 0);
transition: transform 1s;
}
/*方塊向上移動*/
.easy:hover {
transform: translateY(-40px);
transition: transform 1s;
}
/*底部陰影形狀變化*/
.easy:hover:after {
transform: translate(-50%, 40px) scale(0.75);
transition: transform 1s;
}
複製程式碼
在瀏覽器中的效果如下所示:
5.6 模擬書頁效果
配合使用box-shadow和動畫屬性(旋轉)還可以實現下面的紙張效果:左下和右下方的陰影比中間的陰影要突出。
我們分步看看是如何建立上面的書頁效果的,有如下公共樣式:
有如下公共樣式:
<div class="box page"></div>
複製程式碼
.box{
display: inline-block;
width: 200px;
height: 200px;
background-color: #fb3;
}
複製程式碼
具體步驟如下:
(1)利用普通div和偽元素,建立陰影效果的驅殼,其中為了演示方便,新增了border屬性,最終會去掉border。
.page{
position: relative;
}
.page:before, .page:after{
position: absolute;
content: "";
bottom: 15px;
left: 10px;
width: 50%;
top: 80%;
border: 1px solid #cd0000;
}
.page:after {
right: 10px;
left: auto;
}
複製程式碼
在瀏覽器中的效果如下所示:
(2)新增偽元素的陰影效果,以及旋轉一定的角度,修改為如下程式碼:
.page{
position: relative;
}
.page:before, .page:after{
position: absolute;
content: "";
bottom: 15px;
left: 10px;
width: 50%;
top: 80%;
border: 1px solid #cd0000;
box-shadow: 0 15px 10px #777;/*新增,陰影*/
transform: rotate(-3deg);/*新增,旋轉*/
}
.page:after {
transform: rotate(3deg);/*新增,旋轉*/
right: 10px;
left: auto;
}
複製程式碼
在瀏覽器中的效果如下所示:
(3)使用z-index:-1
,將偽元素隱藏掉,並且去掉為了說明效果的border屬性,最終的效果就是我們想要的書頁效果了。
.page{
position: relative;
}
.page:before, .page:after{
z-index: -1;/*新增*/
position: absolute;
content: "";
bottom: 15px;
left: 10px;
width: 50%;
top: 80%;
/*border: 1px solid #cd0000;*/
box-shadow: 0 15px 10px #777;
transform: rotate(-3deg);
}
.page:after {
transform: rotate(3deg);
right: 10px;
left: auto;
}
複製程式碼
在瀏覽器中的效果如下所示:
6.寫在最後
box-shadow在css中的屬性相對來說比較少,但是剛開始接觸的時候比較抽象,特別是擴充套件半徑,我剛開始接觸的時候也是很難理解,但是根據網上一些部落格作者的例子,然後自己動手寫例子,觀察效果,其實理解起來還是比較容易的。如果想更深入的瞭解box-shadow的MDN和W3C,還有一個比較好的線上檢視box-shadow效果的css3gen。
感謝閱讀。
7.參考連結
遇見了,不妨關注下我的微信公眾號「前端Talkking」