これは、「ぼくがNES.cssから学んだこと(前編)」の後編になります。
前回のあらすじ
マリオはCSSで出来ている。
NESS.cssで行なっている描画の仕組み
「NES.css」でドット絵を表現していて、そのスタイルの中身をみてみるとcolor
とbox-shadow
を使っていることがわかりました。
しかし、color
は文字色を指定するのに使うし、box-shadow
と聞くとボタン等の矩形状に影をつけるのに使うのですが、どういう仕組みで表現しているのでしょうか?
box-shadow プロパティについて
前述したように、box-shadow
プロパティはその字の通り、矩形ベースで影を落とすことができます。
box-shadowプロパティ (MDN web docsより)
これによると、
(1) 最初の2つ数値指定で、X・Y方向に影のオフセット(位置をずらす)
(2) 3つ数値指定された場合、3つ目はぼかし半径
(3) 4つ数値指定された場合、4つ目は拡散半径
とのことで、それに色もパラメータに加えて影の色を指定したり、
カンマ区切りで複数の影を当てることができます。
/* (1) X方向に4px、Y方向に8px影をオフセット */
box-shadow: 4px 8px;
/* (2) X方向に4px、Y方向に8pxオフセットして、影にぼかしを2px分かける */
box-shadow: 4px 8px 2px;
/* (3) X方向に4px、Y方向に8pxオフセットして、影にぼかしを2px分、6px分拡散させる */
box-shadow: 4px 8px 2px 6px;
ここでキーになるのは、(1)のぼかしをかけないオフセット、そしてカンマで複数の影をつけるところにあります。
box-shadow を使った描画
では、先のbox-shadow
プロパティの仕様に則して、簡単なhtmlを作ってみます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Box Shadow Test</title>
<style>
div:after{
width: 20px; /* 影のサイズ。これを入れないと表示されない */
height: 20px; /* 影のサイズ。これを入れないと表示されない */
content: '';
display: block;
color: #f00; /* 影の色指定 */
box-shadow: 20px 20px, 40px 40px, 60px 60px;
/* 以下のように個別に色指定する書き方もOK */
/*box-shadow: 20px 20px #f00, 40px 40px #f00, 60px 60px #f00;*/
}
</style>
</head>
<body>
<div></div>
</body>
</html>
NES.cssのドット絵のように、ここではdivタグの擬似要素(after)に対しスタイルを適用しています。width
・height
で影のサイズを指定(他に表示されるにあたりcontent
とdisplay
の指定も必要)し、box-shadow
でX・Y方向のオフセットのみ・影をかけたい箇所を3箇所にするのにカンマ区切りにしています。
影の色はbox-shadow
でも設定できますが、一律同じ色にする場合実はcolor
プロパティで設定できます。個別に影を指定するならコメントアウトしているようにbox-shadow
プロパティ上で色を指定するのもOKです。
すると、ブラウザで表示させると、以下のような20px四方の四角形の連なりができています。
ちなみに、color
でなくbackground
で色指定を行うと、オフセットのない領域(上画像だと最左上の少し空いている部分)に色がつきます。これはbox-shadowがかかっていない、単純なafter擬似要素で作った領域を塗りつぶすようです(以下画面はbackground
で緑色を指定、右から2つ目のドッドをbox-shadow
で個別に色を塗ったもの)。
div:after{
width: 20px;
height: 20px;
content: '';
display: block;
color: #f00;
background: #0f0;
box-shadow: 20px 20px, 40px 40px #00f, 60px 60px;
/* box-shadow: 20px 20px #f00, 40px 40px #f00, 60px 60px #f00; */
}
これをいくつも影をつなげ時に色を変えることでドット絵的な見せ方をしているわけですね。
border
で三角形を作る要領にも近く、CSSはアイディア次第でプロパティ名に即した使い方以外のアプローチができます。
それ CSS Paint で出来...?
ますん。。というのが現時点の仕様を鑑みた個人的見解です。
CSS Paint API とは、JSを使ってグラフィックを背景画像を描ける仕様になっていて、Canvas描画と同じような記述で、かつ通常のCanvasと違ってcanvasタグ以外でも使えるのが特徴的です。
どんな背景でも自由に描ける! CSS Paint APIの使い方
これを使えば自由にドット絵を描けそうだと思ったものの、
2018年12月時点の対応ブラウザが以下になっています...
Chromeおよび息のかかったAndroid系ブラウザ以外全滅となっています。
これらのブラウザ限定であればそれでも良いのですが、サポートブラウザの広範性も求められる点から実用化されるのはまだ先になりそうです。
メリット・デメリット
color
とbox-shadow
を使った描画によって、考えられるメリット・デメリットを整理しました。
【メリット】
-
ドット絵画像のアセット精査
CSSとして書けるものであれば、画像ファイルとして用意するのは不要になりそうです。 -
リクエスト数の削減
上記に関連して、画像アセットファイルが減る事でリクエスト数を削減することができそうです。
画像ファイルは減らせる分には減らした方がいいですが、スタイルについてはリセットCSS含め最低限ファイルが必要なためその中に含められるならそうした方が良さそうです。 -
読み込み表示スピードの向上?
こちら仮説ではありますが、CSSで描画することから画像のリクエスト・描画に比べ比較的早く表示されるのではと推察しています。とはいえ、box-shadow
による処理負荷自体にもよります。 -
ユーザインターフェース(UI)要素のカスタマイズ
ドット絵にターゲットを置いてきましたが、これまで若干細かめのデザインをしたボタンとかは画像化する必要がありましたが、box-shadow
で点描できる点を活用して、CSSでより細かいデザインをカバーすることもできそうです。
【デメリット】
-
コードベース管理になる煩雑性
box-shadow
で座標指定するため、作るサイズや粒度によって長大な記述になりそうに思われます。また、作った絵に微調整が入った際の更新性も。逆にコードだからこそルールを知っていたら誰でも扱える利点も秘めています。 -
CSSファイルサイズの増大
こちらも作るドット絵のサイズやドットの粒度によって記述が増え、結果全体のCSSファイルのサイズが大きくなる点も考えられます。合わせて、それなら各ドット絵ごとにコンポーネント別に管理するのか、scss/stylusファイルとして分けて管理するのか、スタイルの管理方針も検討が必要になりそうです。 -
ベクターイメージには負ける
ドット絵や多少粒度の細かいグラフィックであればある程度できそうなものの、曲線の輪郭をジャギらないようにしたいのであれば、やはりSVGのようなベクターイメージになりそうではあります。
まとめ
CSSだけでちょっとしたドット絵や装飾を作るにあたり、color
とbox-shadow
が有効に思えました。
ただ、手打ちで作成・調整するのも大変なので、また近日番外編としてそのツールを作ってみようと思います(年内までに)。ツール名は「Shadow Paint Generator」(仮)で考えてます。