CSS

A way to change how something looks only while your mouse is over it—so links and buttons clearly feel “clickable” and responsive.

:hover

マウスカーソルが要素の上に乗っている間だけ、色や下線、影などの見た目を切り替えて「ここ押せます」「反応しています」を分かりやすく伝えられる仕組みです。

:hover とは?

:hover は「マウス(や指の代わりになる操作)が要素の上に乗っている間だけ、見た目を切り替える」ためのスイッチです。

リンクにカーソルを当てたら色が変わる、ボタンに当てたら少し浮く、カードに当てたら影が出る──みたいな “触れた感” を作れます。

いちばん基本の形(書き方の型)

CSS

a:hover {
    color: red;
}

:hover が発動する瞬間

初心者が最初に覚える “気持ちいい” 例

リンク:色と下線を変えて「押せる」を伝える

CSS

a {
    color: #0b57d0;
    text-decoration: underline;
}

a:hover {
    text-decoration: none;
}

ボタン:少しだけ浮かせる(影+上にズラす)

CSS

.button {
    display: inline-block;
    padding: 12px 16px;
    border-radius: 10px;
    background: #111;
    color: #fff;
    text-decoration: none;
    transition: transform 120ms, box-shadow 120ms;
}

.button:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.18);
}

カード:全体が反応してクリックできそうに見える

Sample Card

CSS

.card {
    border-radius: 14px;
    padding: 16px;
    border: 1px solid rgba(0, 0, 0, 0.12);
    transition: transform 120ms, box-shadow 120ms;
}

.card:hover {
    transform: translateY(-3px);
    box-shadow: 0 14px 24px rgba(0, 0, 0, 0.12);
}

“どこに hover を書く?” でつまずかないコツ

自分自身がホバーされたら

CSS

.menuItem:hover {
    background: rgba(0, 0, 0, 0.06);
}

親がホバーされたら、子を変える

これができると一気に表現が広がります。

CSS

.card:hover .cardTitle {
    text-decoration: underline;
}

.card:hover .cardIcon {
    transform: rotate(8deg);
}

ここにマウスを乗せてください

HTML

<div class="cardParent">
	<p class="cardText">ここにマウスを乗せてください</p>
</div>

CSS

.cardParent {
    padding: 16px;
    border-radius: 12px;
    border: 1px solid #ccc;
}

.cardParent:hover .cardText {
    color: red;
}

何が起きているか

CSS

.cardParent:hover .cardText {
}

この1行は、意味としてはこうです。

.cardParent にマウスが乗っている その間だけ、中にある .cardText にこのスタイルを適用する

初心者が混乱しやすい点

よくある落とし穴(ここだけ先に押さえると事故が減ります)

スマホで “hover” はどうなる?

スマホはマウスがないので 常に同じ挙動にはなりません。

端末やブラウザによっては、タップで一瞬ホバー状態っぽくなったり、ならなかったりします。

実務のおすすめ:

ホバーは「あると嬉しい」くらいにして、ホバーがなくても困らない見た目を基本にします。

さらに丁寧にやるなら、ホバーできる端末だけに限定します:

CSS

@media (hover: hover) and (pointer: fine) {
    .button:hover {
        transform: translateY(-2px);
    }
}

“ホバーで出てきた要素” にカーソルを乗せると消える問題

例えば、メニューをホバーで表示するとき、表示エリアが狭いと「出した瞬間に外れて消える」ことがあります。

コツ:ホバー判定を “親の広い箱” に持たせる。

CSS

.menu {
    position: relative;
    display: inline-block;
}

.menuPanel {
    position: absolute;
    top: 100%;
    left: 0;
    display: none;
    padding: 10px;
    border-radius: 10px;
    background: #fff;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12);
}

.menu:hover .menuPanel {
    display: block;
}
NG例:ホバーで出した瞬間に、カーソルを乗せると消えるパターン

どういう問題か(先に状況)

これは hover の判定が狭すぎる のが原因です。

HTML(よくある失敗構造)

<div class="menuLabelNg">メニュー</div>
<div class="menuPanelNg">項目A / 項目B</div>

CSS(NGパターン)

.menuPanelNg {
    display: none;
    padding: 8px;
    background: #eee;
}

.menuLabelNg:hover + .menuPanelNg {
    display: block;
}

なぜ消えるのか(重要)

つまり、

出した本人からカーソルが離れた時点で消えている

OK例:親を大きくして、その中で完結させる(王道解決)

考え方(超重要)

hover の判定は 「表示したい要素すべてを包む親」 に持たせる

HTML(親でまとめる)

<div class="menu">
	<div class="menuLabelOk">メニュー</div>
	<div class="menuPanelOk">項目A / 項目B</div>
</div>

CSS(正解パターン・最小構成)

.menu {
	display: inline-block;
}

.menuPanelOk {
	display: none;
	padding: 8px;
	background: #eee;
}

.menu:hover .menuPanelOk {
	display: block;
}

これで何が変わったか

transition: all は便利そうで地雷

all は想像以上に色々アニメーション対象になり、重くなったり、変な動きになりやすいです。

変える予定のプロパティだけ指定するのが安全です。

CSS

transition: transform 120ms, box-shadow 120ms;

:hover と相性がいい “セット技”

:focus / :focus-visible とセットで「キーボード操作でも同じ体験」

マウスだけ反応するのは不親切になりがちです。

キーボードで Tab 移動している人にも「今ここにいる」を見せると使いやすいです。

CSS

.link {
    outline: none;
    text-decoration: underline;
}

.link:hover,
.link:focus-visible {
    text-decoration: none;
    box-shadow: 0 0 0 3px rgba(11, 87, 208, 0.25);
    border-radius: 6px;
}

“ホバーできるなら hover、できないなら常に表示” の考え方

例:PCではホバーで説明を出すけど、スマホでは最初から見せておく。

CSS

.tip {
    opacity: 0;
    transform: translateY(2px);
    transition: opacity 120ms, transform 120ms;
}

@media (hover: hover) and (pointer: fine) {
    .card:hover .tip {
        opacity: 1;
        transform: translateY(0);
    }
}

@media (hover: none) {
    .tip {
        opacity: 1;
        transform: translateY(0);
    }
}

アニメーションは “transform と opacity” が基本的に軽い

ホバーで動かすなら、できるだけ top/left より transform を使うほうが滑らかになりやすいです。

:hover の“優先順位”と衝突

同じ要素に hover が複数当たるとき

CSSは基本的に より具体的(specific)なセレクタ、もしくは 後に書いたもの が勝ちやすいです。

運用のコツ:

ホバーのルールは、コンポーネント単位でまとまって置く(散らかると事故りやすい)。

:hover が効かないときの典型

例:実務っぽい「ボタン」を :hover と :focus-visible でまとめる

CSS

.btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 12px 16px;
    border-radius: 12px;
    background: #111;
    color: #fff;
    text-decoration: none;
    transition: transform 120ms, box-shadow 120ms, opacity 120ms;
}

.btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 4px rgba(11, 87, 208, 0.30);
}

@media (hover: hover) and (pointer: fine) {
    .btn:hover {
        transform: translateY(-2px);
        box-shadow: 0 12px 22px rgba(0, 0, 0, 0.16);
    }
}

.btn:active {
    transform: translateY(0);
    opacity: 0.92;
}