aタグ(リンク)のクリックできる範囲をCSSで親要素まで広げる

aタグ(リンク)のクリックできる範囲をCSSで親要素まで広げる

CSS

aタグのクリックする範囲がズレたり、想像以上にクリックできる範囲(当たり判定)がオカシい!そんなお悩み解決します。

そこで、今回はaタグのクリックできる範囲のズレを直す方法をご紹介します。

※ この記事は2023年1月21日にメンテナンスしました。みなさんのコーディングライフの一助となれば幸いです。

aタグ(リンク)にまつわるお困りごと3つ

この記事では初心者がつまずきがちの3つのお困りごとの解消法と原因をご紹介します

  • ナビゲーションをクリックしても反応しない!?
  • aタグの中に画像を配置して下側にできたアキをどうにかしたい!!
  • リンクのど真ん中に文字や画像を配置したい
この記事を書いた人

かみーゆ/フロントエンドエンジニア

資金ゼロからフィリピンで起業した海外ノマドエンジニア。IT業界10年以上でテクニカルディレクター(技術責任者)・エンジニア講師・ブリッジSEを経てLenzTechnologies Inc.を設立し、代表を務める。CMS concreteCMSエバンジェリスト。テックブログ以外も「磨耗しない人生」や「海外ノマド」のライフスタイルについて発信。好きなものは肉とハイボール。

お困りごと1・あれ?!ナビゲーションをクリックしても反応しない!?

こんなナビを作ってみたものの、見た目はキレイにできているのにクリックしてもテキスト部分しかリンクが反応しない。。。。

そんなことあります。

クリックしても反応しない!? テキスト以外のエリアをクリックしてもちゃんとリンクへ飛ぶようにしたいですよね?

このようにナビゲーションを配置したい時に書きがちなコードです。

display: flexでナビのliタグを横方向に並べ、幅を均等に振り分けます。

HTML
<ul>
  <li><a href="/">ホーム</a></li>
  <li><a href="blog/">ブログ</a></li>
  <li><a href="profile/">プロフィール</a></li>
  <li><a href="contact/">お問合わせ</a></li>
</ul>
CSS
* {
  box-sizing: border-box;
}

ul {
  display: flex;
  flex-wrap: wrap;
}

li {
  width: 25%;
  text-align: center;
  border-left: 1px solid #fff;
}

li:first-child {
  border-left: none;
}

a {
  padding-top: 20px;
  padding-bottom: 20px;
}
残念ながらこのコードではリンクの範囲はliタグと同じサイズになりません。

解決法:CSSでaタグにプロパティdisplay:blockをセットするだけ

ではどうすればいいのか。

解決方法はカンタンです。 aタグにCSSでプロパティdisplay:blockをセットするだけです。

原因の解説

理由はaタグの初期値はdisplay: inline、つまりaタグがインラインレベルの要素だからです。

displayは要素の表示形式を指定するプロパティでinlineを指定すると通常、内側のコンテンツ(テキストなど)以上のサイズに大きくなることはありません

そのためliタグの中にインラインレベルの要素をおくからアキができてしまうわけです。

プロパティdisplayを活用して表示形式を変えましょう。

お困りごと2・aタグの中に画像を配置して下側にできたアキをどうにかしたい!!

画像を入れ子にしたら下の方にこんな感じのアキが!!

aタグの中に画像を配置して下側にできたアキをどうにかしたい!!

解決法:CSSでimgタグにプロパティvertical-align: bottomをセット

この現象は初心者あるあるです。

解消法はCSSでimgタグにvertical-align: bottomをセットするだけです。

HTML
<a href="/"><img src="images/hogehoge.jpg" alt="hogehoge" width="200" height="200"></a>
CSS
a {
  display: block;
  width: 300px;
  height: 300px;
  border: 2px solid #333;
}

img {
  width: 100%;
  height: auto;
  vertical-align: bottom;/* ←これが重要 */}

原因の解説

プロパティvertical-alignはインライン要素の縦方向の位置を調整するプロパティです。 アイコンの位置上付、下付きなどの文字位置の調整もプロパティvertical-alignを使います。

imgタグの下になぜ余白ができるのか。

インラインレベルの要素はアルファベットをベースに作られているからです。

vertical-align: baseline;

HTMLはもともと英語圏の人が作ったものなので、文字にはベースラインが基準になるようにセットされてます。小文字の「g」や「j」下に突き抜けます。

imgタグなどのインラインレベルの要素はこれらの文字と同じ振る舞いをするので下に変なアキができてしまうのです。

インラインレベルの要素はアルファベットをベースに作られている

画像の位置のたての位置の基準を一番下に変えれば良いだけです。

vertical-align: bottom;

お困りごと3・リンクの範囲を縦方向にも広げて文字位置を縦横方向真ん中に配置したい

aタグの中に画像を配置して下側にできたアキをどうにかしたい!! イラストのようなナビゲーションメニューを作る時、**高さを寸分狂わず決まった高さにしたい!!**しかもリンクのテキストは上下左右ピタッとセンタリングしたい。

なのにpaddingheightを駆使してもなぜかうまくいかないことってありませんか?

解決法:aタグにプロパティdisplay:flexをセットして配置を調整

解決法はdisplay: flexを使い倒します。

  • aタグに高さをセットする
  • display: flex
  • justify-content: center
  • align-items: center
CSS
* {
  box-sizing: border-box;
  line-height: 1.8;
}

ul {
  display: flex;
  flex-wrap: wrap;
  background: #4D4D4D;
  list-style: none;
}

li {
  width: 25%;
  text-align: center;
  border-left: 1px solid #fff;
}

