はじめまして、さきがけデジタルの三浦です。
主にウェブページなどのコーディングを担当しております。
私のブログでは、開発で役に立ったコードやテクニックを紹介していきたいと思います!
趣味の話もしていきたいですね~。
◇ ◇
さて、今回は「CSS」と「JavaScript(JS)」についてのお話です。
ウェブページのコーディングでよく使うCSSの疑似要素「before/after」。
文字を挿入するだけではなく、線や図形、画像を表示したりなど、
複雑なデザインを構成するために欠かせないテクニックです。
コーダーのみなさんは、こんなことを思ったことはありませんか?
「疑似要素のCSSをJSで上書きできないか」
弊社サイトの構築時、アニメーションの細かい調整が必要となり、実装するために調べてみました。
結論から言うと「疑似要素に対してJSで直接変化を加えることはできない」ようです。
では、どうしたら良いのか。
さらに調べてたどり着いたのが「CSS変数を使う」方法でした。
■ 実現したいこと
(1)ページ内にタイトルを複数設置する
(2)タイトルに疑似要素を使って下線を引く
(3)下線が伸びるようなアニメーションを設定する
(4)タイトルそれぞれの文字数に応じて、アニメーションの秒数を変動させる
なぜアニメーションの秒数を変化させるのか。
すべて同じ秒数にしてしまうと、
文字数が少ないときは「ゆっくり」と、文字数が多いときには「速く」感じてしまうためです。
「ページ全体で均等なアニメーション」にするために、文字数によって秒数を調整することが必要でした。
★ まず、アニメーションを4秒に設定した場合
※「RunPen」ボタンを押して、動きを見てみてください。「Rerun」ボタンを押すと、もう一度再生できます。
アニメーションの秒数は「4秒」に設定しています。
文字が多い場合は、少し速く動いているように見えます。
3つのテキストを比べると、アニメーションにバラつきがあるように感じます。
★ JSを使ってアニメーションの秒数を制御した場合
一方、こちらはJSを使用して、アニメーションの秒数を制御しています。
文字数が増えても、動きが極端に速くなったりしません。
3つのテキストを比べると、動きに統一感が出ていると思います。
ここからは、完成したコードの紹介と解説をしていきます。
★ HTML
<div class="l-content">
<div class="l-content__section">
<h2 class="c-title">1234567891012345678910</h2>
</div>
<div class="l-content__section">
<h2 class="c-title">12345678910</h2>
</div>
<div class="l-content__section">
<h2 class="c-title">12345</h2>
</div>
</div>
★ CSS
.l-content {
display: grid;
gap: 16px 0;
}
.c-title {
display: inline-block;
white-space: nowrap;
position: relative;
}
.c-title::after {
display: block;
content: "";
width: 100%;
height: 1px;
background-color: #000;
transform: scaleX(0);
transform-origin: center left;
animation: bar var(--animeDuration) linear forwards;
position: absolute;
bottom: 1px;
left: 0;
}
@keyframes bar {
0% { transform: scaleX(0); }
100% { transform: scaleX(1); }
}
★ JavaScript
window.addEventListener("load", function() {
const title = document.querySelectorAll(".c-title");
const baseDuration = 0.18;
title.forEach(element => {
let textCount = element.textContent.length;
let animeDuration = baseDuration * textCount;
element.style.setProperty("--animeDuration", `${animeDuration}s`);
});
});
■ CSSの解説(要点のみ)
animation: bar var(--animeDuration) linear forwards;
アニメーションを指定しますが、JSで変化させたいプロパティの値は「CSS変数」で指定します。
■ JSの解説
window.addEventListener("load", function() { ~
ページの読み込み後に実行されるようにします。
const title = document.querySelectorAll(".c-title");
複数ある H2タグ「.c-title」を取得して、変数「title」に格納します。
※このときの返値は「NodeList」となります。
const baseDuration = 0.18;
アニメーションのベースとなる秒数を指定します。※ CSSのみのサンプルと合わせています
title.forEach(element => { ~
取得したタイトル要素が複数あるので、forEach文で処理を繰り返します。
let textCount = element.textContent.length;
タイトルの文字数を取得します。
let animeDuration = baseDuration * textCount;
アニメーションの秒数を計算します。今回は、ベースの秒数と文字数を掛け算しています。
element.style.setProperty("--animeDuration", ${animeDuration}s);
「setProperty関数」を使い、HTMLタグに直接「style」を設定します。
「CSS変数:animeDuration」の値が「●●秒(計算後)」となるように記載します。
JSがうまく実行されると、
H2タグにCSS変数と値が書き加えられます(検証ツールなどでご確認ください)。
<h2 class="c-title" style="--animeDuration: 22s;">1234567891012345678910</h2>
<h2 class="c-title" style="--animeDuration: 11s;">12345678910</h2>
<h2 class="c-title" style="--animeDuration: 2s;">12</h2>
H2タグに直接styleが書かれているので、
各CSS変数は上書きされることなく、要素それぞれに違う値が適用されます。
◇ ◇
いかがでしたでしょうか?
今回は「アニメーションの秒数」だけにフォーカスを当てましたが、
別のプロパティにしてみたり、複数組み合わせみたりすれば、さらにコーディングの幅が広がるかと思います。
「setProperty関数」にCSS変数を指定しましたが、通常のCSSプロパティも設定できるので、
疑似要素以外にも使い道はたくさんありそうですね。
きょうはここまで!
今後はコーディングの話のほか、ゆる~い事も書いていきたいと思います。
ではでは、またお会いしましょう ノシ