CSS
この記事では「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
マウスカーソルが要素の上に乗っている間だけ、色や下線、影などの見た目を切り替えて「ここ押せます」「反応しています」を分かりやすく伝えられる仕組みです。
- Table Of Contents
:hover とは?
: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);
}
“どこに hover を書く?” でつまずかないコツ
自分自身がホバーされたら
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は 子ではなく親につけている- 実際に変わっているのは 子
よくある落とし穴(ここだけ先に押さえると事故が減ります)
スマホで “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;
}
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;
}
なぜ消えるのか(重要)
- hover 判定は
.menuLabelだけ - カーソルを下に動かした瞬間
.menuLabelから外れる- hover が解除
.menuPanelが消える
つまり、
出した本人からカーソルが離れた時点で消えている
OK例:親を大きくして、その中で完結させる(王道解決)
考え方(超重要)
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;
}
これで何が変わったか
- hover 判定は
.menu - カーソルが
- ラベルの上
- パネルの上
どちらにあっても.menuの中
→ 消えない
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;
}
:focus-visibleは「キーボード操作のとき中心」に出やすいフォーカス表現です。
“ホバーできるなら 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)なセレクタ、もしくは 後に書いたもの が勝ちやすいです。
.button:hoverよりa.button:hoverのほうが強いことがある- 同じ強さなら、後に書いたルールが勝つ
運用のコツ:
ホバーのルールは、コンポーネント単位でまとまって置く(散らかると事故りやすい)。
:hover が効かないときの典型
- その要素が 透明な別要素に覆われている(
positionやz-indexで上に何かがいる) - クリック用の要素が別で、実際にホバーしているのがそっちではない
pointer-events: none;が入っている<a>にdisplay: inline;のままで、ホバーさせたい範囲が思ったより狭い(→display: inline-block;で範囲を作る)
例:実務っぽい「ボタン」を :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;
}
- PCはホバーで気持ちよく
- キーボードでも分かりやすく
- 押した瞬間(
:active)も自然に