実は難しい! CSSのborder-radiusで実装した角丸を矩形からスムーズにアニメーションさせるテクニック
Post on:2025年3月25日
sponsorsr
CSSのborder-radiusで角丸を適用したボックスを拡大・縮小のアニメーションにするとき、最初は鋭角で、拡大したときには角丸になるようにしたいと思ったことはありませんか?
下記のデモはうまく機能していますが、角丸が汚かったり、最初が鋭角の矩形にならなかったり、角丸をスムーズにアニメーションさせる際に遭遇する問題点とその解決方法を紹介します。

Smoothly animating a border-radius
by Bramus!
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
ビュー遷移(View Transitions)は、スナップショットをアニメーション化するため、任意の要素を別の要素に変形させることができます。しかし、同じ要素を変形させる場合、スナップショットを使用すると思うように変形できないことがあります。
たとえば、下記のアニメーションをご覧ください。

角丸はborder-radiusで実装されており、これをトランジションさせる場合は、2つのスナップショットがフェードアウトするのではなく、角丸がない状態から角丸がある状態になるように変形されることを望むことがあると思います。
ビュー遷移による問題点
問題点は、ビュー遷移を使用して.cardをモーフィングさせる下記のデモで確認できます。.cardにはview-transition-nameがあり、border-radiusを0.25remから3remまでアニメーションさせています。また、それに合わせてfont-sizeやaspect-ratioなどのプロパティもアニメーションします。
See the Pen View Transitions with a Border Radius (1/3 – Problem) by Bramus(@Bramus)
on CodePen.
.card要素の角丸がどのようにモーフィングしているかに注目してください。ビュー遷移はスナップショットをフェードさせるため、border-radiusはきれいに変形されず、古い状態から新しい状態にフェードするだけです。
.card内のテキストにもview-transition-nameが設定されているので、.card自体とは別にキャプチャされていることにも注目してください。これは後で重要なポイントになります。
部分的な解決方法
この問題の解決策は、スナップショットを含む::view-transition-groupを操作することです。必要なことは::view-transition-groupにアニメーションを追加することです。上記のデモで言うと、border-radiusのアニメーションです。スナップショットがはみ出さないようにoverflowでclipすることをポイントです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@keyframes adjust-border-radius { from { border-radius: 0.25rem; } to { border-radius: 3rem; } } ::view-transition-group(card) { animation-name: -ua-view-transition-group-anim-card, adjust-border-radius; overflow: clip; background: #ccc; } :active-view-transition-type(shrink)::view-transition-group(card) { animation-direction: normal, reverse; } |
adjust-border-radiusのアニメーション(border-radiusのアニメーション)は、既存の-ua-view-transition-group-anim-cardアニメーションに追加します。新しく追加されたアニメーションは、カードが縮小されたときに反転され、ビュー遷移のタイプを使用してJavaScriptからCSSに伝えられます。
これで期待通りに変形されます。
See the Pen View Transitions with a Border Radius (2/3 – Workaround) by Bramus(@Bramus)
on CodePen.
変化する背景への対応
実は上記のデモでは、不正確さをカバーするために、背景色をグループに複製してごまかしています。.cardのbackground-colorも変化させると、この不正確さがはっきりと分かります。
下記のデモでは、角丸に特に注目してください。100%完璧ではないことが分かります。ついでに、カード内のテキストも変更しました。
See the Pen View Transitions with a Border Radius (2/3 – Workaround, with random text) by Bramus(@Bramus)
on CodePen.
ここでの解決策もアニメーションするプロパティを::view-transition-groupに移動することです。この場合はbackground-colorです。
実際に背景がトランジションの一部としてアニメーションするのを実際に見るには、トランジションの実行中はカードを構成するスナップショットを非表示にする必要があります。これは::view-transition-image-pair(card) to display: none;に設定することで可能です。カードのテキストは別にキャプチャされるため、これは安全に実行できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@keyframes adjust-group { from { background: #ccc; border-radius: 0.25rem; } to { background: lightblue; border-radius: 3rem; } } ::view-transition-group(card) { animation-name: -ua-view-transition-group-anim-card, adjust-group; } :active-view-transition-type(shrink)::view-transition-group(card) { animation-direction: normal, reverse; } ::view-transition-image-pair(card) { display: none; } |
実際の動作は、デモページをご覧ください。
See the Pen View Transitions with a Border Radius (2/3 – Workaround, with random text + background animation --fixed) by Bramus(@Bramus)
on CodePen.
要素の前景のスナップショットが背景のスナップショットからはみ出す場合は、border-radiusを複製してそのスナップショットの::view-transition-groupにclipする必要があります。
将来的には、ネストされたビュー遷移グループによってこの問題は解決されます。ネストは現在Chromeに実装されつつあります。
変化するボーダーへの対応
解決することが難しいのが、ボーダーのアニメーションです。その難しさは、スナップショットがboder-boxを使用して取得されることに由来します。つまり、boderを::view-transition-groupに複製する場合、スナップショットされた要素のbox-sizingに関係なく、そのbox-sizingがborder-boxに設定されていることを確認する必要があります。
この設定があるので、::view-transition-groupにボーダーを安全に複製し、そのキーフレームの一部としてアニメーションさせます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
@keyframes adjust-group { from { border-radius: 0.25rem; background: #ccc; border-width: 2px; } to { border-radius: 3rem; background: lightblue; border-width: 8px; } } ::view-transition-group(card) { box-sizing: border-box; border: 2px solid black; animation-name: -ua-view-transition-group-anim-card, adjust-group; } :active-view-transition-type(shrink)::view-transition-group(card) { animation-direction: normal, reverse; } ::view-transition-image-pair(card) { display: none; } |
実際の動作は、デモページをご覧ください。
See the Pen View Transitions with a Border Radius (2/3 – Workaround, with random text + border) by Bramus(@Bramus)
on CodePen.
終わりに
ビュー遷移の一部としてボーダーなどもスムーズにアニメーションさせるには、そのアニメーションを::view-transition-groupに複製すると解決します。最良の効果を得るには、ビュー遷移がアニメーションさせる要素の背景と前景を別々にキャプチャするようにします。これはそれぞれにview-transition-nameを付与することで可能です。
sponsors











