CSSのinterpolate-sizeプロパティを使ったアニメーションの許可
昨今はCSSのみで様々なアニメーションが実装できるようになりましたが、コンテンツ量が変わると多少の調整が必要になる場合もあります。
あらかじめ決まっているコンテンツの要素の幅をアニメーションさせる場合は、transitionプロパティやwidthプロパティの組み合わせで、widthプロパティには決まった数値を指定することでアニメーションが実装できます。
しかし、コンテンツ幅が変化する可能性のある要素をアニメーションさせる場合は、CSSのみでは実装するのが難しいです。
コンテンツ幅が変化する可能性のある要素には、JavaScriptを使って要素の幅を取得してアニメーションさせるなど、少し手の込んだプログラムが必要になります。
ただ、その問題もCSSのinterpolate-sizeプロパティが解決してくれるでしょう。
CSSで「interpolate-size: allow-keywords;」を指定することで、widthプロパティのauto、min-content、max-contentなどの値をCSSアニメーションに適用することができます。
つまり、コンテンツ量に応じた幅に対してアニメーションが実装できるようになります。
「interpolate-size: allow-keywords;」は親要素以上で指定する必要がありますが、様々な要素で必要になることも考えると、ルート要素(:root)に指定するのがベストでしょう。
CSS
:root {
interpolate-size: allow-keywords;
}
気になるWebブラウザのサポート状況ですが、
2024年10月現在時点では、Google Chrome 129以降のみサポートしています。
Can I use (interpolate-size)
https://caniuse.com/?search=interpolate-size
Google Chromeがサポートされれば、ChromiumベースのMicrosoft Edgeなどもサポートされるので、あとはSafariやFirefoxのサポートを待つのみとなります。
interpolate-sizeプロパティを使ったアニメーションの実装
ここからは、interpolate-sizeプロパティを使ったアニメーションの実装を、サンプルを交えて確認していきます。
サンプルとして、お問い合わせ用のアイコンボタンの動作で見ていきます。
HTMLは以下のような構造を構築します。
HTML
<nav class="contact-nav">
<ul>
<li>
<a href="#">
<img decoding="async" src="data:image/svg+xml;base64,PCEtLT94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPy0tPgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTguMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+Cgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9Il94MzJfIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHN0eWxlPSJ3aWR0aDogNjRweDsgaGVpZ2h0OiA2NHB4OyBvcGFjaXR5OiAxOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Cgkuc3Qwe2ZpbGw6IzRCNEI0Qjt9Cjwvc3R5bGU+CjxnPgoJPHBhdGggY2xhc3M9InN0MCIgZD0iTTAsNjR2Mzg0aDUxMlY2NEgweiBNMjY0LjEzMiwyNjYuNzY1Yy0xLjk5NiwxLjY4OC00Ljk1LDIuNjU3LTguMSwyLjY1N2MtMy4xNTMsMC02LjA5OC0wLjk2NC04LjA4My0yLjY0MgoJCUw0OCwxMTJoNDE2TDI2NC4xMzIsMjY2Ljc2NXogTTk1LjExLDE5NC4zMDZsNjkuNTE4LDU4Ljk1NEw0OCwzNjhWMTYwTDk1LjExLDE5NC4zMDZ6IE0xOTkuMjg4LDI4Mi42NTJsMTYuMzUsMTMuODY2CgkJYzEwLjgzNiw5LjIxNSwyNS4xNjksMTQuMjg4LDQwLjM2MSwxNC4yODhjMTUuMjM2LDAsMjkuNTg4LTUuMDcxLDQwLjQxOC0xNC4yODJsMTYuMzIxLTEzLjg0Nkw0MzIsNDAwSDgwTDE5OS4yODgsMjgyLjY1MnoKCQkgTTM0Ny4zOTQsMjUzLjI4Mkw0NjQsMTYwdjIwOEwzNDcuMzk0LDI1My4yODJ6IiBzdHlsZT0iZmlsbDogcmdiKDc1LCA3NSwgNzUpOyI+PC9wYXRoPgo8L2c+Cjwvc3ZnPgo=" alt="mail">
<span class="nav-text">Mail</span>
</a>
</li>
<li>
<a href="https://bsky.app/profile/akirao.bsky.social" target="_blank" rel="noopener noreferrer">
<img decoding="async" src="data:image/svg+xml;base64,PCEtLT94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPy0tPgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTguMS4xLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+Cgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9Il94MzJfIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHN0eWxlPSJ3aWR0aDogNjRweDsgaGVpZ2h0OiA2NHB4OyBvcGFjaXR5OiAxOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Cgkuc3Qwe2ZpbGw6IzRCNEI0Qjt9Cjwvc3R5bGU+CjxnPgoJPHBhdGggY2xhc3M9InN0MCIgZD0iTTQ0Mi41MzksNzMuOTQ2QzM5Ny43LDM2LjAxOCwzMzMuNTksMTMuODYzLDI1NS4yMDUsMTMuODgxYy03NC4zOTgsMC0xMzcuOTA1LDIwLjk4MS0xODMuMzM3LDU4LjQxMQoJCWMtMjIuNjkyLDE4LjY4Ni00MC43NTgsNDEuNDkxLTUzLjA2LDY3LjQyOEM2LjQ5OCwxNjUuNjQ4LTAuMDEsMTk0LjY0MSwwLDIyNS40MjJjLTAuMDE4LDM3LjIxNCw3Ljc3Nyw3MS41ODYsMjMuNTExLDEwMS41NzcKCQljMTUsMjguNjY0LDM3LjI5OCw1My4wNCw2NS42OTksNzIuMTAzYy02LjcxNSwyOC4yNjktMTYuMTQ4LDY4LjY3LTE2LjE0OCw2OC42ODljLTAuNDMyLDEuODE1LTAuNjU4LDMuNzA2LTAuNjQ4LDUuNjI0CgkJYy0wLjAxOSw3LjU5LDMuNTI2LDE0Ljg5Niw5LjY2OCwxOS42MDhsMC4wMzgsMC4wMjhsMC4wMDksMC4wMWM0LjQwMiwzLjM0OCw5LjcwNiw1LjA2LDE1LDUuMDZjMy45ODcsMCw4LjAzMS0wLjk2OSwxMS42OC0yLjkzNAoJCWwwLjM2Ny0wLjE4OGwwLjM1Ny0wLjIxNmMwLjAxLTAuMDEsNS4wNjktMy4wMSwxMi44NTYtNy42MThjMTEuNjcxLTYuOTAzLDI5LjQzNS0xNy40MDcsNDUuMjkxLTI2Ljc0NQoJCWM3LjkxOS00LjY2NSwxNS4zNjYtOS4wMzgsMjEuMzItMTIuNTA4YzUuOTE2LTMuNDYsMTAuNDc3LTYuMTA0LDEyLjE2LTcuMDM0bDAuMDg1LTAuMDQ3bDAuMTEzLTAuMDY2CgkJYzIyLjEtMTIuNTI2LDM5LjcwNC0xNC42MzMsNTMuODQ5LTE0LjcwOGM1OC42OTItMC4wODUsMTIxLjIxMi0xMS40NjQsMTcxLjEzLTQyLjYyYzI0Ljg5NC0xNS42MDIsNDYuNTYxLTM2LjQxMyw2MS44MDYtNjMuMDU2CgkJYzE1LjI3Mi0yNi42MjQsMjMuODg2LTU4Ljg1MywyMy44NTgtOTYuMTZDNTEyLjEyMiwxNjUuNTQ0LDQ4Ny40MTcsMTExLjc4LDQ0Mi41MzksNzMuOTQ2eiBNNDU0LjcwOSwzMDEuMjQKCQljLTguODEyLDE1LjM3NS0yMC4zNywyOC4zMTYtMzQuMjMyLDM5LjI4MmMtMjAuNzc0LDE2LjQyOS00Ni44NjIsMjguMjg4LTc1LjQ3OSwzNS45MzRjLTI4LjU5OCw3LjY2NC01OS42NDIsMTEuMDg4LTg5Ljc5MiwxMS4wNzgKCQljLTE4LjUxNy0wLjA3NS00NC4zNzksMy40MTQtNzIuNzYxLDE5LjY4M3YtMC4wMDljLTMuMTQsMS43NDktMTAuMTI4LDUuODIyLTE5LjM0NSwxMS4yMTkKCQljLTEzLjIyMiw3Ljc1OS0zMC42MiwxOC4wMTktNDUuMTUsMjYuNjE0YzMuNTQ1LTE1LjA5NCw3LjY1NS0zMi41NzYsMTAuNzMtNDUuNDEzdi0wLjAxOWMwLjUwOS0yLjE0NCwwLjg3NC00LjQ2OCwwLjg4NC03LjExCgkJYzAuMDM3LTMuNzI0LTAuOTIyLTguMjY2LTMuMDc1LTEyLjA0NmMtMS41OS0yLjgzMi0zLjYzOS01LjA2LTUuNDM2LTYuNTgzYy0yLjczNi0yLjI4NS00Ljc5Ni0zLjI3My01Ljk0NC0zLjkwM2wtMS4xNTctMC41OTIKCQlsLTAuMTMxLTAuMDc2Qzg4LjY2NSwzNTMuMDk1LDcwLjE2NiwzMzIuOTcsNTcuNjMsMzA5LjExYy0xMi41MTctMjMuODk2LTE5LjEtNTEuNzgtMTkuMTEtODMuNjg5CgkJYzAuMDEtMjUuNDAxLDUuMjk1LTQ4LjUyNiwxNS4wODUtNjkuMTg4YzE0LjcxOC0zMC45NCwzOS42NjgtNTYuNjA0LDczLjc4Ni03NC44OTZjMzQuMDkxLTE4LjI1NCw3Ny4zOTgtMjguOTM3LDEyNy44MTQtMjguOTM3CgkJYzcxLjI3NiwwLjAxOSwxMjUuOTMzLDIwLjAzMSwxNjIuNDUsNTAuOTUyYzM2LjQ3LDMxLjAyNSw1NS43MDIsNzIuNzk5LDU1LjgyNCwxMjAuODY0CgkJQzQ3My40NTIsMjU1LjcyMyw0NjYuNDE3LDI4MC43MjksNDU0LjcwOSwzMDEuMjR6IiBzdHlsZT0iZmlsbDogcmdiKDc1LCA3NSwgNzUpOyI+PC9wYXRoPgo8L2c+Cjwvc3ZnPgo=" alt="SNS">
<div class="nav-text">Bluesky</div>
</a>
</li>
</ul>
</nav>
メールでのお問い合わせは、コンタクトフォームを設置しているページなどにリンクさせるといいでしょう。
チャットでのお問い合わせは、ご利用のチャットツールやSNSのDMで手軽にやりとりができるものに。ここでは誰でも簡単に無料でアカウントが作成できるBlueskyをリンクさせてみました。
続いてはCSS。
ルート要素(:root)に「interpolate-size: allow-keywords;」を指定しておきます。
他、お問い合わせのナビゲーションのスタイルを指定します。
以下、CSSのサンプルコードになります。
CSS
:root {
interpolate-size: allow-keywords;
}
.contact-nav {
ul {
display: flex;
flex-direction: column;
gap: 0.5rem;
list-style: none;
margin: 0;
padding: 1rem;
a {
display: grid;
grid-template-columns: 1.5rem auto;
gap: 1rem;
padding: 0.5rem;
align-items: center;
background: #ffd1c6;
border-radius: 0.5rem;
text-decoration: none;
font-size: 1rem;
color: #333;
width: 2.5rem;
overflow-x: clip;
white-space: nowrap;
transition: width 0.3s ease;
&:hover,
&:focus-visible {
width: max-content;
background: #ffab98;
}
}
}
img {
width: 1.5rem;
height: auto;
}
.nav-text {
padding-right: 0.5rem;
font-weight: bold;
}
}
今回のサンプルのポイントは、interpolate-sizeプロパティの指定のほか、ul要素のスタイルの部分になります。
リストのa要素のスタイルを見てみましょう。ポイントとなる部分がわかりやすいように、1行空けて記述しています。
「display: grid;」とグリッドレイアウトで構築しています。
grid-template-columnsプロパティで、横方向のグリッド線間の幅を指定します。アイコン部分が1.5rem、残りのコンテンツはautoとします。このときテキスト部分は1.5remからはみ出る状態です。
そしてコンテンツを折りたたんでいる部分は、横幅と切り取りで調整します。
「width: 2.5rem;」でアイコン部分となる幅を調整し、「overflow-x: clip;」でコンテンツを切り取りテキスト部分を非表示とします。
「white-space: nowrap;」は、もし改行したコンテンツを含めたときに、高さが変わった影響でデザインが崩れるので、もしものために指定しておきます。
アニメーションは「transition: width 0.3s ease;」で、横幅を0.3秒かけて変化させています。イージングはお好みの変化を指定してください。
hover擬似クラスまたはキーボード操作時にフォーカスした場合のfocus-visible擬似クラスに対して、横幅を「width: max-content;」とアイコンとテキストを含んだコンテンツの最大幅に指定します。
親要素以上に「interpolate-size: allow-keywords;」が指定してあることで、max-contentでもアニメーションに適用させることができます。
ちなみに、メニューを画面に固定する場合は、「position: fixed;」などで固定しましょう。
以下のCSSのスタイルと、確認のためにHTML要素も追加しておきます。
(サンプル:画面左中央に固定)
HTML(追加)
<section id="info">
<div class="section-conts">
</div>
</section>
<section id="about">
<div class="section-conts">
</div>
</section>
CSS(追加)
.contact-nav {
position: fixed;
top: 50%;
left: 0;
transform: translateY(-50%);
}
section {
min-height: 100vh;
&:nth-of-type(even) {
background-color: #eee;
}
}
infoとaboutのセクションを追加したので、スクロールしても画面左中央にメニューが固定されているのが確認できます。
最後に
今後、CSSのinterpolate-sizeプロパティが多くのWebブラウザでサポートされれば、開閉式のコンテンツやコンパクトなメニューボタンなどを、JavaScriptを使わずCSSのみで手軽に作成することができるでしょう。
ぜひ参考にしてください。