Stimulusで複数のCSSクラスをオンオフする方法(翻訳)
CSSクラスの動的な追加や削除(切り替え)は、Webアプリでよく行われる操作です。
- 例:
hidden要素(display: none)をblock(display: block)に変更することで表示する - 例: DOMの下の方にカスケードするクラスを追加する(つまりbody要素に
darkクラスを追加する)
1個の要素に複数のクラスを追加したい場合があります。私のRails Designerサイトの上部にあるナビゲーションバーがよい例で、下に一定以上スクロールすると、<nav>要素にbg-white/60とbackdrop-blur-mdが追加されて、ナビゲーションバーが半透明になります。
これは、Stimulusにあるそれ専用のCSSクラス用APIで実現できます。
最もシンプルな方法は以下のようになります。
<nav data-controller="navigation" data-navigation-scrolling-class="block">
次にこれをnavigation_controller.jsファイルで以下のように利用します。
export default class extends Controller {
static classes = ["scrolling"];
scroll() {
// IntersectionObserverのスレッショルド/インスタンス化がある程度進むと発動する
this.element.classList.toggle(this.scrollingClass);
}
}
ここではclassList.toggleという機能を使っています。なるほど見事ですが、CSSクラスが複数の場合はどこに書いたらよいのでしょうか?
DOMのClassList APIのtoggleに加えて、以下のようにaddメソッドやremoveメソッドを使うと、以下のようにクラス(の配列)を追加できます。
// ...
scroll() {
this.element.classList.add("bg-white/60", "backdrop-blur-md");
}
// ...
しかし、CSSクラスのリストを以下のようにdata-*属性の値としてscrollingに渡そうとしても失敗します。
<nav data-controller="navigation" data-navigation-scrolling-class="bg-white/60 backdrop-blur-md">
どうすれば解決できるでしょうか?
🔗 複数のCSSクラスは複数形のXXXClasses APIで渡す
Stimulusにはそのための方法がちゃんと用意されています。
CSSクラスを複数渡したいときは、単数形のthis.scrollingClassではなく、複数形のthis.scrollingClassesという名前にすればよいのです。以下のようにこれとJavaScriptのspread構文...を使えばおしまいです。
// ...
scroll() {
this.element.classList.add(...this.scrollingClasses);
}
// ...
なかなか気の利いた解決法だと思いませんか?
概要
元サイトの許諾を得て翻訳・公開いたします。