li:first-child {
	border-left: none;
}

a {
  height: 70px;
  text-decoration: none;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
}

原因と解説

プロパティdisplayをflexにすると子要素やコンテンツの縦方向や横方向並びと位置をコントロールできます

flex-directionというプロパティをセットで使うのですが、初期値はrowがセットされており子要素は横並びになります。なので縦方向に並べたい時はcolumnをセットしておきます。

並べていく方向のコンテンツの位置をコントロールできるのがjustify-contentで、centerにするとこの場合、コンテンツは横方向にセンタリングされます。

縦方向に対しての位置をコントロールするプロパティがalign-itemsです。値をcenterにするとaタグの縦方向に対し真ん中にコンテンツを配置できます。

おまけ・HTML5の要素について要素がどうカテゴライズされているか知っておこう

インライン、ブロック要素という言い方はHTML5ではなくなりました。

ただ、この記事では便宜上aタグとimgタグをインラインレベルの要素と説明しています。

インライン、ブロックの解説は難しいですね。

要素は分類できる

要素(HTLMタグ)、つまりコンテンツは7つに分類できます。

  • メタデータ・コンテンツ … 文書情報や別文書との関係などを定義するコンテンツ
  • フロー・コンテンツ … 文書の本体に現れる一般的なコンテンツ
  • セクショニング・コンテンツ … セクションの範囲を定義するコンテンツ
  • ヘッディング・コンテンツ … 見出しを表すコンテンツ
  • フレージング・コンテンツ … 段落内で使用するようなコンテンツ
  • エンベッディッド・コンテンツ … 文書内に埋め込みを行うコンテンツ
  • インタラクティブ・コンテンツ … ユーザーが操作可能なコンテンツ
HTLMタグ要素の分類

aタグやimgタグは、HTML5では主にフレージングコンテンツの一種ですが同時にユーザーが操作可能なのでインタラクティブコンテンツでもあります。

さらに、imgタグは「画像を埋め込む」コンテンツでもあるのでエンベッディッド・コンテンツにも属します。

とても複雑ですね。

要素の特性を知る上では重要ですが、こんなことイチイチ気にしていたらコーディングできないです。

たとえはフレージング・コンテンツであるspanや、strongの中にpタグやdivタグを入れたら文書構造が破綻するぐらいは知っておいた方がいいですが、気になったら都度調べる程度で十分です。

種類タグ備考
フローコンテンツ<a>, <abbr>, <address>,
<area>(map要素内にある場合)<article>, <aside>,
<audio>,<br>, <b>,
<bdi>, <bdo>, <blockquote>,
<br>, <button>,<br> <canvas>,
<cite>, <code>, <data>, <datalist>,
<del>,<details>, <dfn>,
<div>,<dl>,<br>, <em>,
<embed>, <fieldset>, <figure>,
<footer>, <form>,<br>, <h1>-<h6>,
<header>,<hr>, <i>, <iframe>,
<img>,<input>,<br>
<ins>, <kbd>, <keygen>,
<br>, <label>, <main>, <map>,
<mark>,<menu>, <meter>, <nav>,
<noscript>,<br>, <object>, <ol>,
<output>, <p>, <picture>,
<pre>, <br>, <progress>, <q>,
<ruby>, <s>,<br>, <samp>, <script>,
<section>, <select>,<small>,
<span>, <strong>, <sub>, <sup>,<br>, <table>, <template>,
<textarea>,<br> <time>,
<u>, <ul>, <var>,
<video>, <wbr>, テキスト
メタデータコンテンツ<base>, <link>, <meta>, <noscript>,
<script>, <style>, <template>, <title>
ヘッディングコンテンツ<h1> ~ <h6>見出し
セクショニングコンテンツ<article>, <aside>, <nav>, <section>
フレージングコンテンツ<a>, <abbr>, <area> (map要素内にある場合)
<br> <audio>, <b>, <bdi>, <bdo>,
<br>, <button>,<br> <canvas>, <cite>, <code>, <data>,<br>
<datalist>, <del>, <dfn>, <em>, <embed>,<br>
<i>, <iframe>, <img>, <input>,
<ins>, <kbd>,<br>
<keygen>, <label>, <map>, <mark>, <meter>,
<br> <noscript>, <object>,
<output>, <picture>,<br>
<progress>, <q>, <ruby>, <s>,
<br> <samp>, <script>, <select>,
<small>,<br> <span>,
<strong>, <sub>, <sup>,
<br> <template>, <textarea>, <time>,
<br> <u>, <var>,
<video>, <wbr>, テキスト
エンベディッドコンテンツ<audio>, <canvas>, <embed>, <iframe>, <img>, <object>, <picture>, <video>
インタラクティブコンテンツ<a> (HTML 5.1ではhref属性がある場合に限る),
<br>, <audio> (controls属性がある場合),
<br>, <button>, <details>, <embed>, <iframe>,
<br>, <img> (usemap属性がある場合),
<br>, <input>(type=“hidden”の場合は除く),
<br>, <<keygen>, <label>,<br>
<object>
<br>(usemap属性がある場合)(HTML 5.1では除外),
<br>, <select>, <textarea>,
<video>(controls属性がある場合)

まとめ・この記事を読んでくださった方へ

この記事は私がブログを始めた頃、2014年に書いたものです。

ありがたいことに、いまだに毎月たくさんの人に読んでもらっています。 きっとコーディングで行き詰ってこの記事にたどり着いていると思うので、少しでもわかりやすくなるよう何度もメンテナンスしています。お役に立てたら幸いです^ ^。

最後まで、お読みいただきありがとうございました。