現時点ではStudioには純正のパーツとしてタブ切り替えが用意されていないため、いくつかの機能を組み合わせて実装する必要があります。これまでStudioでのタブ切り替えといえば、BoxにIDを割り当てることで実装する方法が紹介されてきましたが、今回は「トグル機能」を使ってタブ切り替えを実装する方法をご紹介します。以下が完成したタブ切り替えです。横幅のほとんどを%指定で実装しているため、レスポンシブにも対応しやすくなっています。2024年11月14日に開催されたStudio CommunityイベントStudio User's LT「今日から真似できるStudioの使い方」に登壇し、本記事の方法を実際にエディタを操作しながら解説しました。限られた時間ですのでやや駆け足の説明とはなっていますが、テキストだけよりも理解しやすくなると思いますのでぜひご覧ください。5番目の登壇で、1:05:00あたりから始まります。目次従来のタブ切り替えの課題不自然な余白の発生BoxにIDを割り当ててページ内リンクでタブ切り替えを実現する従来の方法は、タブで表示する各コンテンツのボリューム(縦幅)に差があると、タブ切り替えの要素の下に続くコンテンツとの間に不自然な空白が生まれてしまうことが避けられませんでした。今回の実装方法は、この余白の解消が一番の目的となっています。トグル機能を使ったタブ切り替え実装の全体像今回はタブが4つあるパターンを例に説明します。タブ部分だけをずらしたトグルパーツを4つ用意して、それらを重ねることでタブ切り替えを再現します。タブ1の作成手順今回の実装方法では、タブ1とタブ2~4ではレイヤー構造が異なります。まずはタブ1の作成手順です。タブ1のトグルの設定は「デフォルトで開く」ON、「要素外クリックで閉じる」ONにします。トグルボックスの横幅の値が、そのままタブ切り替えのコンテンツボックスの横幅となります。冒頭に載せたサンプルでは1000pxにしています。[<button>input]の横幅を25%、縦幅は任意の値(サンプルでは100px)にします。この横幅は、タブの数やデザインによって適宜変更します。今回はタブが4つあり、それらが均等に配置されるようにするため25%としました。さらに、[<button>input]の上部にネガティブマージンを設定します。このネガティブマージンの値はボタンの縦幅と同じにします(サンプルでは100px)。ここでネガティブマージンを設定していないと、このあと作成するタブ2、タブ3、タブ4のボックスが重なってクリック/タップの判定が出なくなります。はみ出しの設定はデフォルトでは「非表示」になっていますが、これを「表示」に変更しておきます。これでタブ1の枠組みは完成です。タブ部分の文字列やコンテンツボックス内は、通常の作業と同じように、それぞれ必要な内容に書き換えてください。なお、タブやコンテンツボックス内はコンポーネントを活用するとデザインの管理がしやすくなります。タブ2以降の作成手順いま作ったタブの要素が一式含まれている<div>を複製してトグルパーツを増やします。タブ2以降のトグルの設定は「デフォルトで開く」OFF、「要素外クリックで閉じる」ONにします。タブ2以降はタブ1と同じ位置に重ねる工程が必要にあります。これを絶対配置で実装すれば手順はシンプルになりますが、下図のように「絶対配置にしたタブ2以降のコンテンツを展開したときに、下に続くコンテンツを侵食してしまう」という大きな問題を抱えることになります。そのため、タブ2からは絶対配置不使用で意図したところに配置するために、いくつかの工夫を加えます。タブ2のレイヤー全体像は以下の通りです。一気に複雑になりますが、ひとつずつ解説していきます。タブ2のタブ部分の作成複製したタブ1の[<button>input]の下にボックスを挿入します。このボックスはのちに位置調整用として使いますので、以後「位置調整Box」と呼びます。この位置調整Boxと[<button>input]を選択した状態でグループ化します(このグループを「ボタンBox」とよびます)。そうすると、「No content」というテキストを内包したボックスが生成されます(以後、不要Boxと呼びます)。不要Boxは削除できませんが、トグルボックスをダブルクリックして編集モードに入ってから、不要Boxをクリックすると、<div>だったボックスが[<button>input]に変化し、中のテキストが自動的に削除されます(下図参照)。この状態にしたあと、不要Boxの縦幅を0pxにして表面上、非表示の形を作り出します。ボタンBoxは横幅100%、縦幅autoとし、配置は「左下揃え」、方向を「→」にします。ボタンBox内のアイコンは不要なので削除し、テキストを任意の文字列に書き換えます。タブ2全体としての位置調整の前に、タブ2の内部構造を整えておきます。(ややこしい表現になりますが)タブ2のコンテンツ部分はタブ1のコンテンツ部分の左端と揃えたまま、タブ2のタブ部分だけが、タブ1のときよりも横幅25%分右側にくる必要があります(下図参照)。これを実現するためにタブ2のボタンBox内に2つの位置調整Boxを配置します。レイヤーの上から順に位置調整Box(左):横幅25% → タブ:横幅25% → 位置調整Box(右):横幅50%となります(レイヤーの並び順については前出のレイヤー全体像の図を参照)。位置調整Boxの縦幅はいずれも0pxに設定します。これでタブ2の内部構造は作成完了です。つぎにタブ1とタブ2を横並びにする必要があるので、それらをグループ化します。これがタブ切り替え全体の親ボックスとなります。配置は「上左揃え」、方向を「→」にします(配置を上揃えにすることで、タブをクリックしたときに、タブ部分は動かずに下にコンテンツが展開するようになります)。現時点では下図内の上の状態になります。これをタブ2がタブ1に重なるように調整します(前述の理由により絶対配置は使えないため、それ以外の方法を採用します)。全体位置調整Boxを追加して対応します。タブ2の下に空ボックスを追加し、それらをグループ化します(タブ2の中に追加しないように注意)。生成された親ボックスの配置は上中央揃えにします。ここまでの作業でレイヤー構造が複雑になって分かりづらいと感じた場合は、一度タブ2の全レイヤーを閉じてから、その下にボックスを追加すると少しは分かりやすくなると思います。全体位置調整Boxは縦幅0pxで、タブ2の場合は横幅を200%にします。これでタブ2全体を左側に押し込むことができます。タブ3、タブ4の作成タブ2が完成したら、それを複製してタブ3とタブ4を作りますが、その手順をまとめるとタブ2を複製して、(わかりやすいように)タブ3と名称をつけるタブ3のボタンBox内の位置調整Box(左)および(右)の横幅の%を調整する(2つ上の図参照)タブ3の全体位置調整Boxの横幅を400%にするタブ2(またはタブ3)を複製して、(わかりやすいように)タブ4と名称をつけるタブ4のボタンBox内の位置調整Box(左)の横幅の%を調整する(位置調整Box(右)は削除)タブ4の全体位置調整Boxの横幅を600%にするタブ切り替え時の挙動を変更する方法コンテンツBoxのモーションの「時間」の値を変更することで、タブ切り替え時の挙動をコントロールすることができます。値を「0」にすれば、タブをクリックした瞬間にコンテンツが切り替わるようになります。同じタブを連続でクリックするとコンテンツが閉じてしまう問題を回避する方法ボタンBoxの中にある位置調整Boxを複製、下に新しいボックス(クリック防止用Box)を追加し、その2つをグループ化します。グループ化によってできた親ボックスの横幅は100%、配置は「左揃え」、方向を「→」、そして配置を絶対位置にします。子要素であるクリック防止用Boxの塗りは透明、横幅は25%、縦幅はタブ部分と同じにします(今回であれば100px)。さらに上部にネガティブマージンをタブ部分と同じ(-100px)だけ設定します。これで、クリック防止用Boxが該当するタブの上に重なる状態を作ることができました。あとは、このクリック防止用Boxがトグルが開いている時だけタブに重なって、クローズ時は重ならないようにする必要があるので、条件付きスタイル「クローズ」の設定でクリック防止用Boxの横幅が0pxになるようにします。ホバー時のタブの背景色を変える方法[<button>input]のボックスに対して「条件付きスタイル:ホバー」の設定を加えることで、タブにホバーしたときのスタイルを変更できます。[<button>input]の中にコンポーネントを入れている場合は、コンポーネントのボックスに対して「条件付きスタイル:ホバー」の設定をします。選択中のタブのスタイルを指定する方法コンテンツを表示しているタブのスタイルを変更させる場合は、トグルボックスをダブルクリックして編集モードに入ってから、[<button>input]の通常時およびクローズ時のスタイルを指定します。実装がすべて完了したあとだと、トグルボックスの縦幅は0pxになっていて判定が無いため、デザインエディタ上でダブルクリックすることができません。そのため、一時的に縦幅を10px程度にしてクリックできる範囲を確保するとうまくいきます。この実装方法のデメリット全体的に多量の空Boxを配置することになる原則、タブとコンテンツボックスは隣接させて配置することになるため、レイアウトの自由度が若干低くなる要素外をクリックすると全てのタブのコンテンツボックスが閉じ、タブ部分だけが表示されている状態になるまとめやや複雑な手順になりますが、一度作ってしまえば枠組みは流用することができるので、2つ目以降の実装コストは軽減されると思います。状況に応じて、従来の実装方法と使い分けていただければと思います。