ミラーカラムからスクロール形式へ — 教育コンテンツのレイアウト変換
CF計算書の基礎知識ページ(boki3/ch0)で、ミラーカラムレイアウトのトピック列を消してスクロール形式に差し替えた。ユーザーからスクリーンショットが3回飛んできて、そのたびにレイアウトを書き直した。最終的にExcel基礎講座にも横展開し、Ch1以降の全チャプターにも適用した。
発端
ミラーカラムレイアウトは「セクション → チャプター → トピック → スライド」の4列構造で、1枚ずつスライドを切り替えるUIになっている。スライド形式だとチャートの説明が冗長になり、テキストが断片化する。ユーザーから「普通のスクロールコンテンツにしたい」という要望が出た。
試行錯誤のプロセス
1回目: レイアウト全体をstepsレイアウトに差し替え
最初はstepsレイアウト(左サイドバー + スクロールコンテンツ)に丸ごと置き換えた。ユーザーの反応は「違う」。左側のセクション列・チャプター列はミラーカラムの見た目を維持してほしい、中身だけスクロールにしてほしい、とのこと。
2回目: MillerViewerのスロットでコンテンツ差し替え
MillerViewerコンポーネントのslotを使い、右のコンテンツ領域(Column 4)だけをスクロールHTMLに差し替えた。これもユーザーの意図とは違った。「チャプター列は残していいけど、トピック列をスクロールでまとめてほしい」。
3回目: singleSectionModeでトピック列を消す
MillerViewerは、各チャプターのセクション数が1の場合にトピック列を自動非表示にするsingleSectionModeを持っていた。これを利用し、データ側で各チャプターのセクションを1つに統合。トピック列が消え、セクション列 + チャプター列 + スクロールコンテンツの3列構成になった。ここでユーザーからOKが出た。
実装した変更
stepsレイアウトのスタイル適用
steps側のch0では、コンテンツ幅・行間・段落間隔をすでに調整してあった。boki3/ch0にも同じスタイルを移植した。
/* stepsレイアウトから移植した主要スタイル */
.scroll-inner h2 { font-size: 1.5rem; margin: 2.5rem 0 1rem; }
.scroll-inner h3 { font-size: 1.25rem; margin: 2rem 0 0.75rem; }
.scroll-inner p { line-height: 1.8; margin-bottom: 1rem; }
右サイドTOC追加
スクロールコンテンツの右側に目次(Table of Contents)を追加。セクション見出しへのアンカーリンクで、スクロール位置を把握できるようにした。
セクション・チャプタータイトルの整理
タイトルから冗長な「ch」「0-1」などの接頭辞を削除し、数字だけに整理した。3ファイル(TOC、millerデータ、ch0.vue内のscrollChapters)を一括修正。
SVGのwidth="100%"追加
SVGのルート<svg>タグにwidth属性がなく、ブラウザがintrinsic sizeで小さく描画する問題があった。初期読み込み時に画像が一瞬小さく表示され、リフロー後に正しいサイズになる。全SVGにwidth="100%"を追加して解消した。
steps側のコンテンツをboki3/ch0に流し込み
steps/ch0-1とch0-2の方が内容が充実していた。基礎知識の差分を埋めるため、steps側のテキスト・キーワード・SVG図をboki3/ch0に流し込んだ。会計基準の引用(BookkeepingStandardRefコンポーネント)も3箇所追加した。
Ch1以降のスクロール変換
Ch1(借入金ライフサイクル)もch0と同じパターンで変換。millerデータのテキストをHTML化し、singleSectionModeでトピック列を消し、右TOCを追加した。
チャプター切替時のスクロール位置リセット
チャプターを矢印キーで切り替えると、スクロール位置が前のチャプターの下部のまま残る問題があった。nextTickだけではブラウザのスクロール復元に負けるため、flush: 'post' + requestAnimationFrameの二段構えで対処した。
watch(chapterIdx, () => {
// flush: 'post' でDOM更新後に発火
nextTick(() => {
// requestAnimationFrame でブラウザのレイアウト後に再度リセット
requestAnimationFrame(() => {
scrollContainer.value?.scrollTo({ top: 0 })
})
})
}, { flush: 'post' })
Excel基礎講座への横展開
contents.vueのスクロール変換
boki3/ch0と同じ手法でExcel基礎講座のcontents.vueもスクロール形式に変換した。こちらはチャプター列も消す(TOCのchildrenを1つに統合してnoChapterColを発動)仕様。セクション列 + スクロールコンテンツ + 右TOCの3列になった。
top.vueも同様にスクロール変換
top.vueも同じパターンで変換。「テキスト→図」の順を全セクションで統一した。
SVG図のトーン&マナー統一
contents.vueの3つのSVG図を、svg-diagramスキルのデザインルール(グレー8段階、フォントサイズ規則)に合わせて作り直した。
コンテンツ一覧テーブルの追加
「作業スピードを上げる3つの方法」ページの各セクション(基本機能・ショートカット・関数)の直下に、チャプター名(左・rowspan結合)とサブトピック(右)の階層テーブルを追加。全サブトピックにクエリパラメータ付きリンクを設定し、該当ページに直接遷移できるようにした。
振り返り
ミラーカラムのsingleSectionModeという既存機能を見つけたことで、コンポーネントを書き直さずにトピック列だけを消せた。ユーザーの要望を3回聞き直す過程で「セクション列とチャプター列は残す」「トピック列だけスクロール化する」という仕様が固まった。1回目で正解を出そうとするより、スクリーンショットを見ながら方向を修正するフローの方が、手戻りが小さく済む。
flush: 'post' + requestAnimationFrameの二段構えは、Vue + ブラウザのスクロール復元が競合する場面で使い回せるパターンとして覚えておく。