關(guān)于 CSS 陰影益老,之前已經(jīng)有寫過一篇,[box-shadow 與 filter:drop-shadow 詳解及奇技淫巧],介紹了一些關(guān)于
box-shadow
的用法烙样。最近一個新的項目,[CSS-Inspiration]蕊肥,挖掘了其他很多有關(guān) CSS 陰影的點(diǎn)子谒获,是之前的文章沒有覆蓋到的新內(nèi)容,而且有一些很有意思壁却,遂打算再起一篇批狱。
-
本文的題目是 CSS 陰影技巧與細(xì)節(jié)。CSS 陰影展东,卻不一定是
box-shadow
與filter:drop-shadow
赔硫,為啥?因為使用其他屬性也可以模擬陰影盐肃,而且是各種各樣的陰影爪膊。下面且聽我娓娓道來~
單側(cè)投影
- 先說單側(cè)投影,關(guān)于
box-shadow
砸王,大部分時候推盛,我們使用它都是用來生成一個兩側(cè)的投影,或者一個四側(cè)的投影谦铃。如下:
OK耘成,那如果要生成一個單側(cè)的投影呢?
我們來看看 box-shadow 的用法定義:
`{`
`box-shadow: ``none` `| [``inset``? && [ <offset-x> <offset-y> <blur-radius>? <spread-radius>? <color>? ] ]#`
`}`
以
box-shadow: 1px 2px 3px 4px #333
為例荷辕,4 個數(shù)值的含義分別是凿跳,x 方向偏移值、y 方向偏移值 疮方、模糊半徑控嗜、擴(kuò)張半徑。這里有一個小技巧骡显,擴(kuò)張半徑可以為負(fù)值疆栏。
繼續(xù)曾掂,如果陰影的模糊半徑,與負(fù)的擴(kuò)張半徑一致壁顶,那么我們將看不到任何陰影珠洗,因為生成的陰影將被包含在原來的元素之下,除非給它設(shè)定一個方向的偏移量若专。所以這個時候许蓖,我們給定一個方向的偏移值,即可實現(xiàn)單側(cè)投影:
- CodePen Demo -- css單側(cè)投影
投影背景 / 背景動畫
接著上面的說调衰。
很明顯膊爪,
0 = -0
,所以當(dāng)box-shadow
的模糊半徑和擴(kuò)張半徑都為 0 的時候嚎莉,我們也可以得到一個和元素大小一樣的陰影米酬,只不過被元素本身遮擋住了,我們嘗試將其偏移出來趋箩。
CSS代碼如下:
`div {`
`width``: ``80px``;`
`height``: ``80px``;`
`border``: ``1px` `solid` `#333``;`
`box-sizing: border-box;`
`box-shadow: ``80px` `80px` `0` `0` `#000``;`
`}`
- 得到如下結(jié)果:
有什么用呢赃额?好像沒什么意義啊。
額叫确,確實好像沒什么用跳芳。不過我們注意到,
box-shadow
是可以設(shè)置多層的竹勉,也就是多層陰影筛严,而且可以進(jìn)行過渡變換動畫(補(bǔ)間動畫)。但是background-image: linear-gradient()
饶米,也就是漸變背景是不能進(jìn)行補(bǔ)間動畫的。這又扯到哪里去了车胡。好我們回來檬输,利用上面的特性,我們可以利用
box-shadow
實現(xiàn)原本只能利用漸變才能實現(xiàn)的背景圖:
用 box-shadow
匈棘,實現(xiàn)它的 CSS 代碼如下(可以更簡化):
`.shadow {`
`position``: ``relative``;`
`width``: ``250px``;`
`height``: ``250px``;`
`}`
`.shadow::before {`
`content``: ``""``;`
`position``: ``absolute``;`
`width``: ``50px``;`
`height``: ``50px``;`
`top``: ``-50px``;`
`left``: ``-50px``;`
`box-shadow:`
`50px` `50px` `#000``, ``150px` `50px` `#000``, ``250px` `50px` `#000``,`
`50px` `100px` `#000``, ``150px` `100px` `#000``, ``250px` `100px` `#000``,`
`50px` `150px` `#000``, ``150px` `150px` `#000``, ``250px` `150px` `#000``,`
`50px` `200px` `#000``, ``150px` `200px` `#000``, ``250px` `200px` `#000``,`
`50px` `250px` `#000``, ``150px` `250px` `#000``, ``250px` `250px` `#000``;`
`}`
- 用漸變來實現(xiàn)的話丧慈,只需要這樣:
`.gradient {`
`width``: ``250px``;`
`height``: ``250px``;`
`background-image``: linear-gradient(``90``deg, ``#000` `0%``, ``#000` `50%``, ``#fff` `50%``, ``#fff` `100%``);`
`background-``size``: ``100px` `100px``;`
`}`
- 為什么選擇更為復(fù)雜的
box-shadow
呢?因為它可以進(jìn)行補(bǔ)間動畫主卫,像這樣逃默,這是使用漸變做不到的:
CodePen Demo -- box-shadow實現(xiàn)背景動畫
- 當(dāng)然,這只是個示例 Demo簇搅,運(yùn)用點(diǎn)想象力還有很多有意思的效果完域,再貼一個:
CodePen Demo -- CSS Checker Illusion( By David Khourshid
嗯,很有意思瘩将,就是實際用途可能不大吟税。
立體投影
好凹耙,我們繼續(xù)。下一個主題是立體投影肠仪。
這個說法很奇怪肖抱,陰影的出現(xiàn),本就是為了讓原本的元素看起來更加的立體异旧,那這里所謂的立體投影意述,是個怎么立體法?
這里所謂的立體投影吮蛹,并不一定是使用了
box-shadow
荤崇、text-shadow
或者drop-shadow
,而是我們使用其他元素或者屬性模擬元素的陰影匹涮。而這樣做的目的天试,是為了能夠突破box-shadow
這類元素的一些定位局限。讓陰影的位置然低、大小喜每、模糊度可以更加的靈活。OK雳攘,讓我們來看看带兜,這樣一個元素,我們希望通過自定義陰影的位置吨灭,讓它更加立體:
- 上圖 div 只是帶了一個非常淺的
bos-shadow
刚照,看上去和立體沒什么關(guān)系,接下來喧兄,我們通過 div 的偽元素无畔,給它生成一個和原圖邊角形狀類似的圖形,再通過 transform 位移一下吠冤,可能是這樣:
- OK浑彰,最后對這個用偽元素生成的元素進(jìn)行一些虛化效果(filter或者box-shadow都可以),就可以實現(xiàn)一個邊角看起來像被撕開的立體效果:
- 代碼非常簡單拯辙,偽 CSS 代碼示意如下:
`div {`
`position``: ``relative``;`
`width``: ``600px``;`
`height``: ``100px``;`
`background``: hsl(``48``, ``100%``, ``50%``);`
`border-radius: ``20px``;`
`}`
`div::before {`
`content``: ``""``;`
`position``: ``absolute``;`
`top``: ``50%``;`
`left``: ``5%``;`
`right``: ``5%``;`
`bottom``: ``0``;`
`border-radius: ``10px``;`
`background``: hsl(``48``, ``100%``, ``20%``);`
`transform: translate(``0``, ``-15%``) rotate(``-4``deg);`
`transform-origin: ``center` `center``;`
`box-shadow: ``0` `0` `20px` `15px` `hsl(``48``, ``100%``, ``20%``);`
`}`
所以總結(jié)一下:
立體投影的關(guān)鍵點(diǎn)在于利于偽元素生成一個大小與父元素相近的元素郭变,然后對其進(jìn)行 rotate 以及定位到合適位置,再賦于陰影操作
顏色的運(yùn)用也很重要涯保,陰影的顏色通常比本身顏色要更深诉濒,這里使用 hsl 表示顏色更容易操作,l 控制顏色的明暗度
還有其他很多場景:
[CodePen Demo -- 立體投影]
文字立體投影 / 文字長陰影
上面的立體效果在文字上就完全不適用了夕春,所以對待文字的立體陰影效果未荒,還需要另辟蹊徑。
正常而言及志,我們使用 text-shadow 來生成文字陰影茄猫,像這樣:
`<div> Txt Shadow</div>`
`-----`
`div {`
`text-shadow``: ``6px` `6px` `3px` `hsla(``14``, ``100%``, ``30%``, ``1``);`
`}`
嗯狈蚤,挺好的,就是不夠立體划纽。那么要做到立體文字陰影脆侮,最常見的方法就是使用多層文字陰影疊加。
Tips:和
box-shadow
一樣勇劣,text-shadow
是可以疊加多層的靖避!但是對于單個元素而言,drop-shadow
的話就只能是一層比默。好吧醋奠,手寫真的太慢了榛臼,還容易出錯,所以這里我們需要借助一下 SASS/LESS 幫忙窜司,寫一個生成 50 層陰影的
function
就好沛善,我們每向右和向下偏移 1px,生成一層 text-shadow:
`@function makeLongShadow($color) {`
`$val: ``0px` `0px` `$color;`
`@for $i from ``1` `through ``50` `{`
`$val: #{$val}, #{$i}px #{$i}px #{$color};`
`}`
`@return $val;`
`}`
`div {`
`text-shadow``: makeLongShadow(hsl(``14``, ``100%``, ``30%``));`
`}`
- 上面的 SCSS 代碼塞祈。經(jīng)過編譯后金刁,就會生成如下 CSS:
`div {`
`text-shadow``: ``0px` `0px` `#992400``, ``1px` `1px` `#992400``, ``2px` `2px` `#992400``, ``3px` `3px` `#992400``, ``4px` `4px` `#992400``, ``5px` `5px` `#992400``, ``6px` `6px` `#992400``, ``7px` `7px` `#992400``, ``8px` `8px` `#992400``, ``9px` `9px` `#992400``, ``10px` `10px` `#992400``, ``11px` `11px` `#992400``, ``12px` `12px` `#992400``, ``13px` `13px` `#992400``, ``14px` `14px` `#992400``, ``15px` `15px` `#992400``, ``16px` `16px` `#992400``, ``17px` `17px` `#992400``, ``18px` `18px` `#992400``, ``19px` `19px` `#992400``, ``20px` `20px` `#992400``, ``21px` `21px` `#992400``, ``22px` `22px` `#992400``, ``23px` `23px` `#992400``, ``24px` `24px` `#992400``, ``25px` `25px` `#992400``, ``26px` `26px` `#992400``, ``27px` `27px` `#992400``, ``28px` `28px` `#992400``, ``29px` `29px` `#992400``, ``30px` `30px` `#992400``, ``31px` `31px` `#992400``, ``32px` `32px` `#992400``, ``33px` `33px` `#992400``, ``34px` `34px` `#992400``, ``35px` `35px` `#992400``, ``36px` `36px` `#992400``, ``37px` `37px` `#992400``, ``38px` `38px` `#992400``, ``39px` `39px` `#992400``, ``40px` `40px` `#992400``, ``41px` `41px` `#992400``, ``42px` `42px` `#992400``, ``43px` `43px` `#992400``, ``44px` `44px` `#992400``, ``45px` `45px` `#992400``, ``46px` `46px` `#992400``, ``47px` `47px` `#992400``, ``48px` `48px` `#992400``, ``49px` `49px` `#992400``, ``50px` `50px` `#992400``;`
`}`
- 看看效果:
額,很不錯议薪,很立體尤蛮。但是,就是丑斯议,而且說不上來的奇怪抵屿。
問題出在哪里呢,陰影其實是存在明暗度和透明度的變化的捅位,所以,對于漸進(jìn)的每一層文字陰影搂抒,明暗度和透明度應(yīng)該都是不斷變化的艇搀。這個需求,SASS 可以很好的實現(xiàn)求晶,下面是兩個 SASS 顏色函數(shù):
fade-out
改變顏色的透明度焰雕,讓顏色更加透明desaturate
改變顏色的飽和度值,讓顏色更少的飽和
關(guān)于 SASS 顏色函數(shù)芳杏,可以看看這里:Sass基礎(chǔ)—顏色函數(shù)
我們使用上面兩個 SASS 顏色函數(shù)修改一下我們的 CSS 代碼矩屁,主要是修改上面的 makeLongShadow
function 函數(shù):
`@function makelongrightshadow($color) {`
`$val: ``0px` `0px` `$color;`
`@for $i from ``1` `through ``50` `{`
`$``color``: fade-out(desaturate($color, ``1%``), .``02``);`
`$val: #{$val}, #{$i}px #{$i}px #{$color};`
`}`
`@return $val;`
`}`
- 好辟宗,看看最終效果:
- 嗯,大功告成吝秕,這次順眼了很多~
- 當(dāng)然泊脐,使用 CSS 生成立體文字陰影的方法還有很多,下面再貼出一例烁峭,使用了透明色疊加底色的多重線性漸變實現(xiàn)的文字立體陰影容客,感興趣的同學(xué)可以去看看具體實現(xiàn):
長投影
- 上面提到了通過多層陰影疊加實現(xiàn)文字的立體陰影。運(yùn)用在 div 這些容器上也是可以的约郁。當(dāng)然這里還有一種挺有意思的方法缩挑。假設(shè)我們,有一個矩形元素鬓梅,希望給他添加一個長投影供置,像下面這樣:
- 要生成這種長投影,剛剛說的疊加多層陰影可以绽快,再就是借助元素的兩個偽元素芥丧,其實上面的圖是這樣的:
- 關(guān)鍵點(diǎn)在于,我們通過對兩個偽元素的
transform: skew()
變換以及從實色到透明色的背景色變化谎僻,實現(xiàn)了長投影的效果:
彩色投影
通常而言娄柳,我們生成陰影的方式大多是
box-shadow
、filter: drop-shadow()
艘绍、text-shadow
赤拒。但是帘不,使用它們生成的陰影通常只能是單色或者同色系的亭珍。額航夺,當(dāng)然不行蕉朵。
這個真不行,但是通過巧妙的利用
filter: blur
模糊濾鏡阳掐,我們可以假裝生成漸變色或者說是顏色豐富的陰影效果始衅。假設(shè)我們有下述這樣一張頭像圖片:
- 下面就利用濾鏡,給它添加一層與原圖顏色相仿的陰影效果缭保,核心 CSS 代碼如下:
`.avator {`
`position``: ``relative``;`
`background``: ``url``($img) ``no-repeat` `center` `center``;`
`background-``size``: ``100%` `100%``;`
`&::after {`
`content``: ``""``;`
`position``: ``absolute``;`
`top``: ``10%``;`
`width``: ``100%``;`
`height``: ``100%``;`
`background``: inherit;`
`background-``size``: ``100%` `100%``;`
`filter: blur(``10px``) brightness(``80%``) opacity(.``8``);`
`z-index``: ``-1``;`
`}`
`}`
- 看看效果:
其簡單的原理就是汛闸,利用偽元素,生成一個與原圖一樣大小的新圖疊加在原圖之下艺骂,然后利用濾鏡模糊
filter: blur()
配合其他的亮度/對比度诸老,透明度等濾鏡,制作出一個虛幻的影子钳恕,偽裝成原圖的陰影效果别伏。嗯蹄衷,最重要的就是這一句
filter: blur(10px) brightness(80%) opacity(.8);
。
CodePen Demo -- filter create shadow
使用 box-shadow 實現(xiàn)的燈光效果
- 好厘肮,上文主要是一些實現(xiàn)各種陰影的方法愧口,接下來是效果篇。先來看看使用
box-shadow
實現(xiàn)的一些燈光效果轴脐。
box-shadow 實現(xiàn)霓虹氖燈文字效果
- 這個效果也叫 Neon调卑,Codepen 上有很多類似的效果,本質(zhì)上都是大范圍的
box-shadow
過渡效果與白色文字的疊加:
CodePen Demo -- box-shadow實現(xiàn)霓虹氖燈文字效果
使用box-shadow實現(xiàn)陰影燈光show
和上面的效果類似大咱,本質(zhì)上都是多重陰影的過渡效果恬涧,或許再來點(diǎn) 3D 效果?
合理搭配碴巾,效果更佳:
CodePen Demo -- 使用box-shadow實現(xiàn)陰影燈光show
使用 drop-shadow | box-shadow 實現(xiàn)單標(biāo)簽抖音 LOGO
嗯哼溯捆,既然標(biāo)題叫你所不知道的 CSS 陰影技巧與細(xì)節(jié),那么本文也應(yīng)該有一點(diǎn)奇技淫巧厦瓢。
先來看這個提揍,單個標(biāo)簽實現(xiàn)仿抖音 LOGO,當(dāng)然由于限定在一個元素煮仇,所以細(xì)節(jié)方面還是有很多瑕疵劳跃。
想著仿的緣由是某天刷抖音的時候看見這個 LOGO 的一時興起,CSS 寫多了浙垫,看見什么東西都會條件反射的想這個能不能用 CSS 實現(xiàn)刨仑。
- 我們先來看看抖音的 LOGO:
其實很簡單,主體其實是由3個顏色不同類似 J 的形狀組成夹姥。而單獨(dú)拎出一個杉武,又可以把它分成四分之三圓、|以及?組成辙售。
正好轻抱,一個元素加上它的兩個偽元素,剛好可以湊成這三個形狀旦部,我們試著實現(xiàn)以下祈搜,簡單 CSS 代碼如下:
`<div></div>`
`---`
`div {`
`position``: ``relative``;`
`width``: ``37px``;`
`height``: ``218px``;`
`background``: ``#fff``;`
`&::before {`
`content``: ``""``;`
`position``: ``absolute``;`
`width``: ``100px``;`
`height``: ``100px``;`
`border``: ``37px` `solid` `#fff``;`
`border-top``: ``37px` `solid` `transparent``;`
`border-radius: ``50%``;`
`top``: ``123px``;`
`left``: ``-137px``;`
`transform: rotate(``45``deg);`
`}`
`&::after {`
`content``: ``""``;`
`position``: ``absolute``;`
`width``: ``140px``;`
`height``: ``140px``;`
`border``: ``30px` `solid` `#fff``;`
`border-right``: ``30px` `solid` `transparent``;`
`border-top``: ``30px` `solid` `transparent``;`
`border-left``: ``30px` `solid` `transparent``;`
`top``: ``-100px``;`
`right``: ``-172px``;`
`border-radius: ``100%``;`
`transform: rotate(``45``deg);`
`}`
`}`
接下來就是輪到
filter: drop-shadow()
登場,它可以在元素呈現(xiàn)之前士八,為元素的渲染提供一些效果容燕,最常見的也就用它渲染整體陰影。我們通常會用它來實現(xiàn)對話框的小三角與整個對話框的陰影效果曹铃,像下面這樣,左邊是使用drop-shadow
的效果捧杉,右邊是使用普通box-shadow
的效果陕见。
本文假定讀者已經(jīng)了解了 drop-shadow 的基本用法秘血,上圖效果來自這里:CodePen Demo -- Drop-shadow vs box-shadow (2) By Kseso
- OK,回到我們正文评甜,下面我們使用
filter: drop-shadow()
生成它的第一層左邊的藍(lán)色陰影灰粮,添加在主體 div:
`div {`
`position``: ``relative``;`
`width``: ``37px``;`
`height``: ``218px``;`
`background``: ``#fff``;`
`filter:drop-shadow(``-10px` `-10px` `0` `#24f6f0``);`
`&::before,`
`&::after {`
`...`
`}`
`}`
好,接下來我們只需要再添加一層紅色
filter: drop-shadow()
在右側(cè)就大功告成忍坷!等等粘舟!哪里不對,上面我也有提到過佩研, 和
box-shadow
一樣柑肴,text-shadow
是可以疊加多層的!但是對于單個元素而言旬薯,drop-shadow
的話就只能是一層晰骑。也就是說,無法在 div 上再使用
filter: drop-shadow()
生成另一側(cè)的紅色投影绊序,不過還好硕舆,我們還有兩個偽元素的filter: drop-shadow()
以及box-shadow
還沒有用上,經(jīng)過一番嘗試:
`div {`
`position``: ``relative``;`
`width``: ``37px``;`
`height``: ``218px``;`
`background``: ``#fff``;`
`filter:drop-shadow(``-10px` `-10px` `0` `#24f6f0``) contrast(``150%``) brightness(``110%``);`
`box-shadow: ``11.6px` `10px` `0` `0` `#fe2d52``;`
`&::before {`
`filter: drop-shadow(``16px` `0px` `0` `#fe2d52``);`
`}`
`&::after {`
`filter:drop-shadow(``14px` `0` `0` `#fe2d52``);`
`}`
`}`
- 我們分別再利用 div 的
box-shadow
以及兩個偽元素的filter: drop-shadow()
骤公,在單個標(biāo)簽的限制下抚官,最終結(jié)果如下:
CodePen Demo -- 單標(biāo)簽實現(xiàn)抖音LOGO
總結(jié)一下:
- 主要借助了兩個偽元素實現(xiàn)了整體結(jié)構(gòu),借助了 drop-shadow 生成一層整體陰影
- drop-shadow 只能是單層陰影阶捆,所以另一層陰影需要多嘗試
- contrast(150%) brightness(110%) 則可以增強(qiáng)圖像的對比度和亮度凌节,更貼近抖音LOGO的效果
更新于 2018-11-9
關(guān)于上述抖音 LOGO,經(jīng)友人提醒趁猴,其實應(yīng)該只是兩個類 J 形的形狀重疊在一起刊咳,重疊部分為白色,非重疊部分為各自原色儡司。
當(dāng)初想復(fù)雜了娱挨,這個效果我嘗試了一下,使用 CSS 的混合模式
mix-blend-mode
也是可以實現(xiàn)的捕犬,下面給出實現(xiàn)方法如下跷坝,感興趣的同學(xué)可以看看:
CodePen Demo -- 使用 mix-blend-mode 實現(xiàn)抖音 LOGO
當(dāng)然,關(guān)于 CSS 陰影還有很多有意思的技巧和細(xì)節(jié)碉碉,本文限于篇幅不再一一羅列柴钻。
我在 Git 上開了個倉庫,CSS-Inspiration垢粮,以分類的形式贴届,展示不同 CSS 屬性或者不同的課題使用 CSS 來解決的各種方法。更多有意思的 CSS 技巧可以在這里找到,而且是每日更新毫蚓。
最后
- 感謝耐心讀完占键。
- 好了,本文到此結(jié)束元潘,希望對你有幫助 :)
- 如果還有什么疑問或者建議畔乙,可以多多交流,原創(chuàng)文章翩概,文筆有限牲距,才疏學(xué)淺,文中若有不正之處钥庇,萬望告知牍鞠。
本次給大家推薦一個免費(fèi)的學(xué)習(xí)群,里面概括移動應(yīng)用網(wǎng)站開發(fā)上沐,css皮服,html,webpack参咙,vue node angular以及面試資源等龄广。
對web開發(fā)技術(shù)感興趣的同學(xué),歡迎加入Q群:582735936蕴侧,不管你是小白還是大牛我都?xì)g迎择同,還有大牛整理的一套高效率學(xué)習(xí)路線和教程與您免費(fèi)分享,同時每天更新視頻資料净宵。
最后敲才,祝大家早日學(xué)有所成,拿到滿意offer择葡,快速升職加薪紧武,走上人生巔峰。