How to show an element on hover
Short answer
Hide the element and show it when the pointer is over the parent:
<style>
.card { position: relative; width: 200px; }
.card img { display: block; width: 100%; border-radius: 8px; }
.card .actions { position: absolute; inset: auto 8px 8px; display: none; }
.card:hover .actions { display: block; }
</style>
<div class="card">
<img src="/media/photo-400x250.jpg" alt="A flower">
<div class="actions"><button>♥ Like</button></div>
</div>A smooth appearance
display does not animate, so opacity and transition are used for smoothness:
<style>
.tip { opacity: 0; transition: opacity 0.3s; }
.item:hover .tip, .item:focus-within .tip { opacity: 1; }
</style>
<div class="item">
<button>Hover or Tab here</button>
<span class="tip">Saved to favorites</span>
</div>:focus-within also shows the hint when moving with Tab — without it a keyboard user never sees it.
Touch screens
A phone has no hover. Hide on hover only secondary things, and on devices without a mouse show everything at once with the @media (hover: none) media query.
Common mistake
Buttons inside a card are shown only on :hover. A keyboard user lands on an invisible button and does not know where they are, and on a phone it cannot be reached at all. Add a :focus-within rule next to :hover and think about whether the effect is needed on touch screens.
Functions used in this recipe
- :hover — Matches an element while the mouse pointer is over it.
- opacity — The transparency of the whole element together with its content.
- transition — Animates the change of a property from the old value to the new one.
- :focus — Matches the element that currently has focus: a field being typed into, a button selected with Tab.
- visibility — Hides an element but keeps the space it occupies.