A way to change how something looks only while your mouse is over it—so links and buttons clearly feel “clickable” and responsive.
マウスカーソルが要素の上に乗っている間だけ、色や下線、影などの見た目を切り替えて「ここ押せます」「反応しています」を分かりやすく伝えられる仕組みです。
:hover は「マウス(や指の代わりになる操作)が要素の上に乗っている間だけ、見た目を切り替える」ためのスイッチです。
リンクにカーソルを当てたら色が変わる、ボタンに当てたら少し浮く、カードに当てたら影が出る──みたいな “触れた感” を作れます。
CSS
a:hover {
color: red;
}
a:hover)が「どれに・どんな状態のとき」{ ... })が「そのとき何を変えるか」:hover が発動する瞬間
Sample Link
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);
}
transition を入れると「急に変わる」ではなく「スッ…」となって気持ちよくなります。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);
}
CSS
.menuItem:hover {
background: rgba(0, 0, 0, 0.06);
}
これができると一気に表現が広がります。
CSS
.card:hover .cardTitle {
text-decoration: underline;
}
.card:hover .cardIcon {
transform: rotate(8deg);
}
:hover は 親につけて、変えるのは 子、がよくあるパターンです。ここにマウスを乗せてください
HTML
<div class="cardParent">
<p class="cardText">ここにマウスを乗せてください</p>
</div>
.cardParent が 親.cardText が 子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);
}
}
hover: hover は「ホバーできる」pointer: fine は「マウスみたいに細かいポインター」例えば、メニューをホバーで表示するとき、表示エリアが狭いと「出した瞬間に外れて消える」ことがあります。
コツ:ホバー判定を “親の広い箱” に持たせる。
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;
}
どういう問題か(先に状況)
これは 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;
}
なぜ消えるのか(重要)
.menuLabel だけ.menuLabel から外れる.menuPanel が消えるつまり、
出した本人からカーソルが離れた時点で消えている
考え方(超重要)
hover の判定は 「表示したい要素すべてを包む親」 に持たせる
HTML(親でまとめる)
<div class="menu">
<div class="menuLabelOk">メニュー</div>
<div class="menuPanelOk">項目A / 項目B</div>
</div>
.menu が hover 判定の親CSS(正解パターン・最小構成)
.menu {
display: inline-block;
}
.menuPanelOk {
display: none;
padding: 8px;
background: #eee;
}
.menu:hover .menuPanelOk {
display: block;
}
これで何が変わったか
.menu.menu の中all は想像以上に色々アニメーション対象になり、重くなったり、変な動きになりやすいです。
変える予定のプロパティだけ指定するのが安全です。
CSS
transition: transform 120ms, box-shadow 120ms;
マウスだけ反応するのは不親切になりがちです。
キーボードで 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;
}
:focus-visible は「キーボード操作のとき中心」に出やすいフォーカス表現です。例: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);
}
}
ホバーで動かすなら、できるだけ top/left より transform を使うほうが滑らかになりやすいです。
CSSは基本的に より具体的(specific)なセレクタ、もしくは 後に書いたもの が勝ちやすいです。
.button:hover より a.button:hover のほうが強いことがある運用のコツ:
ホバーのルールは、コンポーネント単位でまとまって置く(散らかると事故りやすい)。
position や z-index で上に何かがいる)pointer-events: none; が入っている<a> に display: inline; のままで、ホバーさせたい範囲が思ったより狭い(→ display: inline-block; で範囲を作る)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;
}
:active)も自然に