「data-target="#〇〇"」・・・「#」よ、お前は何者なんだい?


前提

今年8月末に、ゼロからHTMLに取り組み始めました。
黒澤さん(@kurokurosawa)によるウェビナー「YoshiTech 会津わろ法則」Round2 の修了生です。
黒澤さんが提唱する「学んだことをQiitaにアウトプットする取り組み」を、少しずつ実践しています。

現状としては、HTML/CSS の基礎についての学習が一区切りついたので、Bootstrap の学習に入っています。
Bootstrap について一区切りついたら、次はJavaScript に進む予定です。

Udemyを利用して学習しています。
現在受講を進めている講座は、
・ウェブ開発入門完全攻略コース - プログラミング をはじめて学び創れる人へ!未経験から現場で使える開発スキルを習得!
・[HTML/CSS/JavaScript] フロントエンドエンジニアになりたい人の Webプログラミング入門
の二つです。

Bootstrap を用いたコードで、「#」を書き忘れてしまいました

Bootstrap を使って、画面幅が狭くなったときに出現する「ハンバーガーメニュー」のコードに取り組んでいた時のことです。

(画面幅が狭くなるとこうなって・・・)

    ↓
    ↓
(右側のボタンを押すとこうなるやつです)

こうしたハンバーガーメニューを作ろうと、次のコードを書きました。

    <nav class="navbar navbar-expand-lg navbar-light" style="background-color: rgb(194, 226, 247);">

      <a class="navbar-brand" href="#">ナビゲーションバー</a>

      <button class="navbar-toggler" type="button" 
              data-toggle="collapse" data-target="NavbarSupportedContent"
              aria-controls="NavbarSupportedContent" aria-expanded="false" 
              aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span></button>

      <div class="collapse navbar-collapse" id="NavbarSupportedContent">
        <ul class="navbar-nav">
          <li class="nav-item"><a class="nav-link" href="#">ホーム</a></li>
          <li class="nav-item"><a class="nav-link" href="#">ブログ</a></li>
          <li class="nav-item"><a class="nav-link" href="#">ギャラリー</a></li>
        </ul>
      </div>

    </nav>

もちろん、自分でゼロから書いているわけではありません。
Udemy の講座を見ながら、ハンズオン形式の「手取り足取り状態」で書きました。
にもかかわらず・・・エラー発生です。

どんなエラーかというと、ハンバーガーメニューが開いてくれません。
ハンバーガーメニューのボタン自体は表示されるのですが、いくらボタンをクリックしても反応してくれないのです。

結論から言うと、button タグ内の data-target 属性の記述に誤りがありました。

正しくは「data-target="#NavbarSupportedContent"」と書かなければならないのに、「#」を書き忘れていたのです。

書き忘れただけならまだしも・・・

こうした「書き忘れ」自体は、つまるところヒューマンエラーです。
もちろん間違いに対して開き直るのは禁物ですが、かといってヒューマンエラーを根絶するのも不可能でしょう。
大切なのは、ヒューマンエラーの発生を見越しつつ、リカバリーする体制をととのえておくことだと思います。

その意味で、今回の件では「書き忘れ」以上に深刻な問題がありました。
というのも、この書き忘れを見つけるのに、とても時間がかかってしまったのです。

HTML/CSS のコードを書くのにもだいぶ慣れてきて、自分の中では「エラーへの対処法」がそれなりに固まっていたところでした。

もしエラーが発生しても、
・スペルミス
・半角スペースの欠如
・タグ類の閉じ忘れ(特にCSSの「;」の書き忘れ)
・使用する要素や属性の取り違え
・ネスト構造の間違い
といった点に注意してコードを見返せば、エラーの原因は見つかるものだと思っていたのです。

そのやり方が、今回の「#」の書き忘れについては通用しませんでした。

なぜなら、「#」の意味を理解できていなかったからです。

意味を考えない「丸暗記」には限界がある

今回のミスについて、
「data-target 属性について記述する際には、# が必要!」
と割り切って丸暗記してしまうのも、ひとつの対処法かと思います。

はじめのうちは、あえて丸暗記する。
そのうえで、たくさんコードを書きながら、手に覚えさせてしまう。
・・・もちろん、こうしたアプローチも必要です。

ただ、それだけに頼っていると、膨大な時間がかかってしまいます。
そこで、手を動かすことに加えて、「意味を考える」ことが大事になってくるのではないでしょうか。

実際、私はHTML/CSSの学習を始めて、まだそれほど時間が経っていません。
それでも、基礎的なコードの書き方をある程度習得できています。
それは、手を動かしてコードを書くと同時に、コードの意味を考えていたからだと思うのです。
(視聴しているUdemy 講座が、質の高いレクチャーをしてくれるおかげです)
意味を考えずに、ただ丸暗記しようとしていたら、何一つ習得できていなかったことでしょう。

なので今回のミスについても、「# の意味を考える」ことで道が開けるのではないかと考えました。

というわけで、「#」について考えてみました

そこで、「#」がコードの中でどんな役割を果たすのか、自分なりに考えていきたいと思います。

情報をリンクさせるためのものっぽい

