2019/07/31

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

2019年7月24日にUIT meetup vol.7 - 集まれ!(タブン)実務では使わないフロントエンド芸発表会に、CSS芸人として登壇した。

UIT meetupとは、ReactやVue.js、BFFなどのフロントエンド技術を扱った至ってマジメなイベントだ。そんな中、主催者から「次はテーマをかえてフロントエンド芸人を集めたイベントがしたい」とお誘いがあり、CSS芸人として参戦してきた。


当記事は、UIT meetupで発表した内容をスライドと共に文字起こししたものである。

※ 当記事には多くの画像が貼られているため、読み込みに時間がかかる可能性があります。

公式レポート記事: https://engineering.linecorp.com/ja/blog/uit-meetup-vol7/

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

CSS芸人、あらためbox-shadow芸人のダーシノです。今日は「本気でCSS芸やりたい人のためのbox-shadow講座」ということで、15分間box-shadowの話だけをみっちりしたいと思いますので、お付き合いください。


自己紹介

LINEさんとは新宿駅を挟んで反対側にある「さくらインターネット」から来ました、フロントエンドエンジニアのダーシノです。Twitterとかブログとかやってます。ブログには「仮想DOM実践入門」など真面目な記事から、「ブラック企業に殺されかけた話」といった闇深いものまでありますので、興味のある方はぜひ見てみてください。

CSS芸人としての活動はこんな感じです。CSS芸人として呼ばれてきたのですが、実はCSSがすごく苦手でそれを克服するために、笑い男や扇子、そろばん、マリオ、ブロックなどをCSSだけで作っていました。ちなみにこのそろばんは、ラジオボタンを兄弟セレクタで作られていてJavaScriptは一切使っていません。

リンク: https://bcrikko.github.io/css-collection/

あとNES.cssというプロダクトも作っています。

一言でいうと「ファミコン風のCSSフレームワーク」です。現在、GitHubではスター数も13,200を超えていて、今年4月時点でcss-frameworkトピックで世界ランク4位になっています。


box-shadow使ってますか?

ここから本題なのですが、この中でbox-shadow使ったことある方、いらっしゃいますか?(8〜9割くらい挙手)ほとんどの方、使われてますね。

box-shadowはいたるところで使われてます。例えばGoogleの検索フォームであったり、GitHubのポップアップ、Bulmaのトップに表示されているなんかよくわかんないおじさんの動画などにも、box-shadowが使われています。

地味で目立たないので意識しないとわかりづらいのですが、box-shadowはいたるところで使われています。

実は先ほど紹介したNES.css、このボタンやチェックボックス、アイコン、ピクセルアート、ドット絵

これらはすべてbox-shadowで作られています。

ということでいつもは目立たないbox-shadowにスポットライトを当てて、いろいろ紹介しようと思います。


目次

今日話すことは、box-shadowの基礎、box-shadowでファミコン風UIやドット絵をつくる方法、あとbox-shadow芸は結構ハマりポイントがあるのでその内容と解決策を紹介します。


1. box-shadowの基礎

まずはbox-shadowの基礎です。

box-shadowの基本構文はこのような感じです。使ったことがある人ならわかると思いますが、もしわからないようでしたらMDNのbox-shadowのページにチュートリアルとかジェネレータがあるので触っていただけると理解しやすいと思います。

各プロパティの説明です。
  • inset
    • 通常box-shadowの影は要素の外側に表示されるのですが、insetを使うことで要素の内側に影を表示させることができます。
  • offset-x
    • 表示する影の座標です。プラスの値なら右方向、マイナスなら左方向に表示されます。
  • offset-y
    • offset-xと同じで、プラスなら下方向、マイナスなら上方向に影が表示されます。
  • blur-radius
    • 影をぼかすためのガウスフィルタの半径です。通常はプラスの値を設定してぼかしたりするのですが、box-shadow芸では使いません。
  • spread-radius
    • 影の大きさを調整するものですが、こちらもbox-shadow芸では使いません。
  • color
    • 影の色を指定します。

と、6つの値があるのですが、box-shadow芸ではinset, offset-x, offset-y, colorのみ使います。

box-shadow芸をする上で抑えておきたいポイントが3つあります。
  1. box-shadowで作られる影のサイズは要素と同じです。そのため要素のwidth/heightを変更すると影の大きさも変わります。
  2. 影は要素の背面に表示されます。要素に重なる影は表示されません。
  3. box-shadowはカンマ区切りで複数の影を指定することができます。

この3つを抑えておけば、これから紹介するbox-shadow芸もわかると思います。


2. box-shadowで○○する

次は実際にbox-shadowを使ってbox-shadow芸をする方法を紹介します。

2-1. box-shadowでファミコン風UIをつくる

はじめにbox-shadowでファミコン風UIのつくり方を紹介します。

今日紹介するのはテキストボックスとボタンのつくり方です。

まず簡単なテキストボックスの方から紹介します。
先ほど紹介した3つのポイント覚えていますか?影は要素の背面に表示される、カンマ区切りで複数していできるというのがありました。テキストボックスをつくるには影を上下左右にちょっとだけ移動させます。そうすることでファミコンっぽい角張った輪郭を表示することができます。

もうちょっと詳しく説明すると、このテキストボックスの輪郭は4つの影から成っていて、1つの影が1辺を表現しています。サンプルコードの上から、offset-xに4pxなので右に4px、offset-xに-4pxなので左に4px、次はoffset-yに4pxなので右に4px、最後はoffset-yに-4pxなので左に4px、でこのように表示することができます。

次にボタンのつくり方です。これは先ほどのテキストボックスとほぼ同じです。違う部分はinsetを使ってボタンに立体感を表現しているところです。default、hover、active、それぞれの状態をinsetの値を調整することで、こんな感じの立体感を表現しています。見た目以上に簡単なしくみです。

