本気で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

6154244654c5f07cdf7c09da61bfe55f?s=128

ダーシノ

July 24, 2019
Tweet

Transcript

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

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

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

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

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

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

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

  9. None
  10. これ全部 box-shadow

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

  12. 話すこと • box-shadowの基礎 • box-shadowで◦◦する • ファミコン⾵UIをつくる • ドット絵を描く •

    box-shadow芸のハマりポイントと解決策 • ギガを消費する?! • メンテできない?! • まとめ 1 2 3 4
  13. 1. box-shadowの基礎

  14. box-shadowの基本構⽂ inset
 通常ボックスの外に表⽰される影を内側に表⽰する offset-x
 表⽰する影のX座標、正の数: 右側、負の数: 左側 offset-y
 表⽰する影のY座標 正の数: 下側、負の数:

    上側 blur-radius
 ガウスフィルタの半径 
 ゼロでは影がぼやけない 1px以上で影がぼやける spead-radius
 影の拡⼤/縮⼩ 正の数: 拡⼤、負の数: 縮⼩
 ゼロのときの影は親要素と同じサイズになる color
 影の⾊を指定する、指定しない場合はcurrentColorになる box-shadow: <inset> offset-x offset-y [blur-radius] [spread-radius] [color];
  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
  16. 2. box-shadowで◦◦する

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

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

  19. テキストボックス Input text <label>Input text</label> <input type="text" class="nes-input"> <style> .nes-input

    { box-shadow: /* 右 */ 4px 0 black, /* 左 */ -4px 0 black, /* 下 */ 0 4px black, /* 上 */ 0 -4px black; } </style>
  20. テキストボックス Input text <label>Input text</label> <input type="text" class="nes-input"> <style> .nes-input

    { box-shadow: /* 右 */ 4px 0 black, /* 左 */ -4px 0 black, /* 下 */ 0 4px black, /* 上 */ 0 -4px black; } </style>
  21. ボタン default :hover :active <button class="nes-btn">Button</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の スタイルを調整する
  22. box-shadowで◦◦する② ドット絵を描く

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

  24. ドット絵 <i class="nes-icon heart"></i> <style> .nes-icon.heart { /* 1ドットのサイズ */

    width: 1px; height: 1px; /* ドット絵 */ box-shadow: ..., ..., 2px 3px black,3px 3px red , ..., ..., 2px 4px red, 3px 4px white, ..., ...; } </style>
  25. 3. box-shadow芸の ハマりポイントと解決策

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

  27. ⼤量のピクセル情報を持っている <i class="nes-icon heart"></i> <style> .nes-icon.heart { width: 4px; height:

    4px; background: transparent; box-shadow: 12px 8px #444444, 16px 8px #444444, 20px 8px #444444, 44px 8px #444444, 48px 8px #444444, 52px 8px #444444, 8px 12px #444444, 12px 12px #f22326, 16px 12px #f22326, 20px 12px #f22326, /* 省略 */ 28px 56px #444444, 32px 56px #842300, 36px 56px #444444, 32px 60px #444444, } </style>
  28. ⼤量のピクセル情報を持っている <i class="nes-icon heart"></i> <style> .nes-icon.heart { width: 4px; height:

    4px; background: transparent; box-shadow: 12px 8px #444444, 16px 8px #444444, 20px 8px #444444, 44px 8px #444444, 48px 8px #444444, 52px 8px #444444, 8px 12px #444444, 12px 12px #f22326, 16px 12px #f22326, 20px 12px #f22326, /* 省略 */ 28px 56px #444444, 32px 56px #842300, 36px 56px #444444, 32px 60px #444444, } </style> box-shadowだけで 2,713 bytes
  29. サイズごとにbox-shadowの指定が必要 <i class="nes-icon is-small heart"></i> <i class="nes-icon heart"></i> <i class="nes-icon

    is-medium heart"></i> <i class="nes-icon is-large heart"></i> <style> .nes-icon.heart { width: 2px; height: 2px; box-shadow: /* 省略 */; } .nes-icon.heart.is-small { width: 1px; height: 1px; box-shadow: /* 省略 */; } .nes-icon.heart.is-medium { width: 3px; height: 3px; box-shadow: /* 省略 */; } .nes-icon.heart.is-large { width: 4px; height: 4px; box-shadow: /* 省略 */; } </style> 4パターン分の box-shadow
  30. サイズごとにbox-shadowの指定が必要 <i class="nes-icon is-small heart"></i> <i class="nes-icon heart"></i> <i class="nes-icon

    is-medium heart"></i> <i class="nes-icon is-large heart"></i> <style> .nes-icon.heart { width: 2px; height: 2px; box-shadow: /* 省略 */; } .nes-icon.heart.is-small { width: 1px; height: 1px; box-shadow: /* 省略 */; } .nes-icon.heart.is-medium { width: 3px; height: 3px; box-shadow: /* 省略 */; } .nes-icon.heart.is-large { width: 4px; height: 4px; box-shadow: /* 省略 */; } </style> 4パターン分の box-shadow box-shadowだけで 2,713 bytes × 4 ※ 実際はoffset-x, offset-yの値が若⼲変わるので2,713 bytes×4とは異なる
  31. None
  32. ギガ消費を抑える⽅法 • currentcolor(要素のcolorプロパティ)を使う • transform: scale() + marginを使う 1 2

  33. 1. currentcolorを使う <i class="nes-icon heart”></i> <style> .nes-icon.heart { /* ⼀番多く使われている⾊をcurrentcolorに設定する

    */ color: #f22326; box-shadow: /* 省略 */ 52px 8px 0 #444444, 8px 12px 0 #444444, 12px 12px 0, 16px 12px 0, 20px 12px 0, 24px 12px 0 #444444, 40px 12px 0 #444444, 44px 12px 0, 48px 12px 0, 52px 12px 0 #842300, /* 省略 */ 28px 56px 0 #444444, 32px 56px 0 #842300, 36px 56px 0 #444444, 32px 60px 0 #444444; } </style> #f22326とスペースで 8bytes分削減できる
  34. 1. currentcolorを使う <i class="nes-icon heart”></i> <style> .nes-icon.heart { /* ⼀番多く使われている⾊をcurrentcolorに設定する

    */ color: #f22326; box-shadow: /* 省略 */ 52px 8px 0 #444444, 8px 12px 0 #444444, 12px 12px 0, 16px 12px 0, 20px 12px 0, 24px 12px 0 #444444, 40px 12px 0 #444444, 44px 12px 0, 48px 12px 0, 52px 12px 0 #842300, /* 省略 */ 28px 56px 0 #444444, 32px 56px 0 #842300, 36px 56px 0 #444444, 32px 60px 0 #444444; } </style> #f22326の7bytes分 節約できる box-shadowだけで 704 bytesの削減
  35. 2. transform: scale()を使う <i class="nes-icon is-small heart"></i> <i class="nes-icon heart"></i>

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

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

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

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

  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;
  41. None
  42. メンテを可能にする⽅法 • がんばる • Sassをうまくこと使う 1 2

  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 アイコンの実装
  44. ハイライトでアイコンが浮かび上がる!

  45. 4. まとめ

  46. box-shadowはつよい

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

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

  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のとり⽅