各種特殊的陰影
陰影有5個值:
box-shadow: 0 5px 4px -4px black;
瀏覽器創建陰影的大概過程是這樣的:
先創建一個和原有元素大小相同的塊,顏色由最後一個值指定。
接下來由前兩個值指定左偏移和上偏移。
第三個值來給定模糊的大小,你給了4,就意味着在現在塊的邊界向外向裏分別模糊4。
第四個值用來在現有的塊的基礎上調整塊的大小,給-4相當於在4個方向上都縮小4。
只有一邊有的陰影
利用上面這些創建只有一邊的陰影就很容易了。假設創建只有下面有的:
使用最後一個值將陰影縮小到正好被元素覆蓋,在使用上偏移,將其下面的部分露出來。
box-shadow: 0 5px 4px -4px black;
只有相對的兩邊有陰影
啊。。。這個只有使用兩個陰影才能實現了。。。
box-shadow: 5px 0 5px -5px black,
-5px 0 5px -5px black;
不規則陰影
面對矩形或使用圓角屬性創建出來的圖形的時候,之前的陰影可以很好的起到作用,但是當有僞元素或透明背景等會使元素外形不規則的情形時,之前的陰影就不那麼好用了。
這裏有一個新的玩意,叫Filter Effects specification。
這個玩意是從SVG裏借鑑來的,但是使用上不需要SVG的知識,簡單的函數就好,比如blur()、grayscale()、drop-shadow()。
這裏我們要用到的就是drop-shadow(),接收的參數和box-shadow差不多,沒有改變大小的那個。
#irregularShadow{
height:100px;
color: deeppink;
border: 10px dashed;
text-shadow: .1em .2em yellow;
-webkit-filter: drop-shadow(.1em .1em .5em rgba(255,255,0,1));
filter: drop-shadow(.05em .05em .1em gray);
}
這個其實是對這個元素中所有不透明的部分應用了陰影,這時如果你使用text-shadow,就會多一層陰影哦。
這個陰影非常靈活,基本就意味着這個元素(包括其僞元素)在光照下哪裏會有陰影,這裏就會在哪裏生成陰影。
色彩渲染圖片濾鏡
就是在圖片上添加濾鏡的效果咯。
以前我們使用圖片編輯軟件來編輯出各種不同效果的圖片來達成目的,但這樣不僅增加了HTTP請求,也使得維護變得更加困難。
還有一種是通過在圖片上面覆蓋一層透明的覆蓋層,模擬給圖片加上濾鏡的效果,這樣確實可以模擬有限的效果,但是這樣做並不能模擬所有的效果。
使用CSS的Filter和Blending可以很好的達到效果。
使用JS的canvas可以將圖片轉換到畫布中,這樣可以在畫布中獲得對所有點的顏色的完全控制,如果你想編寫自己的濾鏡的算法的話,那這個非常適合,但是如果使用CSS中的Filter和Blending就可以達到的效果,使用這個方法無論是從速度,開銷還是我們自己的工作量來說都是不划算的。
Filter
我們可以合併多個filter來達成我們的效果。而且,這個屬性還可以使用動畫。可以做出炫酷的效果哦。
#filter{
width:200px;
transition: 1s filter, 1s -webkit-filter;
-webkit-filter: sepia() saturate(4) hue-rotate(295deg);
filter: sepia() saturate(4) hue-rotate(295deg);
}
#filter:hover,
#filter:focus {
-webkit-filter: none;
filter: none;
}
Blending
這個就像是PS中的混合,有時filter並不能完全達到我們想要的效果時我們就可以使用這個。
這個東西在控制頂層的圖層如何與底層的圖層混合,我們將背景色放在背景圖片下,再使用混合來混合這兩個圖層。
#blend{
width:200px;
height:200px;
background-size: cover;
background-position: center;
background-color: hsl(335, 100%, 50%);
background-blend-mode: luminosity;
transition: .5s background-color;
background-image: url("../img/tiger.jpg");
}
#blend:hover {
background-color: transparent;
}
毛玻璃效果
在背景很複雜的情況下,我們需要呈現文字的時候就需要在文字下面一個半透明的底。
但有時半透明的底也還是不夠,我們想參照macOS那樣將背景高斯模糊一下。
我們當然不能在本元素上進行高斯模糊,這樣內容也會被模糊,那麼我們就使用僞元素吧。
對於背景元素,我們就簡單的設置下背景圖片,這裏有一點是要注意的,首先一定要創建一個不爲auto且不爲負的z軸放置上下文,這個一會兒解釋。
#blur {
position: relative;
padding:20px;
height:400px;
background: url("../img/tiger.jpg") 0/cover fixed;
z-index: 1;
}
裏面放置文字內容的元素放一個半透明的背景,僞元素模糊過的背景將放在這個半透明背景的下面。這裏的z軸放置上下文一定要爲默認值auto。
#blur .content{
position: relative;
max-width:400px;
margin:0 auto;
border-radius: 20px;
padding:20px;
background: hsla(0,0%,100%,.3);
overflow: hidden;
font: normal 22px/40px serif;
}
僞元素:
#blur .content:before{
content: '';
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
-webkit-filter: blur(20px);
filter: blur(20px);
background: url("../img/tiger.jpg") 0/cover fixed;
z-index: -1;
margin: -30px;
}
僞元素這裏要說的比較多。
首先,我們這裏是放一個僞裝的圖片用來模糊,所以這張圖片顯示的位置一定要保證和大背景位置相同纔行,這裏使用的是fixed的背景位置,如果你不喜歡使用別的也沒問題,能保證位置一致就好。
其次,之前創建的z軸上下文在這裏就用到了,我們想要的效果是將被模糊的僞裝圖片放在僞元素的父元素(在這裏就是其生成元素)的透明背景的下面,但是要放在其父元素的父元素(真正背景所在元素)的背景的上面。
z-index: -1會使這個僞元素放到其z軸上下文的背景前,內容下面。在這裏#blur創建了z軸上下文,.content因爲還是默認值auto,所以沒有創建。那麼這個僞元素就理所當然的放在了我們想放的地方。
最後,因爲模糊在邊緣部分是有漸變的,模糊的半徑會越來越小直至爲0,我們不想要這樣的效果,我們想要的是清晰的邊界。那麼margin: -30px就起到了這個作用,再配合其父元素的overflow:hidden,我們就將這部分漸變隱藏起來了。
折角效果
以前的實現是添加兩個僞元素一個用來遮蓋元素的一角,一個用來模仿折過來的角。
這樣的解決方法不夠靈活,有更靈活的嘛?
45度時的方案
首先利用線性漸變創建一個切角的元素。
#folded-corner{
width:200px;
height:200px;
background: #58a; /* Fallback */
background:
linear-gradient(-135deg, transparent 2em, #58a 0);
}
然後我們再用線性漸變創建一個小小的矩形背景,這個矩形的對角線正好與切角的那條邊重合,矩形的左下半部分作爲折過去的角,右上半部分保持透明就好。
#folded-corner{
width:200px;
height:200px;
background: #58a; /* Fallback */
background:
linear-gradient(-135deg,transparent 50%, rgba(0,0,0,.4) 0) no-repeat 100% 0 / 2em 2em,
linear-gradient(-135deg, transparent 1.5em, #58a 0);
}
其他角度
其他角度可就不像45度這麼簡單咯。。。
首先你得計算好。。。其次這回折過來的角其實應該是反着的,用一個矩形小背景的辦法行不通了,得用僞元素了。
我們首先來搞定形狀的問題:
我們需要根據切角的角度和大小來計算僞元素的長寬。這裏使用scss將會有很大的優勢。
@mixin folded-corner($background, $size, $angle: 30deg) {
$x: $size / sin($angle);
$y: $size / cos($angle);
&::before {
content: '';
position: absolute;
top: 0; right: 0;
width: $x; height: $y;
background: linear-gradient(to left bottom,
transparent 50%, rgba(0,0,0,.4) 0)
100% 0 no-repeat;
}
}
這時乍一看是完成了,但你找個真正的紙折一下就會發現,其實並不對。。。
僞元素還需要旋轉一定的角度纔行。
最後就是這樣咯:
@mixin folded-corner($background, $size, $angle: 30deg) {
position: relative;
background: $background; /* Fallback */
background:
linear-gradient($angle - 180deg,
transparent $size, $background 0);
border-radius: .5em;
$x: $size / sin($angle);
$y: $size / cos($angle);
&::before {
content: '';
position: absolute;
top: 0; right: 0;
background: linear-gradient(to left bottom,
transparent 50%, rgba(0,0,0,.2) 0,
rgba(0,0,0,.4)) 100% 0 no-repeat;
width: $y; height: $x;
transform: translateY($y - $x)
rotate(2*$angle - 90deg);
transform-origin: bottom right;
border-bottom-left-radius: inherit;
box-shadow: -.2em .2em .3em -.1em rgba(0,0,0,.2);
}
}