CSSグラデーションで三角を作ってアニメーションさせる

擬似要素とborderプロパティーを組み合わせてCSSで三角形を作る方法はかなり市民権を得ているように思う。ちょくちょく見かけるようになった。しかしこのテクニックには欠点がいくつかある。例えばbox-shadowがうまくつかないこととか。それ以外にもWebKitでCSS Transitionによるアニメーションが起こらないという欠点もある。それを回避するために三角を作る新たな方法を発明したという話。

View Demo: なんかしゅるしゅる動く奴

よくある感じでメニューを例に作った。左端に三角で背景を切り取る形にして、:hoverでしゅるしゅるっと上に三角を動かすようなアニメーションをさせる。まずは三角の作り方から。

枠線は使えない。transform()なども考慮したが擬似要素を使わないとなるとマークアップ依存になりそうなので諦めた。ということで最終兵器とも言えるCSSグラデーションでドット打ち的なことを行うテクニックを利用した。

縦方向にアニメーションさせたいので、うまいこと縦に繰り返しになるように三角を作ろうと頑張って考えると、以下のようなコードになる。

.test a {
  background-image:
    ...
    linear-gradient(top, rgb(221, 50, 47) 0, rgb(221, 50, 47)  3px, white  3px, white 29px, rgb(221, 50, 47) 29px, rgb(221, 50, 47) 32px),
    linear-gradient(top, rgb(221, 50, 47) 0, rgb(221, 50, 47)  4px, white  4px, white 28px, rgb(221, 50, 47) 28px, rgb(221, 50, 47) 32px),
    linear-gradient(top, rgb(221, 50, 47) 0, rgb(221, 50, 47)  6px, white  6px, white 26px, rgb(221, 50, 47) 26px, rgb(221, 50, 47) 32px),
    ...
  ;
  background-position:
    ...
     3px 0,
     4px 0,
     5px 0,
    ...
  ;
  background-repeat: repeat-y;
  background-size: 1px 32px;
}

それぞれのCSSグラデーションは背景色で塗り白に戻しもう一度背景色で塗るというもの。その白い部分を徐々に少なくしていくようにたくさん作り、それをbakcground-positionプロパティーで1pxずつずらして並べていく。すると徐々に白い部分が先細りになるわけなので三角形になる。大切なのはbackground-positionbackground-sizeプロパティーで、この2つのプロパティーでそれぞれのグラデーションが重ならないようにしながら縦方向は繰り返しになるように調節する。デモのケースでは16のCSSグラデーションで三角を完成させた。三角の向きを逆にする場合はグラデーションの並びをひっくり返せば良い。向きを90度変更したい場合はグラデーションのキーワードをleftからtopに変更するだけ(多分)。

アニメーションは背景を動かすことになるので、background-positionプロパティーをいじる。あとはtransition-durationプロパティーで等でアニメーションを調節するだけ。

.test a:hover {
  background-position:
    ...
     3px -320px,
     4px -320px,
     5px -320px,
    ...
  ;
  transition-duration: 1s;
}

これでデモのようなしゅるしゅる動く奴が完成。

汎用性は微妙。box-shadowが効かないのも同じだし、アンチエイリアスもかからないのでデモのようなシャッキリしたものにしか使えない。ただCSSグラデーションとアニメーションの組み合わせはそこそこ面白いと思う。何かにシャッターの様に重ねておいて、オンマウスで上下左右に開くみたいなのも多分出来る。クリックできないじゃん……と思ったそこのあなた、pointer-eventsプロパティーをご用意させていただいております。