Kekeの日記

エンジニア、読書なんでも

影との戦いを制する力を手に入れる!CSSのbox-shadowプロパティを理解する

f:id:bobchan1915:20190210210134p:plain

はじめに

ここの節は余談なので飛ばしてもらっていいです。

ジブリ映画『ゲド戦記』の原作であるゲド戦記シリーズの第1巻『ゲド戦記 影との戦い』では、主人公のゲドの学童期が描かれます。

すでに奇才と認められていたにも関わらず、ゲドは他人より優れたいという虚栄心から、呼び出してはいけない死者の魂を呼び出してしまいます。禁忌に触れて、「影」が出現してしまいゲドに重症の怪我を負わせ、そのあとも影はゲドを追いかけつづけます。その影とゲドの対峙を描いた一冊なのです。

影との戦い―ゲド戦記〈1〉 (岩波少年文庫)

影との戦い―ゲド戦記〈1〉 (岩波少年文庫)

  • 作者: アーシュラ・K.ル=グウィン,ルース・ロビンス,Ursula K. Le Guin,清水真砂子
  • 出版社/メーカー: 岩波書店
  • 発売日: 2009/01/16
  • メディア: 単行本
  • 購入: 6人 クリック: 27回
  • この商品を含むブログ (29件) を見る

ネタバレになるので結論はいいませんが、人は誰でも他人より優れたいと思うのは、ダーウィンが唱えた自然淘汰の考えからも自明で、それが人の心の影そのものでもあったりします。特に、若ければ頭で考え、歯止めを効かすのは難しいでしょう。

高名な心理学者であるユングも、影(=無意識)について考察をしています。 特に無意識が意識の領域に出現するのを抗うものとしての「心の問題」が出るものと解説してます。

ja.wikipedia.org

からといって、本記事の主題であるCSSのBox shadowは私たちの心の影(=無意識)ではありません。笑

ただ、私にとって影とは自分自身であり、少し考え深かったのでこの節を書きました。 劣等感、充実感など心の諸問題は、良し悪し関わらず私自身であると強く思いました。

それでは、本題に入ります。

目次

今回は以下のようなコンテンツで解説をしていこうかなと思います。

注意点

本記事では、HTMLのメタ言語であるPug(Jade)を使用して、CSSのメタ言語であるScssを使用しています。

Box shadow

概要

ボックスに影をつけるのはbox-sizingプロパティで定義でき、影は一つ以上つけることができます。

例えば以下のようなdiv要素があったとします。

f:id:bobchan1915:20190210183006p:plain

この中の薄ピンクの要素をinner-container、それを囲うアクアマリンの要素をouter-containerと定義します。

つまり、HTMLは以下のようになっています。

.outer-container
     .inner-container
         h5.content.subtitle Hello
         h3.content.title This is my blog

ID名やClass名は今回は適当につけています。

CSSというと、このようになっています。

