質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.32%
CSS3

CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

2回答

534閲覧

【HTML】目次の作成について

keel

総合スコア9

CSS3

CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

3クリップ

投稿2025/03/06 01:59

編集2025/03/06 04:11

実現したいこと

スクロールすると右側の目次が追従し、sectionごとに目次部分が切り替わるような仕様を作りたいです。
section1にいる場合は目次「①」に背景色が加わり、そのsectionの見出し文が表示されるような感じです。
section2以降にスクロールした場合は、目次「①」の背景色と見出し文がなくなり、「②」の背景色と見出し文が表示されるような仕様です。

イメージ説明

発生している問題・分からないこと

https://www.bring-flower.com/blog/fixed-and-highlighted-toc/
BringFlowerさんのコードを参考にしました。

olタグの幅を縮めて無理やり縦書きにして、上記のようなものを実現しようと試みましたが、上手くいきません。
JavaScriptにまだまだ乏しく、どのように書けば再現できますでしょうか?
どうかよろしくお願いします。

イメージ説明

※追加しました。
イメージ説明

該当のソースコード

html、css、JavaScript

1<meta name="robots" content="noindex,nofollow" /> 2<!doctype html> 3<html lang="ja"> 4 5<head> 6 <meta charset="UTF-8" /> 7 <meta name="viewport" content="width=device-width, initial-scale=1" /> 8 <link rel="stylesheet" href="https://plot-hub.com/code_example/lib/css/reset.css"> 9 10 <style media="screen"> 11 section.toc-demo{ 12 margin: 0 auto; 13 } 14 h2{ 15 font-size: 20px; 16 background-color: #f3f3f3; 17 border-bottom: 3px solid #333; 18 padding: 5px 0 5px 10px; 19 } 20 p{ 21 padding-left: 10px; 22 } 23 ol{ 24 width: 43px; 25 position: fixed; 26 top: 4vh; 27 right: 25px; 28 } 29 li{ 30 list-style-type:none; 31 } 32 a{ 33 display: block; 34 width: 100%; 35 color: #fff; 36 margin-bottom: 1px; 37 text-decoration: none; 38 padding: 3px 5px 3px 10px; 39 } 40 a.current{ 41 background-color: #dd5eb3; 42 color: #000; 43 writing-mode: vertical-rl; 44 -webkit-writing-mode: vertical-rl; 45 -moz-writing-mode: vertical-rl; 46 -ms-writing-mode: tb-rl; 47 -ms-writing-mode: vertical-rl; 48 } 49 .top{ 50 width: 100%; 51 height: 70vh; 52 background-color: #fbb03b; 53 } 54 .writing-mode{ 55 writing-mode: vertical-rl; 56 -webkit-writing-mode: vertical-rl; 57 -moz-writing-mode: vertical-rl; 58 -ms-writing-mode: tb-rl; 59 -ms-writing-mode: vertical-rl; 60 } 61 62 .content{ 63 width: 100%; 64 height: 100vh; 65 } 66 .toc-demo .content:nth-child(2){ 67 background: #8cc63f; 68 } 69 .toc-demo .content:nth-child(3){ 70 background: #0092ff; 71 } 72 </style> 73</head> 74 75<body> 76 <section class="top">TOP</section> 77 <section class="toc-demo"> 78 <div class="content"> 79 <h2 class="h2test">見出し1</h2> 80 </div> 81 <div class="content"> 82 <h2 class="h2test">見出し2</h2> 83 </div> 84 <div class="content"> 85 <h2 class="h2test">見出し3</h2> 86 </div> 87 <div class="content"> 88 <h2 class="h2test">見出し4</h2> 89 </div> 90 <div class="content"> 91 <h2 class="h2test">見出し5</h2> 92 </div> 93</section> 94 95 <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> 96 <script type="text/javascript"> 97 const headings = document.querySelectorAll('.h2test'); 98let toc = '<ol id="fixed-toc">'; 99 100headings.forEach( function(heading, index) { 101 heading.id = 'heading-0' + (index+1); 102 let id = heading.id; 103 toc = toc + '<li><a href="#' + id + '">' + heading.textContent + '</a></li>'; 104}); 105 106toc = toc + '</ol>'; 107document.querySelector('.toc-demo').insertAdjacentHTML('afterbegin', toc); 108 109window.addEventListener('scroll', function() { 110 let scroll = window.scrollY;//スクロール量を取得 111 let hight = window.innerHeight;//画面の高さを取得 112 let offset = 400;//どの時点で現在表示されている見出しとするかの調整値 113 const toc_completed = document.getElementById('fixed-toc'); 114 115 headings.forEach( function( heading , index) { 116 let i = index + 1; 117 let target = document.querySelector('#fixed-toc li:nth-of-type(' + i + ') > a'); 118 let pos = heading.getBoundingClientRect().top + scroll;//見出しの位置 119 120 if ( scroll > pos - hight + offset ) {//スクロール量が見出しを超えた 121 122 if (headings[index + 1] !== undefined){// 次の見出しがある=最後の見出しではない 123 124 let next_pos = headings[index + 1].getBoundingClientRect().top + scroll;//次の見出しの位置 125 if ( scroll > next_pos - hight + offset ) { // スクロール量が次の見出しも超えている 126 target.classList.remove('current'); 127 } else if (target.classList.contains('current') == true) { // すでにcurrentがついている 128 return; 129 } else if ( i == 1 && toc_completed.classList.contains('active') == false ){// 1つ目 130 target.classList.add('current') 131 toc_completed.classList.add('active') 132 } else { // 次の見出しは見えてない 133 target.classList.add('current'); 134 } 135 136 } else { //最後の見出しの時 137 target.classList.add('current'); 138 } 139 } else { //スクロール量が見出しを超えてない 140 target.classList.remove('current'); 141 if ( i == 1 && toc_completed.classList.contains('active')){ //1つ目に到達していない場合 142 toc_completed.classList.remove('active') 143 } 144 } 145 }); 146}); 147 </script> 148 149 150 151</body> 152 153</html> 154

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

JavaScript内のheading.textContentが見出し文だと思うのですが、だけ表示するには新たにif文を加えていけばいいのでしょうか?
目次の数字は見出しには書かないようにしたいのですが、いまいちやり方がわかりません...。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2025/03/06 03:09

『上手くいきません』とのことでしたが、具体的にはどういった部分が上手くいっていないと感じていますか? 当方でコードを試してみましたが、目次自体は切り替わっているようです。
keel

2025/03/06 04:09

BringFlowerさんのコードを参考にして、それを最初の画像のようなデザインに変えてみようとしましたが、どう付け加えたらいいのかわかりません。 実現したい内容の画像を追加しましたのでご確認いただけますと幸いです。 細かく言いますと、 1、目次の数字をolタグで用意して、それをJavaScriptで繋げる?ようにしたいのですが、BringFlowerさんのコードではJavaScriptでolタグを作っており、ここから数字をどう加えればいいのか分かりません。 2、sectionごとに見出しの表示・非表示という処理をしたく、.currentに加えれば出来ないかと思い、手を加えてみたのですが、形が崩れるばかりでどうすればいいのか行き詰まっています。 分かりづらくて申し訳ありません。 よろしくお願いします。
utm.

2025/03/06 05:23

特定のsectionがビューポートの1番上に接した時に、メニューエリアの表示されるセクションを1度消して、特定のセクション用の表示を出すということだと思うので、 メニューと関連するセクションを全て取得する(section list) スクロールを検知する スクロールの位置がビューポートのトップと接地するものを取得する(active section) メニューのセクション表示を全て消す メニューから(active section)に指定している項目を表示する という流れになりそうです。ifは最初に指定した(section list)と、スクロール位置の一致くらいじゃないでしょうか URLのアンカーを直接書き換えるロジックにした方が色々後で良さそうかもですが。
guest

回答2

0

ベストアンサー

だいぶいじってしまいましたが。

html

1<!doctype html> 2<html lang="ja"> 3 4<head> 5 <meta charset="UTF-8" /> 6 <meta name="robots" content="noindex,nofollow" /> 7 <meta name="viewport" content="width=device-width, initial-scale=1" /> 8 <link rel="stylesheet" href="https://plot-hub.com/code_example/lib/css/reset.css"> 9 10 <style media="screen"> 11 section.toc-demo { 12 margin: 0 auto; 13 } 14 15 h2 { 16 font-size: 20px; 17 background-color: #f3f3f3; 18 border-bottom: 3px solid #333; 19 padding: 5px 0 5px 10px; 20 } 21 22 p { 23 padding-left: 10px; 24 } 25 26 ol { 27 width: 43px; 28 position: fixed; 29 top: 4vh; 30 right: 25px; 31 writing-mode: vertical-rl; 32 display: flex; 33 } 34 35 li { 36 list-style-type: none; 37 list-style-position: inside; 38 list-style-type: symbols('①' '②' '③' '④' '⑤'); 39 text-orientation: sideways; 40 } 41 42 a { 43 display: block; 44 width: 100%; 45 color: #fff; 46 margin-bottom: 1px; 47 text-decoration: none; 48 padding: 3px 5px 3px 10px; 49 } 50 51 a.current { 52 background-color: #dd5eb3; 53 color: #000; 54 writing-mode: vertical-rl; 55 -webkit-writing-mode: vertical-rl; 56 -moz-writing-mode: vertical-rl; 57 -ms-writing-mode: tb-rl; 58 -ms-writing-mode: vertical-rl; 59 } 60 61 .top { 62 width: 100%; 63 height: 70vh; 64 background-color: #fbb03b; 65 } 66 67 .writing-mode { 68 writing-mode: vertical-rl; 69 -webkit-writing-mode: vertical-rl; 70 -moz-writing-mode: vertical-rl; 71 -ms-writing-mode: tb-rl; 72 -ms-writing-mode: vertical-rl; 73 } 74 75 .content { 76 width: 100%; 77 height: 100vh; 78 } 79 80 .toc-demo .content:nth-child(2) { 81 background: #8cc63f; 82 } 83 84 .toc-demo .content:nth-child(3) { 85 background: #0092ff; 86 } 87 </style> 88</head> 89 90<body> 91 <ol> 92 <li></li> 93 <li></li> 94 <li></li> 95 <li></li> 96 <li></li> 97 </ol> 98 <section class="top">TOP</section> 99 <section class="toc-demo"> 100 <div class="content"> 101 <h2 class="h2test">見出し1</h2> 102 </div> 103 <div class="content"> 104 <h2 class="h2test">見出し2</h2> 105 </div> 106 <div class="content"> 107 <h2 class="h2test">見出し3</h2> 108 </div> 109 <div class="content"> 110 <h2 class="h2test">見出し4</h2> 111 </div> 112 <div class="content"> 113 <h2 class="h2test">見出し5</h2> 114 </div> 115 </section> 116 117 <script> 118 document.querySelectorAll('.content').forEach(element => { 119 new IntersectionObserver( 120 (entries, observer) => { 121 entries.forEach((entry) => { 122 if (entry.isIntersecting) { 123 document.querySelectorAll(`li`).forEach(x => x.textContent = ''); 124 document.querySelector(`li:nth-child(${[...document.querySelectorAll('.content').values()].indexOf(entry.target) + 1})`).textContent = 125 entry.target.querySelector('.h2test').textContent; 126 } else { 127 } 128 }); 129 }, 130 { 131 root: null, 132 rootMargin: "-50% 0% -50% 0%", 133 threshold: (x => Array.from(Array(x + 1), (...[, i]) => i / x))(1), 134 }) 135 .observe(element); 136 }) 137 138 </script> 139 140 141</body> 142 143</html>

コメントを受けて追記

ひとまず、書いてみました。
ご自分のコードに組み込む際に解説が必要な部分がありましたら、コメントでお知らせください。

html

1<!doctype html> 2<html lang="ja"> 3 4<head> 5 <meta charset="UTF-8" /> 6 <meta name="robots" content="noindex,nofollow" /> 7 <meta name="viewport" content="width=device-width, initial-scale=1" /> 8 <!-- <link rel="stylesheet" href="https://plot-hub.com/code_example/lib/css/reset.css"> --> 9 <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/destyle.css@4.0.1/destyle.min.css"> 10 11 <style media="screen"> 12 section.toc-demo { 13 margin: 0 auto; 14 } 15 16 h2 { 17 font-size: 20px; 18 background-color: #f3f3f3; 19 border-bottom: 3px solid #333; 20 padding: 5px 0 5px 10px; 21 } 22 23 p { 24 padding-left: 10px; 25 } 26 27 ol { 28 width: 43px; 29 width: auto; 30 position: fixed; 31 top: 4vh; 32 right: 25px; 33 writing-mode: vertical-rl; 34 display: flex; 35 line-height: 1; 36 counter-reset: index; 37 } 38 39 li { 40 list-style-type: none; 41 list-style-position: inside; 42 /* list-style-type: symbols('①' '②' '③' '④' '⑤'); */ 43 text-orientation: sideways; 44 counter-increment: index; 45 display: flex; 46 47 &::before { 48 content: counter(index); 49 text-orientation: upright; 50 border: 1px solid; 51 border-radius: 50%; 52 } 53 54 &.current { 55 &::before { 56 background-color: #000; 57 color: white; 58 } 59 60 } 61 } 62 63 a { 64 display: block; 65 width: 100%; 66 color: #fff; 67 margin-bottom: 1px; 68 text-decoration: none; 69 padding: 3px 5px 3px 10px; 70 } 71 72 a.current { 73 background-color: #dd5eb3; 74 color: #000; 75 writing-mode: vertical-rl; 76 -webkit-writing-mode: vertical-rl; 77 -moz-writing-mode: vertical-rl; 78 -ms-writing-mode: tb-rl; 79 -ms-writing-mode: vertical-rl; 80 } 81 82 .top { 83 width: 100%; 84 height: 70vh; 85 background-color: #fbb03b; 86 } 87 88 .writing-mode { 89 writing-mode: vertical-rl; 90 -webkit-writing-mode: vertical-rl; 91 -moz-writing-mode: vertical-rl; 92 -ms-writing-mode: tb-rl; 93 -ms-writing-mode: vertical-rl; 94 } 95 96 .content { 97 width: 100%; 98 height: 100vh; 99 } 100 101 .toc-demo .content:nth-child(2) { 102 background: #8cc63f; 103 } 104 105 .toc-demo .content:nth-child(3) { 106 background: #0092ff; 107 } 108 </style> 109</head> 110 111<body> 112 <ol> 113 <li></li> 114 <li></li> 115 <li></li> 116 <li></li> 117 <li></li> 118 </ol> 119 <section class="top">TOP</section> 120 <section class="toc-demo"> 121 <div class="content"> 122 <h2 class="h2test">見出し1</h2> 123 </div> 124 <div class="content"> 125 <h2 class="h2test">見出し2</h2> 126 </div> 127 <div class="content"> 128 <h2 class="h2test">見出し3</h2> 129 </div> 130 <div class="content"> 131 <h2 class="h2test">見出し4</h2> 132 </div> 133 <div class="content"> 134 <h2 class="h2test">見出し5</h2> 135 </div> 136 </section> 137 138 <script> 139 document.querySelectorAll('.content').forEach(element => { 140 new IntersectionObserver( 141 (entries, observer) => { 142 entries.forEach((entry) => { 143 if (entry.isIntersecting) { 144 document.querySelectorAll(`li`).forEach(x => { 145 x.textContent = ''; 146 x.classList.remove('current') 147 }); 148 149 const target = document.querySelector(`li:nth-child(${[...document.querySelectorAll('.content').values()].indexOf(entry.target) + 1})`) 150 target.textContent = entry.target.querySelector('.h2test').textContent; 151 target.classList.add('current') 152 } else { 153 } 154 }); 155 }, 156 { 157 root: null, 158 rootMargin: "-50% 0% -50% 0%", 159 threshold: (x => Array.from(Array(x + 1), (...[, i]) => i / x))(1), 160 }) 161 .observe(element); 162 }) 163 164 </script> 165 166 167</body> 168 169</html>

投稿2025/03/06 09:04

編集2025/03/07 02:43
Lhankor_Mhy

総合スコア37338

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

keel

2025/03/07 00:51

ご回答ありがとうございます。 いただいたコードで試してみました。 レベルが高く、script部分がどうなっているのかさっぱりわからないので、解読をしてみます! 1点ご教示していただきたいです。 38行目のlist-style-typeですが、symbolsだと無効になり、表示されませんでした。(Google chrome) 自分なりに調べ、listの疑似要素を使って丸数字の表示と背景色の切り替え(見出し文が表示されると該当の丸数字に背景色加わる)ができないか試しましたが、数字が切り替わらなかったりしてよく分からなくなってきた状態です。 どうすればいいでしょうか... よろしくお願いします。
Lhankor_Mhy

2025/03/07 01:07

あー、そうでした、symbols() はブラウザ対応よくなかったんでしたっけ……失礼しました。 おそらくおっしゃるとおりで、丸数字はCSSカウンターを使って疑似要素を出して丸背景で丸数字風に見せるのがいいかと思います。ただ、CSSカウンターはバグも多いので、お気をつけて。 当方でもお時間いただければ試してみたいと思います。
keel

2025/03/07 10:05

ありがとうございます。 script部分はまだ何となくですが、把握は少しずつできてきました...。 スクロール量の取得部分がいまいち分からないのですが、141行目のentries, observerを使って取得しているのでしょうか? https://weblasts.com/javascript/intersection-observer こちらのサイトを参考にして考えていたのですが、これに近いものでしょうか? root: nullが画面領域? 各見出し(.content)に入った際、処理が始まる? 言葉にするのが難しくどう聞いたらいいのが分からず申し訳ありませんが、 解説をいただけますと幸いです。 よろしくお願いします。
Lhankor_Mhy

2025/03/08 00:07

> root: nullが画面領域? はいそうです。また、rootMargin: "-50% 0% -50% 0%", の設定により調整されており、大まかにいうと画面中央に横直線の領域があり、そこに.contentが交差したときに、 if (entry.isIntersecting) 以下の処理がされる、というイメージです。 IntersectionObserver の解説はこのページがわかりやすいです。 https://ics.media/entry/190902/
keel

2025/03/10 01:04

なるほど... すごく参考になりました! まだまだ勉強不足なので、もっと理解を深めていきます! また機会がありましたらよろしくお願いします。
keel

2025/03/10 06:09

すみません、質問なのですが、丸数字の大きさを変更した場合、縦書きのタイトルを中央揃えにするにはどうすればいいでしょうか? 私なりにcssで変更できないか試しましたが、何をできなかったのでJavaScriptで追記するような感じがいいのでしょうか?
Lhankor_Mhy

2025/03/10 06:54 編集

li に align-items: center ではだめでしょうか?
keel

2025/03/11 09:14

ご回答ありがとうございます。 いただいたアドバイスで出来ました! すごく単純な見落としでした...。
guest

0

参考サイトを確認したところ、class属性へcurrentを指定して現在の見出しかを判定している様です。

現在の見出し
<a href="#heading-05" class="current">見出し5</a>
選択されていない見出し
<a href="#heading-01" class="">見出し1</a>

keelさんの質問は、現在の見出しの時だけテキストを表示したい、という認識ですので下記2点を変更する必要があるかと思います。

① 初期表示時には、見出しを表示しない。
befor
toc = toc + '<li><a href="#' + id + '">' + heading.textContent + '</a></li>';
after
toc = toc + '<li><a href="#' + id + '">&npsb;</a></li>';

② 現在の見出しの場合に見出しを表示する。
target.innerText = headings(i).textContent; (target.classList.add('current')時)
target.innerText = "&npsb;"; (target.classList.remove('current')時)

実際にコードを動かして確認したコードではありません。お役に立てれば幸いです。

投稿2025/03/06 05:44

AndoJun

総合スコア43

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

keel

2025/03/06 08:59

ご回答ありがとうございます。 いただいたコードで試してみましたが、私のやり方がよくなかったのか、上手くいきませんでした...。 ①を試したところ目次部分は「&npsb」が5つ(見出しの数だけ)表示され、 ②ではtarget.classList.addとtarget.classList.removeの記述のすぐ下に各コードを表記しましたが、特に変わりませんでした。 ②の表記する場所を間違えているのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.32%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問