SVGでborderのアニメーション。

〽️borderを動かしたい! 〽️座標空間を一致させる。 〽️SVGでborderを実装。 〽️border-radius。 〽️hoverでアニメーション。 〽️スタイリングも自在。 〽️こっからはじまる。






基本code。


<div> <svg width = "100%" height ="100%"> bb<rect width = "100%" height = "100%" bb fill = "none" stroke = "〇〇" stroke-width = "〇〇"/> </svg> </div> <style> div { position:relative; } div svg { position:absolute; pointer-events:none; } </style>


borderを動かしたい!


こんにちは、「ふ」です。
HTML要素のborder(枠線)をアニメーションさせたい!と思い立ちました。

しかしながら。

現状のCSSに用意されているプロパティだけでは、如何せん、力不足。
〜borderのデザインに取り組んだことのある方は、そんな物足りなさを感じているのではないでしょうか。



borderだけSVGで作る。

それならば、枠線をSVGで作ってしまおうという考えに至ります。
HTML要素はそのまま、枠線だけSVGにして、双方のレイアウトを調和させる。
SVGなら、スタイリングやアニメーションは思いのままです。

今回はHTML要素とSVG領域、2つの座標系を一致させることで、「動くborder」を実装してみたいと思います。

svgの線をアニメーションさせる方法は、こちら⬇︎の記事で詳しく紹介しています。

SVG、線を描くアニメーション。

2020.09.23
〽️ 破線のプロパティをつかいます。


座標空間を一致させる。


SVGのviewBox属性は、「画像としての可視範囲」を座標的に「どこからどこまでにするか」を指定するものです。
⬆︎の例では、「水平方向0〜4、垂直方向0〜3」に可視範囲を指定しています。

viewBox指定をするということは同時に、「画像の縦横比を固定」する作業でもあります。
縦横比の一致しない親要素とSVG領域を組み合わせた場合、その「縛り」が作用するため、領域からはみ出したり、余白が生じてしまいます。

それでは。
親要素いっぱいにviewBox指定のないSVG領域を配置するとどうなるのでしょうか。
画像自身は縦横比の情報を持ち合わせていないため、幅と高さは親要素に依存することに成増。

つまり、親要素の縦横比に合わせてSVG領域が変形を起こします。

さらに、そのSVG領域いっぱいの長方形を配置した場合。
この長方形は親要素である、SVG領域と同じ幅&高さで描画されます。

親要素いっぱいの長方形を「塗り:なし 線:表示」とすると、これはもう「親要素のborder(枠線)」として成り立ちますね♪
この長方形は、祖父母である<div>の幅と高さに合わせて、変形してくれます。

〜次のセクションで実装してみましょう。

SVGでborderを実装。


サンプルHTML/CSS。


<div id = "soto"> <p>border_animate</p> </div> <style> #soto { width:60%; margin:0 auto; background-color:bisque; } #soto p { padding:2em; font-weight:bold; } </style>

実際にコードを書いていきましょう。
<div>領域の中に<p>を使ったテキストを置いたもの。テキトーにCSSを指定しました。




border_animate

現在の状態⬆︎です。
SVGで枠を追加していきます。

<div id = "soto"> 「「1<svg width = "100%" height = "100%">」」 bb<rect bbwidth = "100%" bbheight = "100%" bbfill = "none" bbstroke = "gray" bbstroke-width = "5" bb/> 「「1</svg>」」 <p>border_animate</p> </div>




border_animate

<div>の中に、<svg>と<p>が上から順番に配置されました。
<div>と<svg>のpositionをrelativeとabsの関係にして、重ね合わせましょう。

<style> #soto { width:60%; margin:0 auto; background-color:bisque; 「「1position:relative;」」 } #soto svg { 「「1position:absolute; top:0;」」 } </style>




border_animate

<svg>の中に配置した長方形が、<div>領域と重なりました。
<div>の幅や高さが変わっても、borderのレイアウトはそれを 追随します。←やってみましょう。

#soto { 「「1width:90%;」」 }




border_animate

<div>の幅を90%としたところ、それに合わせて長方形も広がりました。
これでborderとして使えそうですね ♪

border全体を表示。

下準備として、あと2つやることがあります。

