$30 off During Our Annual Pro Sale. View Details »

本気でCSS芸やりたい人のためのbox-shadow講座 / Mastering box-shadow

本気でCSS芸やりたい人のためのbox-shadow講座 / Mastering box-shadow

発表内容文字起こし
https://kuroeveryday.blogspot.com/2019/07/mastering-box-shadow.html

UIT meetup vol.7 集まれ!(タブン)実務では使わないフロントエンド芸発表会
https://uit.connpass.com/event/138084/

NES.css | NES-style CSS Framework
https://github.com/nostalgic-css/NES.css

CSS Collection(CSS芸)
https://bcrikko.github.io/css-collection/

box-shadowを使ってCSSだけでドット絵を描き、アニメーションさせる
https://kuroeveryday.blogspot.com/2018/10/draw-and-animate-pixel-art-using-only-css.html

transform: scale()で要素が重なってしまったときのmarginのとり方
https://kuroeveryday.blogspot.com/2019/02/margin-of-elements-resized-by-transform.html

https://twitter.com/bc_rikko

ダーシノ

July 24, 2019
Tweet

More Decks by ダーシノ

Other Decks in Programming

Transcript

  1. CSS芸やりたい⼈のための
    box-shadow講座
    UIT meetup vol.7 - CSS芸⼈枠
    ダーシノ(@bc_rikko)

    本気で

    View Slide

  2. ダーシノ
    さくらインターネット
    速弾きができるフロントエンドエンジニア
    @bc_rikko BcRikko Black Everyday Company
    https://kuroeveryday.blogspot.com/

    View Slide

  3. https://bcrikko.github.io/css-collection/

    View Slide

  4. View Slide

  5. ・ファミコン⾵CSSフレームワーク
    ・GitHub Stars: 13,000+
    ・世界ランク 4位
    ※css-frameworkトピック 2019年4⽉時点
    NES.css

    View Slide

  6. box-shadow
    使ってますか?

    View Slide

  7. ここにも
    ここにも
    ここにも
    ここにも

    View Slide

  8. 地味で⽬⽴たないけど、
    いたるところで使われている

    View Slide

  9. View Slide

  10. これ全部
    box-shadow

    View Slide

  11. box-shadowプロパティに
    スポットライトを当てる!

    View Slide

  12. 話すこと
    • box-shadowの基礎
    • box-shadowで○○する
    • ファミコン⾵UIをつくる
    • ドット絵を描く
    • box-shadow芸のハマりポイントと解決策
    • ギガを消費する?!
    • メンテできない?!
    • まとめ
    1
    2
    3
    4

    View Slide

  13. 1. box-shadowの基礎

    View Slide

  14. box-shadowの基本構⽂
    inset

    通常ボックスの外に表⽰される影を内側に表⽰する
    offset-x

    表⽰する影のX座標、正の数: 右側、負の数: 左側
    offset-y

    表⽰する影のY座標 正の数: 下側、負の数: 上側
    blur-radius

    ガウスフィルタの半径 

    ゼロでは影がぼやけない 1px以上で影がぼやける
    spead-radius

    影の拡⼤/縮⼩ 正の数: 拡⼤、負の数: 縮⼩

    ゼロのときの影は親要素と同じサイズになる
    color

    影の⾊を指定する、指定しない場合はcurrentColorになる
    box-shadow:

    offset-x
    offset-y
    [blur-radius]
    [spread-radius]
    [color];

    View Slide


  15. 100x100
    1. 影のサイズは要素と同じ
    2. 影は要素の背⾯に表⽰される
    3. 影はカンマ区切りで複数指定できる
    box-shadow芸の3つのポイント

    100x100
    影3
    100x100
    .box {
    width: 100px;
    height: 100px;
    box-shadow:
    90px 90px black;
    }
    .box {
    width: 100px;
    height: 100px;
    box-shadow:
    150px 0 black,
    0 150px black,
    150px 150px black;
    }
    (0,0)

    100x100
    影1
    100x100
    影2
    100x100
    x:150px
    y:150px

    View Slide

  16. 2. box-shadowで○○する

    View Slide

  17. box-shadowで○○する①
    ファミコン⾵UIをつくる

    View Slide

  18. box-shadowでファミコン⾵UIをつくる
    Input text
    ※ フォントはPress Start 2P

    View Slide

  19. テキストボックス
    Input text
    Input text

    <br/>.nes-input {<br/>box-shadow:<br/>/* 右 */<br/>4px 0 black,<br/>/* 左 */<br/>-4px 0 black,<br/>/* 下 */<br/>0 4px black,<br/>/* 上 */<br/>0 -4px black;<br/>}<br/>

    View Slide

  20. テキストボックス
    Input text
    Input text

    <br/>.nes-input {<br/>box-shadow:<br/>/* 右 */<br/>4px 0 black,<br/>/* 左 */<br/>-4px 0 black,<br/>/* 下 */<br/>0 4px black,<br/>/* 上 */<br/>0 -4px black;<br/>}<br/>

    View Slide

  21. ボタン
    default
    :hover
    :active
    Button
    .nes-btn {
    box-shadow:
    4px 0 black, /* 右 */
    -4px 0 black, /* 左 */
    0 4px black, /* 下 */
    0 -4px black, /* 上 */
    inset 4px 4px navy; /* 内側 */
    }
    .nes-btn:hover {
    box-shadow:
    4px 0 black, /* 右 */
    -4px 0 black, /* 左 */
    0 4px black, /* 下 */
    0 -4px black, /* 上 */
    inset 6px 6px navy; /* 内側 */
    }
    .nes-btn:active {
    box-shadow:
    4px 0 black, /* 右 */
    -4px 0 black, /* 左 */
    0 4px black, /* 下 */
    0 -4px black, /* 上 */
    inset -4px -4px navy; /* 内側 */
    }
    基本は
    フォーム⼊⼒と同じ
    insetを使って
    ⽴体感を表現する
    insetを使って
    hoverやactiveの
    スタイルを調整する

    View Slide

  22. box-shadowで○○する②
    ドット絵を描く

    View Slide

  23. box-shadowでドット絵を描く

    View Slide

  24. ドット絵

    <br/>.nes-icon.heart {<br/>/* 1ドットのサイズ */<br/>width: 1px;<br/>height: 1px;<br/>/* ドット絵 */<br/>box-shadow:<br/>...,<br/>..., 2px 3px black,3px 3px red , ...,<br/>..., 2px 4px red, 3px 4px white, ...,<br/>...;<br/>}<br/>

    View Slide

  25. 3. box-shadow芸の
    ハマりポイントと解決策

    View Slide

  26. ハマりポイント①
    ギガを消費する?!

    View Slide

  27. ⼤量のピクセル情報を持っている

    <br/>.nes-icon.heart {<br/>width: 4px;<br/>height: 4px;<br/>background: transparent;<br/>box-shadow:<br/>12px 8px #444444, 16px 8px #444444,<br/>20px 8px #444444, 44px 8px #444444,<br/>48px 8px #444444, 52px 8px #444444,<br/>8px 12px #444444, 12px 12px #f22326,<br/>16px 12px #f22326, 20px 12px #f22326,<br/>/* 省略 */<br/>28px 56px #444444, 32px 56px #842300,<br/>36px 56px #444444, 32px 60px #444444,<br/>}<br/>

    View Slide

  28. ⼤量のピクセル情報を持っている

    <br/>.nes-icon.heart {<br/>width: 4px;<br/>height: 4px;<br/>background: transparent;<br/>box-shadow:<br/>12px 8px #444444, 16px 8px #444444,<br/>20px 8px #444444, 44px 8px #444444,<br/>48px 8px #444444, 52px 8px #444444,<br/>8px 12px #444444, 12px 12px #f22326,<br/>16px 12px #f22326, 20px 12px #f22326,<br/>/* 省略 */<br/>28px 56px #444444, 32px 56px #842300,<br/>36px 56px #444444, 32px 60px #444444,<br/>}<br/>
    box-shadowだけで
    2,713 bytes

    View Slide

  29. サイズごとにbox-shadowの指定が必要




    <br/>.nes-icon.heart {<br/>width: 2px; height: 2px;<br/>box-shadow: /* 省略 */;<br/>}<br/>.nes-icon.heart.is-small {<br/>width: 1px; height: 1px;<br/>box-shadow: /* 省略 */;<br/>}<br/>.nes-icon.heart.is-medium {<br/>width: 3px; height: 3px;<br/>box-shadow: /* 省略 */;<br/>}<br/>.nes-icon.heart.is-large {<br/>width: 4px; height: 4px;<br/>box-shadow: /* 省略 */;<br/>}<br/>
    4パターン分の
    box-shadow

    View Slide

  30. サイズごとにbox-shadowの指定が必要




    <br/>.nes-icon.heart {<br/>width: 2px; height: 2px;<br/>box-shadow: /* 省略 */;<br/>}<br/>.nes-icon.heart.is-small {<br/>width: 1px; height: 1px;<br/>box-shadow: /* 省略 */;<br/>}<br/>.nes-icon.heart.is-medium {<br/>width: 3px; height: 3px;<br/>box-shadow: /* 省略 */;<br/>}<br/>.nes-icon.heart.is-large {<br/>width: 4px; height: 4px;<br/>box-shadow: /* 省略 */;<br/>}<br/>
    4パターン分の
    box-shadow
    box-shadowだけで
    2,713 bytes × 4
    ※ 実際はoffset-x, offset-yの値が若⼲変わるので2,713 bytes×4とは異なる

    View Slide

  31. View Slide

  32. ギガ消費を抑える⽅法
    • currentcolor(要素のcolorプロパティ)を使う
    • transform: scale() + marginを使う
    1
    2

    View Slide

  33. 1. currentcolorを使う

    View Slide

  34. 1. currentcolorを使う

    View Slide

  35. 2. transform: scale()を使う




    <br/>.nes-icon.heart {<br/>width: 1px; height: 1px;<br/>box-shadow: /* 省略 */;<br/>transform: scale(2);<br/>margin: 0 32px 32px 0;<br/>}<br/>.nes-icon.heart.is-small {<br/>transform: scale(1);<br/>margin: 0;<br/>}<br/>.nes-icon.heart.is-medium {<br/>transform: scale(2);<br/>margin: 0 48px 48px 0;<br/>}<br/>.nes-icon.heart.is-large {<br/>transform: scale(3);<br/>margin: 0 64px 64px 0;<br/>}<br/>
    scaleでリサイズ
    ボックスサイズが変わらず
    要素が重なってしまうので
    margin(right, bottom)で調整
    参考: transform: scale()で要素が重なってしまったときのmarginのとり⽅
    https://kuroeveryday.blogspot.com/2019/02/margin-of-elements-resized-by-transform.html
    marignで調整した場合
    marign未使⽤の場合

    View Slide

  36. 2. transform: scale()を使う




    <br/>.nes-icon.heart {<br/>width: 1px; height: 1px;<br/>box-shadow: /* 省略 */;<br/>transform: scale(2);<br/>margin: 32px;<br/>}<br/>.nes-icon.heart.is-small {<br/>transform: scale(1);<br/>margin: 0;<br/>}<br/>.nes-icon.heart.is-medium {<br/>transform: scale(2);<br/>margin: 48px;<br/>}<br/>.nes-icon.heart.is-large {<br/>transform: scale(3);<br/>margin: 64px;<br/>}<br/>
    scaleでリサイズ
    ボックスサイズが変わらず
    要素が重なってしまうので
    marignで調整
    参考: transform: scale()で要素が重なってしまったときのmarginのとり⽅
    https://kuroeveryday.blogspot.com/2019/02/margin-of-elements-resized-by-transform.html
    box-shadowだけで
    8,843 bytesの削減

    View Slide

  37. ファイルサイズを60%も削減

    View Slide

  38. ハマりポイント②
    メンテできない?!

    View Slide

  39. メンテできない原因
    ⾊違うから直して!

    View Slide

  40. メンテできない原因
    ⾊違うから直して!
    box-shadow: 3px 2px #444,4px 2px #444,5px 2px #444,11px 2px #444,12px 2px
    #444,13px 2px #444,2px 3px #444,3px 3px,4px 3px,5px 3px,6px 3px #444,10px 3px
    #444,11px 3px,12px 3px,13px 3px #842300,14px 3px #444,1px 4px #444,2px 4px,3px
    4px #fff,4px 4px #fff,5px 4px,6px 4px,7px 4px #444,9px 4px #444,10px 4px,11px
    4px,12px 4px,13px 4px,14px 4px #842300,15px 4px #444,1px 5px #444,2px 5px,3px
    5px #fff,4px 5px,5px 5px,6px 5px,7px 5px,8px 5px #444,9px 5px,10px 5px,11px
    5px,12px 5px,13px 5px,14px 5px #842300,15px 5px #444,1px 6px #444,2px 6px,3px
    6px,4px 6px,5px 6px,6px 6px,7px 6px,8px 6px,9px 6px,10px 6px,11px 6px,12px
    6px,13px 6px,14px 6px #842300,15px 6px #444,1px 7px #444,2px 7px,3px 7px,4px
    7px,5px 7px,6px 7px,7px 7px,8px 7px,9px 7px,10px 7px,11px 7px,12px 7px,13px
    7px,14px 7px #842300,15px 7px #444,1px 8px #444,2px 8px,3px 8px,4px 8px,5px
    8px,6px 8px,7px 8px,8px 8px,9px 8px,10px 8px,11px 8px,12px 8px,13px 8px,14px
    8px #842300,15px 8px #444,2px 9px #444,3px 9px,4px 9px,5px 9px,6px 9px,7px
    9px,8px 9px,9px 9px,10px 9px,11px 9px,12px 9px,13px 9px #842300,14px 9px
    #444,3px 10px #444,4px 10px,5px 10px,6px 10px,7px 10px,8px 10px,9px 10px,10px
    10px,11px 10px,12px 10px #842300,13px 10px #444,4px 11px #444,5px 11px,6px
    11px,7px 11px,8px 11px,9px 11px,10px 11px,11px 11px #842300,12px 11px #444,5px
    12px #444,6px 12px,7px 12px,8px 12px,9px 12px,10px 12px #842300,11px 12px
    #444,6px 13px #444,7px 13px,8px 13px,9px 13px #842300,10px 13px #444,7px 14px
    #444,8px 14px #842300,9px 14px #444,8px 15px #444;

    View Slide

  41. View Slide

  42. メンテを可能にする⽅法
    • がんばる
    • Sassをうまくこと使う
    1
    2

    View Slide

  43. 2. Sassをうまいこと使う
    @mixin pixelize($size, $matrix, $colors) {
    $ret: "";
    @for $i from 1 through length($matrix) {
    $row: nth($matrix, $i);
    @for $j from 1 through length($row) {
    $dot: nth($row, $j);
    @if $dot != 0 {
    @if $ret != "" {
    $ret: $ret + ",";
    }
    $color: nth($colors, $dot);
    $ret: $ret + ($j * $size) + " “
    + ($i * $size) + " " + $color;
    }
    }
    }
    width: $size; height: $size;
    box-shadow: unquote($ret);
    }
    $colors: (#fff, #444, #f22426, #842300);
    $heart: (
    (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
    (0,0,2,2,2,0,0,0,0,0,2,2,2,0,0,0),
    (0,2,3,3,3,2,0,0,0,2,3,3,4,2,0,0),
    (2,3,1,1,3,3,2,0,2,3,3,3,3,4,2,0),
    (2,3,1,3,3,3,3,2,3,3,3,3,3,4,2,0),
    (2,3,3,3,3,3,3,3,3,3,3,3,3,4,2,0),
    (2,3,3,3,3,3,3,3,3,3,3,3,3,4,2,0),
    (2,3,3,3,3,3,3,3,3,3,3,3,3,4,2,0),
    (0,2,3,3,3,3,3,3,3,3,3,3,4,2,0,0),
    (0,0,2,3,3,3,3,3,3,3,3,4,2,0,0,0),
    (0,0,0,2,3,3,3,3,3,3,4,2,0,0,0,0),
    (0,0,0,0,2,3,3,3,3,4,2,0,0,0,0,0),
    (0,0,0,0,0,2,3,3,4,2,0,0,0,0,0,0),
    (0,0,0,0,0,0,2,4,2,0,0,0,0,0,0,0),
    (0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0),
    (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
    );
    .nes-icon.heart {
    @include pixelize($size, $heart, $colors)
    }
    うまいことbox-shadowを⽣成してくれるmixin アイコンの実装

    View Slide

  44. ハイライトでアイコンが浮かび上がる!

    View Slide

  45. 4. まとめ

    View Slide

  46. box-shadowはつよい

    View Slide

  47. 「CSS芸」は
    コードも美しくあるべき

    View Slide

  48. めざせ!
    box-shadowマスター

    View Slide

  49. 参考サイト
    CSS Backgrounds and Borders Module Level 3#box-shadow
    https://drafts.csswg.org/css-backgrounds-3/#box-shadow
    https://github.com/nostalgic-css/NES.css
    nostalgic-css/NES.css: NES-style CSS Framework
    https://kuroeveryday.blogspot.com/2018/10/draw-and-animate-pixel-art-using-only-css.html
    box-shadowを使ってCSSだけでドット絵を描き、アニメーションさせる
    https://kuroeveryday.blogspot.com/2019/02/margin-of-elements-resized-by-transform.html
    transform: scale()で要素が重なってしまったときのmarginのとり⽅

    View Slide