CSSでリンク範囲を親要素全体に広げる簡単な方法を解説

PCで検索

「カード全体をクリックできるようにしたい」「リストの行のどこを押してもリンクが反応してほしい」——Web制作をしていると、こういう要望は本当によく出てきます。テキストの文字部分しかクリックできないと、特にスマホでは押しづらくて地味にストレスですよね。

そこでこの記事では、リンク(aタグ)のクリック範囲を親要素全体に広げる方法を、私がふだん使っている書き方でまとめておきます。JavaScriptは使わず、HTMLとCSSだけで完結します。

方法は大きく2通りあります。用途に合わせて選べるように、両方を順番に紹介していきますね。

方法1:aタグを絶対配置して親要素いっぱいに広げる

まず定番のやり方です。親要素の中に空の`a`タグを置いて、それを親いっぱいに引き伸ばして「見えないクリック層」にする、という発想です。

HTML

<div class="card">
    <h3>記事のタイトル</h3>
    <p>ここに説明テキストが入ります。</p>
    <a href="article.html" aria-label="記事のタイトルを読む"></a>
</div>

`div`の中にコンテンツを置き、最後に空の`a`タグを1つ入れています。この`a`タグが、あとでカード全体を覆うクリック領域になります。

ひとつ注意したいのがアクセシビリティです。中身が空のリンクは、スクリーンリーダーで「リンク」としか読まれず、どこへ飛ぶのか伝わりません。そこで`aria-label`でリンクの行き先を補っておくと安心です。(MDNでも、リンクの中身はどこへ遷移するのかが分かる文言にすべきだと明記されています)

CSS

.card {
    position: relative;
}
.card a {
    position: absolute;
    inset: 0;
}

これだけです。昔は`top: 0; left: 0; width: 100%; height: 100%;`と4行書くのが定番でしたが、今は`inset: 0`の1行でスッキリ書けます。

CSSのポイント

  • 親に position: relative;
    `position: absolute;`を指定した要素は「一番近い、位置指定された祖先」を基準に配置されます。親の`div`に`position: relative;`を付けておくことで、`a`タグがこの`div`を基準に置かれるようになります。これを忘れると、ページ全体を基準にリンクが飛んでいってしまうので要注意です。
  • 子に position: absolute; と inset: 0;
    `inset: 0;`は`top: 0; right: 0; bottom: 0; left: 0;`をまとめた書き方です。絶対配置された要素は、上下(`top`と`bottom`)・左右(`left`と`right`)の両方を`0`にすると、幅・高さを指定しなくても親の領域いっぱいまで自動で広がります。この挙動はMDNのpositionの解説でも説明されている、CSSの正式な仕様です。だから`width`や`height`を書かなくても大丈夫なんですね。

この方法は、カードの中に別のリンク(「詳細はこちら」ボタンなど)を置きたくないシンプルなケースにぴったりです。

方法2:aタグでブロックごと囲む

実はもうひとつ、もっと素直な方法があります。`a`タグで`div`ごとまるっと囲んでしまうやり方です。

<a href="article.html" class="card-link">
    <div class="card">
        <h3>記事のタイトル</h3>
        <p>ここに説明テキストが入ります。</p>
    </div>
</a>

「`a`の中に`div`を入れていいの?」と不安になるかもしれませんが、これはHTML5以降は正式に有効です。`a`タグは「透過的コンテンツモデル(transparent content model)」といって、周囲で許可されている要素なら中に入れてOKというルールになっています。MDNの`a`要素の解説でも、ブロック要素を含められることが明記されています。

この方法なら、余計なCSSはほとんど不要で、リンクテキストも自然に持てるのでアクセシビリティ的にも扱いやすいです。

ただし透過的コンテンツモデルには例外があります。`a`の中に、別の`a`やボタン・入力欄などの「操作できる要素(インタラクティブコンテンツ)」は入れられません。カードの中にさらに別リンクやボタンを置きたいときは、この方法ではなく方法1を選ぶことになります。

どちらを使えばいい?

私の使い分けはこんな感じです。

  • カードの中に他のリンクやボタンを置かない → 方法2(`a`で丸ごと囲む)がシンプルでおすすめ
  • カードの中に別のリンクやボタンも共存させたい → 方法1(`inset: 0`で覆う)を選ぶ

どちらもよく使う場面は共通していて、ニュース記事や商品紹介のカード、`li`で囲んだナビゲーションメニュー、バナー広告などです。特にスマホでは指でタップする以上、押せる範囲が広いほど操作しやすくなります。ちょっとした工夫ですが、使い勝手ははっきり変わりますよ。

まとめ

リンクのクリック範囲を親要素全体に広げる方法を2つ紹介しました。

  • 方法1:親に`position: relative;`、空の`a`に`position: absolute; inset: 0;`
  • 方法2:`a`タグでブロックごと囲む(中に別リンク・ボタンがない場合)

どちらもHTMLとCSSだけで手軽に実装できます。空リンクを使うときは`aria-label`で行き先を補うのを忘れずに。用途に合わせて選んで、押しやすいリンク設計に役立ててみてください。