svg要素のstroke-width(線幅)は、線の中心(アウトライン)を起点に広がっていきます。

現在長方形はsvg領域いっぱいに広がっています。stroke-widthを「5」としているのですが、長方形は親要素のsvg領域に支配されているため、内側の線幅は表示されているのですが、svg領域の外側は見えなくなってしまっています。

overflowプロパティで、svg領域の縛りを開放しておきましょう。

#soto svg { position:absolute; top:0; 「「1overflow:visible;」」 }




border_animate

線幅の外側部分も表示されました。

クリックできるようにしておく。

borderを付けるということは、「ユーザにアクションを起こしてもらいたい要素」が含まれていることも多々あるでしょう。
しかし。今の状態では<div>には最前面に<svg>領域が重なっているため、背面に<button>などの要素があったとしてもクリックできない状態になっています。

前面のsvgのpointer-eventsを無効にすることで、背面にある要素のクリックを有効にしましょう。

#soto svg { position:absolute; top:0; overflow:visible; 「「1pointer-events:none;」」 }

border-radius。


ちょっと気になること。

CSSでborderを指定するとき、角丸(border-radius)を付けることは多々あります。
<div>領域に角丸を付けたい。その場合、SVGで作ったborderはどのようにすればいいのでしょうか?

#soto { ...... 「「1border-radius:40px;」」 }




border_animate

まづは<div>領域に40pxの角丸を付けました。
じつは。<rect>にも同じ指定をするだけでいいんです。

viewBox指定のないSVGを配置すると、その座標空間はHTMLと同一のものと成増。
HTML要素の最小単位は「1px」ですよね。現在のSVGの単位座標の大きさも同じく「1px」となっています。

<rect bbwidth = "100%" bbheight = "100%" bbfill = "none" bbstroke = "gray" bbstroke-width = "5" bb「「1rx = "40px"」」 />

<rect>要素の角丸は、rx属性で指定することができます。



border_animate

親要素と同じ角丸を付けることができました。

hoverでアニメーション。


それではアニメーションさせていきます。
今回はhoverイベントに対して、要素のborderが「くるん」と描画されるものを作ってみました。

「線」のアニメーションなので、例によってstroke-dasharrayとstroke-dashoffset、2つのプロパティを利用します。

#soto svg rect { transition:1.7s; stroke-dasharray:400%; stroke-dashoffset:400%;「「1 ....①」」 } #soto:hover svg rect {「「1 ....②」」 bbstroke-dashoffset:0%; }


① 領域の幅と高さを厳密に取得して破線の長さを指定してもいいのですが、今回はちょっと省略。400%とすれば、だいたい1周分の破線に成増。

② svg自体には「pointer-events:none」を指定したため、hoverを反応させることはできません。親要素の<div>に対してhoverイベントを 指定します。その上で、rectにアクセスしてstroke-dashoffsetを変化させています。

この、

element:hover child child { }

擬似クラスのhoverから子要素をたどっていくセレクタの記述。便利なのでついでに覚えておきましょう。

完成。




border_animate

完成品⬆︎です。
実際にhover(スマホの場合はタップ)するとborderが描かれます。




border_animate

こちらは<div>のbackground-colorをなしにしたもの。
これはこれで使えそうですね。お疲れ様でした!

スタイリングも自在。


最後までお読みくださり、ありがとうございました。
今回のSVGを使ったborder(枠線)。<div>要素とは独立した<svg>要素なので、スタイリングの自由度もCSSのborderに比べて広範囲です。

例えば。

#soto svg { ...... overflow:hidden; }




border_animate

<div>、<rect>ともに角丸をつけておき、<svg>には敢えてoverflowを非表示にする。
と、⬆︎のような「外周部はradiusなし、内周部はradiusあり」が表現できます。




#soto svg rect { filter:blur(3px); }




border_animate

今度は<rect>にぼかしフィルターを付けてみました。
ちょっと雰囲気が変わりましたね。

ほかにもたくさんアレンジできそうです。皆さんのほうでも、ぜひ試してみてください。

ではまた〜 ♪



HSL変換を使った配色や色指定。

2021.09.24
配色パターンを秒作。


CSSアニメーション、中間テスト。

2021.06.03
基本編を終えたらチャレンジしましょう。












「ふ」です。

swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。