💎

CSSのclip-pathプロパティによる矢印アイコンを実装してみる

2022/10/23に公開

矢印のアイコンを実装するには、画像ファイルやCSSのborderプロパティで実装することがほとんどです。
筆者も簡単な矢印であればborderプロパティ、複雑な形状や表現された矢印は画像(SVGやPNG)で実装していました。
しかし、CSSのclip-pathプロパティを使用することでも矢印を表現することできます。

clip-pathプロパティとは

clip-pathプロパティは形状用の関数を使用して、要素を切り抜く(クリッピング)ことができるCSSプロパティです。
CSS3が登場した時くらいから使用できたCSSプロパティですが、url関数でSVGによる切り抜きしかできなかったり、そもそも使用できなかったりとブラウザのサポートが十分ではありませんでした。
近年ではほとんどのブラウザ(最新版)で使用することができますし、IEは日本時間の2022年6月16日にサポートが終了したことで、IEをサポートする必要がなくなればIEのことを考えずにclip-pathプロパティを使用することができます。

良いところと残念なところ

良いところ

  • 要素(疑似要素を含む)1つ、CSSのみで簡単に作れる。
  • 色の変更もCSSで簡単に変更できる。
  • グラデーションが付けられる。
  • SVGの形状が概ねそのまま使える。
  • a要素自身にclip-pathプロパティを適用、あるいはa要素を内包した親の要素に適用すれば、リンクもその形状の範囲になる。
  • 同じ数のポイントがあればアニメーションすることができる。

残念なところ

  • 影や枠線が付けられない。
  • 複雑な形状だと形状を変更するのに大変。
  • path関数はパーセントでの指定はできない。

clip-pathプロパティの簡単な使い方

clip-pathプロパティは切り抜く形状の関数を使って値を指定します。

関数名 説明
inset 矩形(長方形・四角形)を定義します。
circle 円形を定義します。
ellipse 楕円形を定義します。
polygon 多角形を定義します。
path パスで形状を定義します。
直線や曲線を混在させて複雑な形状を定義することができます。

例えば次のコードは四角形のdiv要素を円形に切り抜きます。

<div class="sample"></div>
.sample {
	width: 100px;
	height: 100px;
	background-color: #333;
	clip-path: circle(50%);
}

clip-pathプロパティについての詳しい説明は参考リンクをご覧ください。

今回ご紹介する矢印アイコンは、polygon関数を使用したもの、path関数を使用したものをご紹介しています。
直線で表現できるものはpolygon関数、直線だけでなく曲線も表現したいものはpath関数を使用します。

参考リンク

CSS Masking Module Level 1 - W3C
clip-path - MDN

形状ごとの実装方法

三角形

borderプロパティでよく描かれる三角形の矢印は、polygon関数を使用して引数に3点の座標を指定すれば表現することができます。

引数の値をパーセントで指定することで、要素の幅や高さに応じて三角形の形もそれに応じた形にしてくれます。

線のような矢印

borderプロパティでよく描かれる線のような矢印は、三角形のときと同様にpolygon関数を使用することで表現することができます。

残念ながら線を表現するような関数はなく、独自に点の座標を計算して引数で指定しようとすると少々面倒ではありますが、座標の指定としては6点だけなので、書く量としては少なくて済むかなと思います。

計算が面倒とはいえ、上記の矢印は正方形(四角形)を45度回転させた表現なので、三角関数を用いた計算で例えば次のようなJavaScriptで算出してしまえば、簡単に指定することはできるかと思います。

X軸の座標 = 線の太さ * Math.cos(45 * (Math.PI / 180));
Y軸の座標 = 線の太さ * Math.sin(45 * (Math.PI / 180));

引数の値をパーセントで指定することで、要素の幅や高さに応じて矢印の形もそれに応じた形にしてくれます。

角が丸い線のような矢印

線のような矢印で角が丸くなった矢印は、path関数を使用することで表現することができます。

角を丸くする場合はベジェ曲線を用いて表現することができますが、線のような矢印と同様に点の座標を計算して引数で指定しようとすると、かなり面倒ではあります。
ベジェ曲線については詳しくは参考リンクをご覧ください。

path関数は残念ながらパーセントで指定することはできませんので、要素の幅や高さにあった座標をピクセル単位で指定する必要があります。

参考リンク

SVG Paths - W3C
パス SVG - MDN

鋭い矢印

尖ったような矢印は、同じようにpolygon関数を使用することで表現することができます。

4点の座標を指定するので、三角形と同じように簡単に表現することができます。
引数の値をパーセントで指定することで、要素の幅や高さに応じて矢印の形もそれに応じた形にしてくれます。

シャフト付き矢印

棒のようなシャフトの付いた矢印は、同じようにpolygon関数を使用することで表現することができます。

点の座標をしていする数は少し多いですが、座標自体は簡単な位置なので指定しやすいかなと思います。
引数の値をパーセントで指定することで、要素の幅や高さに応じて矢印の形もそれに応じた形にしてくれます。

アニメーション

clip-pathプロパティはanimationプロパティなどを組み合わせると、アニメーションすることができます。

@keyframesルールにはアニメーションするためのclip-pathプロパティを指定し、座標を変えることでアニメーションすることができます。
注意点としては、点(座標)の数が同じである必要があります。
数が揃っていないと正しくアニメーションすることができません。

SVGから簡単に指定

複雑な矢印を座標を自身で考えながら指定しようとすると面倒で、複雑になればなるほど時間もかかります。
そこで、IllustratorなどのソフトウェアからSVGを出力して、SVGのコードを使用することで簡単に表現することができます。
例えば次のようなSVGでは、path要素にあるd属性の値を、そのままCSSのpath関数の引数に指定することで、そのまま同じ表現が可能です。

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 55.01 100">
	<g>
		<path d="M5,100c-1.28,0-2.56-.49-3.54-1.46-1.95-1.95-1.95-5.12,0-7.07L42.93,50,1.46,8.54C-.49,6.58-.49,3.42,1.46,1.46,3.42-.49,6.58-.49,8.54,1.46L53.54,46.46c1.95,1.95,1.95,5.12,0,7.07L8.54,98.54c-.98,.98-2.26,1.46-3.54,1.46Z"/>
	</g>
</svg>
.arrow {
	clip-path: path("M5,100c-1.28,0-2.56-.49-3.54-1.46-1.95-1.95-1.95-5.12,0-7.07L42.93,50,1.46,8.54C-.49,6.58-.49,3.42,1.46,1.46,3.42-.49,6.58-.49,8.54,1.46L53.54,46.46c1.95,1.95,1.95,5.12,0,7.07L8.54,98.54c-.98,.98-2.26,1.46-3.54,1.46Z");
	height: 100px;
	aspect-ratio: 1;
	background-color: #333;
}

ただし、clip-pathプロパティ自体は複数の関数を指定することはできませんので、タグが分かれているようなものだと表現することは難しくなります。

最後に

矢印の形状も太さや大きさなどを変数でもたせたり、SCSSのミックスインや関数にするなどで簡単に作るような仕組みにするなどすると、より簡単に作ることができるようにする工夫もできるかと思います。
この記事を書いた時点ではまだDraftですが、CSS Values and Units Module Level 4で三角関数の実装が進められているので、将来的には組み合わせて使うことでより実装が簡単になるかもしれませんね。

CSS Values and Units Module Level 4 - W3C

Discussion