参考スライド: 「CSSだけでウェブサイトをドット化する方法」でもう少し詳しく説明しています。

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

次にbox-shadowでドット絵を描く方法を紹介します。

このスーファミのコントローラやハート、スター、いいね、なにがしキャットのドット絵はすべてbox-shadowで作られています。

このハートのドット絵をもとに、もう少し詳しく説明します。
box-shadowの3つのポイントで、影は要素と同じサイズ、カンマ区切りで複数指定できるというのがありました。ですので、ドット絵の1ドットのサイズはもとの要素のwidth/heightで指定できます。そこからoffset-x/offset-yを使って、右下に向かって1ドットずつ、offset-xに2px、offset-yに3pxの位置に黒い影を表示する、という感じで書いていくと、このようなドット絵を描くことができます。


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

box-shadowによるCSS芸をいくつか見ていただきましたが、実はbox-shadow芸にはハマりポイントがいくつか存在します。その中から特に重要な2つと

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

最初のハマりポイントは「ギガを消費する」です。

box-shadowでドット絵を描く方法を見ていただいたと思うのですが、box-shadowには大量のピクセル情報が含まれています。
ハートの左上の黒いドットを表示するには、1ドットのサイズが4pxなので、offset-xが12px、offset-yが8px、colorが#444444となって、スペースも合わせると、1ドット表現するだけで16バイトも必要になります。

ですので、この16x16のハートのドット絵を描くと、box-shadowの値だけで2,713バイトになります。

2〜3年くらい前にhyperappというフロントエンドのフレームワークがちょっとだけ湧きましたよね?ご存知ですか?あれが当時1KBだと言っていたので、それと比較すると、このハート1個は3-hyperappに相当します。狂気の沙汰ですよね。

闇はまだ続きます。
アイコンのサイズを変更したい場合、先ほど紹介したとおりbox-shadowの1ドットのサイズと座標(offset)が密接に関係しているので値の再利用ができません。そのため、小さい、普通、中くらい、大きいという4つのパターンを用意するには、そのサイズ分box-shadowが必要になります。

4パターンのサイズを用意すると、単純計算で11KB以上になります。ですので、4パターンのハートのドット絵は、11-hyperappに相当します。

これヤバいですよね?

そこでギガの消費を抑える方法を紹介します。方法はいくつかあるのですが、今回は特に効果的な2つの方法を紹介します。

ひとつはcurrentcolorを使う方法です。
box-shadowの仕様で、colorの値を省略した場合は、その要素のcurrentcolorを参照します。ですので、このドット絵で一番多く使われている色(赤)をcurrentcolorにすることで、box-shadowの値から赤のカラーコードを削除することができます。
要素のcolorプロパティに赤を指定することで1ドットにつき、カラーコードとスペースで8バイト分削減できます。

この対策で、704バイトの削減になります。

次にドット絵のサイズを変更したい場合です。
先ほど言ったとおり、box-shadowの値はサイズと座標が密接に関係しているため再利用できません。その代わりにベースとなる1つのドット絵を作成し、それをtransform: scaleでリサイズすることで、3パターン分のbox-shadowを丸っと削除できます。
注意点としてscaleでサイズを変更した場合、要素の左上を原点に拡大されるため、場合によってはドット絵同士が重なってしまいます。そのためmarginで調整する必要があります。

参考記事: transform: scaleで要素が重なったときのmarginのとり方を詳しく解説しています。


currentcolorを使って、scaleでリサイズすることで、なんと8,843バイトも削減することができます。

この2つの対策を行ったことで、ver1.0.0ではファイルサイズが616KBあったNES.cssも、ver2.0.0では約60%のダイエットに成功し、256KBまで軽くすることができました。


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

ドット絵の描き方見ていただいてわかるかと思いますが、メンテできません。

このハートのドット絵で一部色が違っているので修正してくれ、と言われたとします。見た目的には一目瞭然で簡単そうですよね。ですが、devtoolsとかで実際にCSSを見てみると…。

こんなです。

これヤバいですよね?

ということで、メンテ可能にする方法ですが、ひとつは目grepで「がんばる」ことです。ですが、我々プログラマは「怠惰」ですので、極力がんばりたくないですよね。
なので、Sass、プリプロセッサをうまいこと使って解決します。

左側のコードが、二次元配列で描かれたドット絵とカラーパレットを受け取ってうまいことbox-shadowを生成するmixinです。もちろんfunctionでも大丈夫です。
右側がドット絵の実装部分です。カラーパレットを配列として定義し、そのindexを用いてドット絵を描いたものです。黒背景なのでわかりづらいかもしれませんが、これをVSCodeやIDEなどで見ると…。

こんな感じに、ハイライトのおかげでアイコンが浮かび上がって見えます。ですので、どこを修正すればよいかすぐわかると思います。


4. まとめ


最後にまとめです。

box-shadowは一般的な使われ方以上にさまざまな使いみちがあります。今回はファミコン風に焦点を当てましたが、box-shadowはつよいのでアイデア次第でいろんなことが実現できます。

あと、CSS芸はビジュアル面ばかり注目されがちなのですが、プログラマである以上、コードも美しくあるべきだと思います。ですので、ファイルサイズを削減したり、メンテナブルなコードを書いたりすることも含めて「CSS芸」だと思います。

今日紹介したことが、私のbox-shadow芸のすべてです。見た目以上に簡単にできますので、ぜひ皆さんも挑戦してみてください。
めざせ!box-shadowマスター!ということで発表を終わります。ありがとうございました。


参考サイト




関連記事






以上

written by @bc_rikko

0 件のコメント :

コメントを投稿