.outer-container {
    background-color: aquamarin;
    padding: 40px 30px; 
    
    .inner-container {
          backgroud-color: bisque;
          width: 100%;
          height: 100%;

すると、例えば以下のようにinner-container要素にbox-shadowプロパティを付与すると以下のようになります。

今は何も理解しなくても大丈夫です。

... {
    ...
    
    .inner-container {
           ...
           box-shadow: 3px 3px 3px gray; // <-- ここを追加
           }
}

出力は以下のようになります。

f:id:bobchan1915:20190210184050p:plain

影がついています。

今回は影を一つだけつける方法を解説しますが、羅列するだけでなくて、,区切りで影を複数設定することができます。

box-shadow: 3px 3px gray;
box-shadow: 3px 3px 3px 3px rgba(0, 0, 0, 0.4) inset;

でもいいですし、

box-shadow: 3px 3px gray, 3px 3px 3px 3px rgba(0, 0, 0, 0.4) inset;

ここで問題なのですがどのように影を「制御」し、自分の意のまま操れるのでしょうか

デバッグ方法

Shadowに限らずChrome Developers ToolsではCSSのプロパティをデバッグできます。

"Elements" -> "Styles"で見てみてください。

特にShadowに関しては、box-shadow:の隣の四角が重なっているマークを押すと、Shadowに関してプロパティを変えることができるので便利です。

f:id:bobchan1915:20190216140242g:plain

プロパティの設定方法

box-shadow: 3px 3px 3px gray;のように設定しましたが、一体、これはどのようなことを設定しているのでしょうか。詳細に解説してみます。

まず、サンプルをいくつか紹介します。

box-shadow: 3px 3px gray;
box-shadow: 3px 3px 3px 3px rgba(0, 0, 0, 0.4) inset;

ここで理解していただきたいのが、いくつも種類があるということです。

前提 省略可能な設定値もある

これから解説していきますが、

box-shadow: 3px 3px gray;
box-shadow: 3px 3px 3px 3px rgba(0, 0, 0, 0.4) inset;

でも動作します。設定方法に差異が大きくあって、どれが必要か不必要なのかがわからなくなるかもしれませんう。

というのも

  • 3つ目のぼかし距離
  • 4つ目の広がり距離
  • 最後のinsetキーワード

は省略することができます。

なので、本質的な解説をするために、そのときそのときに必要な設定値を使います。

描画エリアとぼかし、広がり

どのくらいの大きさで、どの方向に影をつけるのかを決めます。〇〇px 〇〇px ...のように定義しているところです。

最大4つの指定値を順番に説明します。

1. 水平方向のオフセット距離(Offset Distance)

以下のように値の符号によって、影の方向が変わります。

  • 正の値: 右方向
  • 負の値: 左方向

例えば以下のようにします。

box-shadow: 10px 0px gray;

出力は以下の通りです。

f:id:bobchan1915:20190210190237p:plain

また、負の値をすると以下のようになります。

f:id:bobchan1915:20190210190309p:plain

オフセット距離とありますが簡単にいうとBorder(=枠)からの距離です。

2. 垂直方向のオフセット距離(Offset Distance)

これは1. 水平方向のオフセット距離で解説をしたものの垂直バージョンです。

特に変わりはないため、解説をしません。

3. ぼかし距離(Blur Radius)

少しぼかしのアルゴリズムを解説しなければなりません。 のちに別の記事で取り上げたいなと思うのですが、ぼかすは色の境界付近で指定したピクセルの色の平均化をします。 つまり、どれくらいの領域で平均化をするかを指定する必要があります。

ここでは大きくすればするほどぼやけます。

f:id:bobchan1915:20190210200126p:plain

もちろんShadowがついていない領域は(0, 0, 0)として扱われます。 当然、背景色(ここではinner-containerに対してのouter-containerのaquamarin色に対して算術が行われるをわけではないので注意してください。

例えばぼかし距離を3pxに指定したときに周りの3px × 3pxに対しての算術を行うことになります。 内部の四角が歪んでしまいましたが、外の四角で囲まれる9ピクセルに対して中央の単一ピクセルは平均化された値が代入させることになります。

f:id:bobchan1915:20190210201432p:plain

また、外側に対しても以下のようになります。

f:id:bobchan1915:20190210201749p:plain

ぼかし距離が0、または省略したときは何もないピクセルですが、ぼかし距離を設定したときに、中央の灰色の色ができます。

これがすべてのピクセルに対して行われるので、影がもやっとぼやけます。

アルゴリズムから自明ですが、オフセット距離 + ぼかし距離 / 2 だけさらに要素全体が大きくなったかのように感じます

4. 広がり距離(Spread Distance)

オフセット距離と同様に、符号によって振る舞いが変化します。

  • 正の値: Shadowのサイズを大きくする
  • 負の値: Shadowのサイズを小さくする

例えば以下のようにします。

box-shadow: 3px 0px 0px 4px grey;

すると出力は以下のようになります。

f:id:bobchan1915:20190210203113p:plain

全体的に指定したpx分だけ広げるという印象です。

色の指定

色を指定します。これはcolorborder-colorなどと一緒です。

以下のようにいろんな方法で指定することができます。

box-shadow: 10px 0px gray;
box-shadow: 10px 0px rgba(0, 255, 255, 0.4);
box-shadow: 10px 0px #ffffff;
box-shadow: 10px 0px $company-red; // <- SCSSの変数を使う

統一した方法で指定すればいいと思います。

insetキーワード

insetをつけると、影を要素の内側につけることができます。insetは日本語では挿入を意味して、つまりボックスの中にShadowを挿入します。

f:id:bobchan1915:20190210202623p:plain

insetを指定すると、挿入するので、下にShadowをつけていたのが上に影が挿入されます。

時々、反転することが頭の中でこんがらがるので、OffsetだったのがInsetになるので影がつくのではなく、挿入されるということを覚えておけばいいと思います。

お遊びですが、

box-shadow: 0px 0px 10px 10px lightgray;

のようにするとどのようになるでしょうか?少し想像してみてください。

. . . . . 答えは以下の通りです。

f:id:bobchan1915:20190210204514p:plain

まるで、真上から見下ろしたような感じになります。 たまに、このようなShadowをつけたいときありますよね。

ぜひ、色々、練習してみるといいかもしれません。

テキストに影をつけたくなったら?

テキスト自体に影をつけたくなったらtext-shadowプロパティを使うとつけることができます。

今回の記事では解説しませんが、必要に応じて学んでみてください。

最後に

デザインからの要請で影(=Shadow)をつける必要があることは多いと思います。

そのときに、この記事をみて、スムーズに対応できればいいなと思い、自分自身の備忘録としても本記事を書き起こしました。

ありがとうございました。