Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

box-shadow 使ってますか?

Slide 7

Slide 7 text

ここにも ここにも ここにも ここにも

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

これ全部 box-shadow

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

1. box-shadowの基礎

Slide 14

Slide 14 text

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];

Slide 15

Slide 15 text

影 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

Slide 16

Slide 16 text

2. box-shadowで○○する

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

テキストボックス Input text Input text .nes-input { box-shadow: /* 右 */ 4px 0 black, /* 左 */ -4px 0 black, /* 下 */ 0 4px black, /* 上 */ 0 -4px black; }

Slide 20

Slide 20 text

テキストボックス Input text Input text .nes-input { box-shadow: /* 右 */ 4px 0 black, /* 左 */ -4px 0 black, /* 下 */ 0 4px black, /* 上 */ 0 -4px black; }

Slide 21

Slide 21 text

ボタン 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の スタイルを調整する

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

box-shadowでドット絵を描く

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

⼤量のピクセル情報を持っている .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, }

Slide 28

Slide 28 text

⼤量のピクセル情報を持っている .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, } box-shadowだけで 2,713 bytes

Slide 29

Slide 29 text

サイズごとにbox-shadowの指定が必要 .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: /* 省略 */; } 4パターン分の box-shadow

Slide 30

Slide 30 text

サイズごとにbox-shadowの指定が必要 .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: /* 省略 */; } 4パターン分の box-shadow box-shadowだけで 2,713 bytes × 4 ※ 実際はoffset-x, offset-yの値が若⼲変わるので2,713 bytes×4とは異なる

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

1. currentcolorを使う

Slide 34

Slide 34 text

1. currentcolorを使う

Slide 35

Slide 35 text

2. transform: scale()を使う .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; } scaleでリサイズ ボックスサイズが変わらず 要素が重なってしまうので margin(right, bottom)で調整 参考: transform: scale()で要素が重なってしまったときのmarginのとり⽅ https://kuroeveryday.blogspot.com/2019/02/margin-of-elements-resized-by-transform.html marignで調整した場合 marign未使⽤の場合

Slide 36

Slide 36 text

2. transform: scale()を使う .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; } scaleでリサイズ ボックスサイズが変わらず 要素が重なってしまうので marignで調整 参考: transform: scale()で要素が重なってしまったときのmarginのとり⽅ https://kuroeveryday.blogspot.com/2019/02/margin-of-elements-resized-by-transform.html box-shadowだけで 8,843 bytesの削減

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

メンテできない原因 ⾊違うから直して! 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;

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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 アイコンの実装

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

4. まとめ

Slide 46

Slide 46 text

box-shadowはつよい

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

めざせ! box-shadowマスター

Slide 49

Slide 49 text

参考サイト 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のとり⽅