今回のコードで「#」が必要になった data-target 属性。
この属性の役割は、「ハンバーガーメニューを開いたときに出てくる情報を指定する」ということだと思います。
つまり、「ハンバーガーメニューのボタン」と「開いたメニューに表示される情報」をリンクさせるための属性です。

「#」をリンクに使う例として思い浮かぶもの

こうした「#」が出てくる例としては、ページ内リンクが思い浮かびます。


<body>
  <p>(本文1)</p>
  <p>電話番号は<a href="#phone_number">こちら</a>をクリック</p>
  <p>(本文2)</p>
  <p id="phone_number">電話番号は〇〇〇</p>
</body>

そういえば、id 属性を付加した要素に CSS をあてるときにも、「#」を使いますよね!

#phone_number{
  color:red;
  border:solid 1px black;
}

似たような例でも「#」を使わない場合が・・・

一方、似たような場面なのに「#」を使わない例も思い浮かびます。
たとえば、外部サイトにリンクを張る場合。


<body>
  <p>(本文1)</p>
  <p>お店のホームページは<a href="https://〇〇〇">こちら</a>をクリック</p>
  <p class="background_color_red">(注意書き1)</p>
  <p>(本文2)</p>
  <p class="background_color_red">(注意書き2)</p>
</body>

また、class 属性を付加した要素に CSS をあてるときには、「#」ではなく「.」を使います。

.background_color_red{
  background-color:red;
}

あるいは、HTMLファイルにCSSスタイルシートを読み込む際にも、「#」は使いません。

<link rel="stylesheet" href="css/style.css">

・・・なぜ「#」を使う場合とそうでない場合に分かれるのでしょう?

「#」を使う場合のポイント1 「ファイル内の特定箇所へのリンク」

ヒントを求めて Web をさまよっていると、とても参考になる記事を見つけました。

ハイパーリンクを提供する | The Web KANZAKI

この記事の中で、ページ内リンクの例として、次のようなコードが挙げられています。

<a href="#detail">このファイル内の詳細へ</a>

そして、直後に次のような注意書きが書かれています。

×よくある間違い:#を忘れると、「detail」という名前のファイルを探そうとしてNot Foundエラーになります。

「#」がなければ、ファイル名と誤解されてしまう・・・
この注意書きが、とても大きなヒントになってくれました!

つまり、まずは次のように考えるとよいのだと思います。

1. リンク先としてファイル全体を指定するときは、「#」は不要 

2. リンク先としてファイル内の特定箇所を指定するときは、「#」を使う
 2-1 同一ファイル内の特定箇所を指定するときは「#〇〇」
  2-2 外部ファイル内の特定箇所を指定するときは「ファイル名#〇〇」

こう考えれば、外部リンクやCSSスタイルシートを読み込む際には「#」が不要で、ページ内リンクには「#」が必要になる理由が分かります。

また、そもそもの発端である「data-target="#〇〇"」の意味についても、だいぶハッキリしてきます。つまり、
【ハンバーガーメニューが開いたときに出てくるようにしたいのは、同一ファイル内の特定箇所にある情報。だからこそ、「#」を書く必要がある】
というわけです。

ここまでイメージできるようになれば、data-target 属性に「#」を書き忘れてエラーが発生した場合にも、リカバリーにかかる時間を短縮できそうです。

「#」を使う場合のポイント2 「名前の唯一性」

ここまでの段階で、今回の目的(「#」の書き忘れへの対処)はすでに達成できています。
ですが、先ほどの記事(ハイパーリンクを提供する | The Web KANZAKI)には、さらなるヒントがありました。

それは、「#」を用いて指定する「名前」についてのお話です。

名前は、同一ドキュメントの中で唯一のものでなければならず、重複してはいけません(Uniqueness)。このとき、(1)大小文字の違いだけによる名前付けは、この唯一性を満足できません;(2)ただし、名前の照合時(string match)に大小文字は区別されます。以下のような使い方をしないよう注意してください。

記事内では、これを「名前の唯一性」と呼んでいます。

「#」を使って指定する名前は、「唯一」のものでなければならない。
だからこそ、CSSをid属性とリンクさせる場合には「#」を使えて、class属性とリンクさせる場合には使えないのですね。

CSSでの「#」と「.」の使い分けにまで、視野を広げることができました!
(そういえば、そもそもの発端であるBootstrapを使ったコードの中で、ハンバーガーメニューに紐づける要素のタグ付けには id 属性が使われていたのでした・・・まるで伏線が回収されたような感覚です笑!)

おまけ:個人的な「#」のビジュアルイメージ

今回の検討を踏まえて、「#」に対して個人的に次のようなビジュアルイメージを持つに至りました。

フック付きロープイラスト/イラストACより

先端に金属製のフックが結びつけられたロープです。
(よくアクション映画なんかで、フックを高いところめがけて投げて「ガチっ!」と固定させ、壁をよじ登るのに使うアレです)

ファイル内の特定箇所に向けて、このロープを投げかけるようなイメージ。
また、1本のロープなので1か所にしか使えず、「名前の唯一性」のイメージにもぴったりなんじゃないかな?と思っています。。。

最後まで読んでいただき、ありがとうございました!