ホームページ >ウェブフロントエンド >htmlチュートリアル >CSS Magic Hall: Box-Shadow はそれほど単純ではありません:)_html/css_WEB-ITnose

CSS Magic Hall: Box-Shadow はそれほど単純ではありません:)_html/css_WEB-ITnose

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBオリジナル
2016-06-21 08:48:131526ブラウズ

はじめに

ボックスシャドウについて話すとき、最初に考えられるのは、もちろん、それを使用してシャドウを実現することです。実際、この記事は、他の興味深い効果を実現するためにも使用できます。ボックスシャドウのことについて話します。

何も言わずにエフェクトを見てください

3D ボール

<style type="text/css">.ball{  background: rgba(100,100,100,0.2);  width: 100px;  height: 100px;  padding: 10px;  border-radius: 50%;  box-shadow: -14px 8px 100px #333 inset,               0 0 2px #888,          3px -1px 4px #444;}</style><div class="ball"></div>

紙の影 (@张鑫兴师より)

<style type="text/css">.curved_box {    display: inline-block;    *display: inline;    width: 200px;    height: 248px;    margin: 20px;    background-color: #fff;    border: 1px solid #eee;    -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 60px rgba(0, 0, 0, 0.06) inset;    -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.06) inset;     box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.06) inset;    position: relative;    *zoom: 1;}.curved_box:before {    -webkit-transform: skew(-15deg) rotate(-6deg);    -moz-transform: skew(-15deg) rotate(-6deg);    transform: skew(-15deg) rotate(-6deg);    left: 15px;}.curved_box:after {    -webkit-transform: skew(15deg) rotate(6deg);    -moz-transform: skew(15deg) rotate(6deg);    transform: skew(15deg) rotate(6deg);    right: 15px;}.curved_box:before, .curved_box:after {    width: 70%;    height: 55%;    content: ' ';        -webkit-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);    -moz-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);     box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);        position: absolute;    bottom: 10px;    z-index: -1;    }</style><div class="curved_box"></div>

プロパティをよく読んでください

上記のような素晴らしいエフェクトを見て、ボックス シャドウを理解したいと思いませんか?一歩ずつ解読していきましょう!

属性の構文の概要

box-shadow: none | 2682287aecd16e99c4f70c025ad645ed[,2682287aecd16e99c4f70c025ad645ed]*デフォルト値は none2682287aecd16e99c4f70c025ad645ed:inset? ,4} && b10fb37415d019cfffa8c4d7366c607f?シャドウ パターン、デフォルトはアウトセット、つまりアウター ボックス シャドウが使用されます。 inset に設定すると、内側のボックスシャドウが使用されます。 水平オフセット、元の位置からの影の水平方向の変位。正の数値は右への移動を意味し、負の数値は左への移動を意味します。 垂直オフセット、元の位置からの影の垂直方向の変位は、正の数値は下方向に移動することを意味し、負の数値は上方向に移動することを意味します。 ぼかし半径、デフォルト値は 0、シャドウのぼかし半径です。 拡散距離、デフォルト値は 0 で、影の領域を拡大または縮小します。 b10fb37415d019cfffa8c4d7366c607f、影の色、デフォルトは color 属性と一致します。

注: 複数の影を同時に設定でき、影の Z インデックス値は左から右に減少します。

アウターボックスシャドウとインナーボックスシャドウをプレイするにはどうすればよいですか?

デフォルトでは、外側の box-shadow が使用されます。 inset キーワードが box-shadow に追加されると、内側の box-shadow が使用されます。しかし、この 2 つの効果は何でしょうか。

<style type="text/css">.box{  float: left;  background: #888;  width: 100px;  height: 100px;  margin-right: 20px;}.outer-box-shadow{  box-shadow: 10px 10px #F00;}.inner-box-shadow{  box-shadow: 10px 10px #F00 inset;}</style><div class="box outer-box-shadow"></div><div class="box inner-box-shadow"></div></div>

outer-box-shadow 特徴: 影は要素の境界ボックスの外側に表示されます。実装原理:

  1. 要素の境界ボックスと同じサイズのシャドウ ボックスを作成します。
  2. 要素の境界ボックスと一致するようにシャドウ ボックスを要素の下に配置します。
  3. 水平オフセットと垂直オフセットに基づいて元の位置を基準に移動します。
  4. 拡散距離に基づいてシャドウ ボックスのサイズを調整します (ボックスの変位に影響します)。
  5. ぼかし半径に基づいてシャドウボックスを移動
  6. 最後に、シャドウボックスと要素境界ボックスの重なっている部分を切り出します。

    <style type="text/css">.box{  background: #888;  width: 100px;  height: 100px;}.outer-box-shadow{  box-shadow: 90px 10px #F00;}</style><div class="box outer-box-shadow"></div></div>

    シミュレート:

    <style type="text/css">.box{  position: relative;}.box-shadow{  position: absolute;  z-index: -1;  background: #F00;  width: 100px;  height: 100px;  left: 20px;  top: 20px;}.box-content{  background: #888;  width: 100px;  height: 100px;}</style><div class="box">  <div class="box-shadow"></div>  <div class="box-content"></div></div>

inner-box-shadow 機能: シャドウは、内の要素。実装原理 (完全に個人的な理解):

  1. 要素のパディング ボックスと同じサイズのシャドウ ボックスを作成します。
  2. 要素のパディング ボックスと一致するようにシャドウ ボックスを配置します。要素 Top;
  3. 要素のパディングエッジと一致するように、水平方向と垂直方向にそれぞれ 2 本の線を描画します (合計 4 本の線が left/top/right/bottom-guideline として記録されます)
  4. 水平オフセットと垂直オフセットに従って、左/上/右/下のガイドラインを移動します。
  5. 拡散距離に応じて4つのラインを移動します。拡散距離が正の数の場合、左のガイドラインは右に移動し、上のガイドラインは下に移動し、右のガイドラインは左に移動し、下のガイドラインは上に移動します。その逆が真です。
  6. ぼかし半径に従って要素の各パディングエッジとそれに対応するガイドラインの間の領域を処理します。
  7. シャドウ ボックスをクリップします
    1. 重ならない領域を切り取ります要素 Part のパディング ボックスを使用します。
    2. 要素の各パディング エッジとそれに対応するガイドラインの間の領域のみを表示します。

      <style type="text/css">.box{  float: left;  background: #888;  width: 100px;  height: 100px;  margin-right: 10px;}.box1{  box-shadow: 0 0 0 20px red inset;}.box2{  box-shadow: 10px 0 0 20px red inset;}.box3{  box-shadow: 10px 0 10px 20px red inset;}.box4{  box-shadow: 0 0 10px 50px red inset;}</style><div class="box box1"></div><div class="box box2"></div><div class="box box3"></div><div class="box box4"></div>

      シミュレート:

      <style type="text/css">.box-shadow{  position: relative;  display: inline-block;  background: red;  overflow: hidden;}.bg{  position: absolute;  background: #888;  left: 30px;  right: 10px;  top: 20px;  bottom: 20px;}.content{  position: relative;  z-index: 1;  width: 80px;  height: 80px;  padding: 20px;}</style><div class="box-shadow">  <div class="bg"></div>  <div class="content"></div></div>

ぼかし半径による境界線のぼかし

W3C 仕様ではブラウザメーカーがぼかし効果を実現するためにどの方法を使用するかについては規定されていません。とにかく、その効果はガウスぼかし効果とほぼ同じです。ただし、注意する必要があるのは、ぼかし効果により影の範囲が拡大されることです

<style type="text/css">.outline{  border: 1px solid red;  margin: 40px 0;}.s{  background: rgba(255, 100, 100, 0.1);  width: 100px;  height: 100px;}.s1{  box-shadow: 110px 0 0 #333;}.s2{  box-shadow: 110px 0 20px #333;}.s3{  box-shadow: 110px 0 40px #333;}</style><div class="outline">  <div class="s s1">sample1</div></div><div class="outline">  <div class="s s2">sample2</div></div><div class="outline">  <div class="s s3">sample3</div></div>

sample1 はぼかし半径が 0 の場合の効果です。影のサイズが要素のサイズとまったく同じであることがわかります。そして、sample2はぼかし半径20pxの効果ですが、sample3ではさらに影のサイズが拡大しているのがわかります。ぼかし半径の値が 0 より大きい場合、影のサイズが拡大されることが感覚的に理解できましたが、どの程度拡大されるのでしょうか?次に、まずブレが発生する開始位置を明確にする必要があります。

  1. 对于outer-shadow-box而言,模糊发生的起始位置就是阴影盒子的各边;
  2. 对于inner-shadow-box而言,模糊发生的起始位置就是各guideline。然后模糊效果是从发生的位置,对于水平方向的边或guideline则向垂直方向发散,对于垂直方向的边或guideline则向水平方向发散,且发散的距离相同。发散的距离相同,因此每个方向各发散为blur radius/2的距离。看sample3中阴影尺寸已经与元素盒子重叠了,因为阴影盒子左边框向左发散了20px了,超过它俩之间10px的水平距离了,而sample2则恰恰邻近而已。

缩放阴影尺寸 by spread distance

如果说blur radius是暗地里扩大阴影的尺寸,那么spread distance则是明目张胆地缩放阴影的尺寸了。

<style type="text/css">.outline{  border: 1px solid red;  margin: 40px 0;}.s{  background: rgba(255, 100, 100, 0.1);  width: 100px;  height: 100px;}.s1{  box-shadow: 110px 0 0 #333;}.s2{  box-shadow: 110px 0 0 10px #333;}.s3{  box-shadow: 110px 0 0 -10px #333;}</style><div class="outline">  <div class="s s1">sample1</div></div><div class="outline">  <div class="s s2">sample2</div></div><div class="outline">  <div class="s s3">sample3</div></div>

还记得《CSS魔法堂:重拾Border之——解构Border》中提及通过border-top/right/bottom/left-colors实现彩虹边框吗?由于兼容性问题和1px对应一种color的缘故,实际应用得很少,但通过outer-box-shadow和spread distance我们就可以得到效果更好,兼容性很高的实现方案了。

<style type="text/css">.rainbow{  margin: 50px;  width: 100px;  height: 100px;  box-shadow: 0 0 0 2px rgb(255,0,0),              0 0 0 5px rgb(255,165,0),              0 0 0 8px rgb(255,255,0),              0 0 0 10px rgb(0,255,0),              0 0 0 12px rgb(0,127,255),              0 0 0 15px rgb(0,0,255),              0 0 0 20px rgb(139,0,255);}</style><div class="rainbow"></div>

弄清各图层的z-index

上图可以看到没有阴影时,各图层的z-index顺序。那么阴影呢?

  1. 对于outer-box-shadow,则其z-index高于margin图层,低于background-color图层;
  2. 对于inner-box-shadow,则其z-index高于padding图层,低于content图层。

阴影的position

通过horizontal/vertical offset重定位阴影盒子,通过blur radius或spread distance缩放阴影盒子的尺寸,但请注意的是阴影盒子不影响其他盒子的布局,其实阴影盒子就相当于采用absolute定位一样,不会占据Normal flow的空间,也不会影响其他元素的布局,因此仅修改阴影位置或尺寸时,只会触发repaint,而不会触发reflow。

圆角or直角box-shadow傻傻分不清楚?

阴影不仅默认尺寸与元素盒子一致,默认形状也一致。也就是元素盒子采用圆角时,阴影的默认形状也是圆角的。既然说是默认形状一致,就是说可以不一致咯!那到底如何不一致呢,下面我们一起来看个究竟吧!

<style type="text/css">.s1{  background: #0EF;  width: 100px;  height: 100px;  border-radius: 10px;  box-shadow: 110px 0 0 -10px #333,        220px 0 0 0 #666,        360px 0 0 20px #888;}</style><div class="s1">sample1</div>

当设置spread distance后,border-radius的值也将随之变化,具体公式为border-radius + spread-distance * (1 + (border-radius / spread-distance - 1)^3)。因此spread distance为正数时,border-radius会变大; 而spread distance为负数时,border-radius会减小,直至为0px为止。

被割裂的box-shadow

当设置box-shadow的盒子被拆分为多个盒子时,其对应的box-shadow又会如何呢?其实这不仅仅是box-shadow的问题,如border、background-image等均会遇到同样的问题。CSS3中引入一个新特性box-decoration-break来设置上述情况时的渲染效果。box-decoration-break: slice | cloneslice是默认值,表示首先按未拆分时的状态渲染border、background-image等样式,然后再将其直接拆分为多个盒子;clone表示首先将其直接拆分为多个盒子,然后再逐个盒子渲染border、background-image等样式。

<style type="text/css">.intro{  font-size: 14px;  line-height: 1.5;  text-indent: 1em;  width: 300px;}.intro span{  border: 1px solid #666;  border-radius: 5px;  box-shadow: 5px 3px 3px #AAA;}.slice{  -webkit-box-decoration-break: slice;}.clone{  -webkit-box-decoration-break: clone;}</style><p class="intro"><span class="slice">Hey there, welcome to be here to share something aboute CSS together:) My name is fsjohnhuang, a FE from Midea. Enjoy the evolution of FE, and feel excited in the work I'm doing now.</span></p><p class="intro"><span class="clone">Hey there, welcome to be here to share something aboute CSS together:) My name is fsjohnhuang, a FE from Midea. Enjoy the evolution of FE, and feel excited in the work I'm doing now.</span></p>

从上面可以看到,与其说box-decoration-break的属性值影响box-shadow的效果,还不如说是box-decoration-break的属性值影响border-radius和border作用到元素盒子的效果,然后由盒子的效果再间接影响box-shadow的效果。

兼容性IE和Edge均不支持,FF支持得最好,而Webkit内核的则要加-webkit-前缀。对于不支持的浏览器,其效果如同box-decoration-break:slice

兼容性

IE9都支持box-shadow多让人可喜可贺的消息啊(因为我工作中只需兼容IE9+就Ok了:))。但IE6~8呢?方案很多啦,上面也有简单的介绍到。@张鑫旭老师提到在模拟blur radius效果时,采用以下方案

.ieBlock{    height:100px;    width:100px;    background:#000;    filter:progid:DXImageTransform.Microsoft.Blur(pixelradius=10);    -ms-filter:"progid:DXImageTransform.Microsoft.Blur(pixelradius=10)"; }

要比采用以下方案要好!

.shadow {    -moz-box-shadow: 3px 3px 4px #000;    -webkit-box-shadow: 3px 3px 4px #000;    box-shadow: 3px 3px 4px #000;    /* For IE 8 */    -ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000')";    /* For IE 5.5 - 7 */    filter: progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000');}

另外若想不假思索地用到生产环境中,还是用成熟的CSS库较好。具体请参考PIE使IE支持CSS3圆角盒阴影与渐变渲染

感谢

the-box-shadowbreak-decorationCSS3 box-shadow实现纸张的曲线投影效果CSS实现跨浏览器兼容性的盒阴影效果CSS实现跨浏览器的box-shadow盒阴影效果(2)PIE使IE支持CSS3圆角盒阴影与渐变渲染《图解CSS3核心技术与案例实战》 —— 3.5 CSS3盒子阴影属性

打赏支持作者写出更多好文章,谢谢!

著者に報酬を与えます

著者がより良い記事を書くことをサポートするためのヒント、ありがとう!

支払い方法を選択してください

著者について: ^-^Fat John

個人フロントエンドスタックエンジニアのホームページ · 私の記事 · 1 ·

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。