いま本家サイトの改装中で、デザインを考えてました。そしたら border-image-slice という素敵なものを見つけたので、使ってみました。

  1. トンチキな例
  2. シンプルな例

トンチキな例

↓こんな感じの、なんか凄まじくトンチキな画像『border-image.gif』があるとします。

border-image.gif

トンチキですね。この記事書くために適当に作りました。

まず、この画像をボーターにするために寸法を測ります。(※小さいので拡大してます)

拡大してます
拡大してます

これを寸法通りに border-image-slice して、画像ボーダーにしたものが以下です。

うわああああああ!!!

HTML
<div class="tonchiki">うわああああああ!!!</div>
CSS
.tonchiki {
	box-sizing: border-box; /* borderの太さ込みで 300 * 300 になるように */
	width: 300px;
	height: 300px;
	color: #fff;
	border-style: solid;
	border-width: 44px 28px 20px 40px;
	border-image-source: url('border-image.gif');
	border-image-slice: 44 28 20 40 fill;
	border-image-repeat: repeat;
	image-rendering: pixelated;
}
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
	/* 高解像度対応 */
	.tonchiki {
		border-image-source: url('border-image@x2.gif'); /* 同じ画像を縦横2倍に拡大したもの */
		border-image-slice: 88 56 40 80 fill;
	}
}

以下、関係ある設定値を一つずつ説明します。

border-style

ボーダーの見た目です。いつも border: 1px solid #fff; とか書く時の、solid にあたる部分です。

画像ボーダー自体とは無関係ですが、画像がリンク切れになってたり、画像ボーダーに対応していないブラウザで見た時にはこれが適用されます。MDNによると仕様上は必須らしいので、設定しておきます。

border-width

ボーダーの幅 (太さ) です。いつも border: 1px solid #fff; とか書く時の、1px にあたる部分です。

4つ数字を並べた場合は 上 → 右 → 下 → 左 の順に設定されます。なので上述したように画像の寸法を測って、時計回りに書きます。

border-image-source

ボーダーに使う画像のURLを指定します。

border-image-slice

ボーダーに使う画像を、左上・上辺・右上・右辺・右下・下辺・左下・左辺・真ん中の9つのパーツに切り出すための設定です。

通常は border-width と同じ数字を設定すれば大丈夫です。ここは px をつけちゃダメです。どう考えても px だと思うんですけど。

真ん中のパーツは、fill キーワードを指定した場合のみ、真ん中を塗りつぶすために使われます。ここでは fill を指定しているので、画像ボーダーの内側に真ん中のパーツ (灰色の部分) が使われてます。

border-image-repeat

要素の大きさが元の画像と異なる場合、かどっちょ以外のパーツをどう表示するかの設定です。

このサンプルでは repeat を指定したので、足りない分は元の画像をぴったり敷き詰めて表示されてます。これ以外の設定値 (stretch とか) だと画像が引き延ばされる場合があるので、ドットをそのまま生かしたい場合は repeat が無難です。

その他の設定値はMDNの border-image-repeat のページを参照してみてください。

ちなみに border-image-repeat: repeat stretch みたく2つ同時に指定した場合、1つ目が左右方向、2つ目が上下方向に適用されます。「左右は繰り返したいけど上下は伸ばしたい」なんてのが可能です。

image-rendering

画像ボーダーと直接の関係はありません。ここでは pixelated を指定してます。

pixelated を指定すると、描画時に画像が引き延ばされてもぼやけなくなります。画像ボーターに限らず、ドット絵を素材に使う場合は便利なプロパティです。

でも「border-image-repeatrepeat ならそもそも引き延ばされないんじゃないの??」って感じですが、少なくともChrome (72.0.3626.96) では border-image-repeatrepeat でも pixelated してないと微妙にぼやけるようです。

なので、ボーダーの画像がぼやけてほしくない場合は、とりあえず指定しておくのが良いと思います。

……が、後日確認したところ、border-image-repeatround だとこれを指定してもぼやける場合があるような気がします。詳細は不明ですが、過信はできないのかも。

高解像度対応

device pixel ratio が1ではない端末のために、メディアクエリで大きい画像を使うように指定することがあると思います。その場合は画像の大きさが変わってしまうので、一緒に border-image-slice を指定し直してあげる必要があります。

ここでは device pixel ratio が2の端末のために、縦横2倍の画像を border-image@x2.gif として用意しました。なので border-image-slice も元の値のちょうど2倍を指定してます。

実際のボーダーの幅は変わらないので、border-width を変更する必要はありません。

シンプルな例

シンプルな例も用意しました。画像は↓こんなです。

border-image.gif

黒丸にしか見えません。これは1ドットが 4px * 4px で、縦横7ドット (28px * 28px) です。

これを上下左右とも 12px のところでスライスして fill したものが以下です。

うわああああああ!!!

HTML
<div class="simple">うわああああああ!!!</div>
CSS
.simple {
	box-sizing: border-box;
	width: 300px;
	height: 300px;
	color: #fff;
	border-style: solid;
	border-width: 12px;
	border-image-source: url('https://note.kiriukun.com/public/files/entry/20190214-border-image-slice/border-image-2.gif');
	border-image-slice: 12 fill;
	border-image-repeat: repeat;
	image-rendering: pixelated;
}
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
	.simple {
		border-image-source: url('https://note.kiriukun.com/public/files/entry/20190214-border-image-slice/border-image-2@x2.gif');
		border-image-slice: 24 fill;
	}
}

なお、この例だと黒く塗って fill しなくても border-image-outset を使えば background-color で好きな背景色にできそうですが、話が逸れるのでやりませんでした。すみません。