
In questo articolo analizzeremo passo dopo passo un effetto hover animato per una card prodotto, realizzato con HTML e CSS puri. Si tratta di un design dal look moderno e accattivante, dove l’elemento principale è un’immagine (in questo caso, di una scarpa Nike) che si muove quando il puntatore del mouse si trova sulla card. Questo tipo di effetto è molto utile in siti e-commerce, landing page o portfolio, perché permette di mettere in risalto in modo dinamico l’oggetto presentato, aggiungendo al contempo dettagli come taglie, colori e un pulsante di acquisto.
Lo scopo dell’articolo è:
- Presentare il codice e spiegarne i passaggi salienti.
- Mostrare perché queste tecniche sono state scelte.
- Fornire use-case reali per l’utilizzo di un effetto simile.
- Offrire consigli su come personalizzare e integrare la card in progetti concreti.
Alla fine, troverai il codice completo (HTML e CSS) pronto per essere copiato e incollato nel tuo progetto. Durante l’articolo, riporteremo alcuni frammenti di codice parziali per spiegare meglio i singoli aspetti. Per eventuali riferimenti approfonditi a proprietà CSS o best practice front-end, troverai link utili a fonti autorevoli come MDN, CSS Tricks e web.dev.
1. Struttura HTML di base per questo effetto hover card prodotto
Iniziamo dal markup principale della card. Abbiamo un contenitore .container
e, al suo interno, una .card
che ospiterà immagine e contenuti testuali. Il codice minimal è il seguente:
<div class="container">
<div class="card">
<div class="imgBx">
<img src="https://assets.codepen.io/4164355/shoes.png" alt="Nike Shoes">
</div>
<div class="contentBx">
<h2>Nike Shoes</h2>
<div class="size">
<h3>Size :</h3>
<span>7</span>
<span>8</span>
<span>9</span>
<span>10</span>
</div>
<div class="color">
<h3>Color :</h3>
<span></span>
<span></span>
<span></span>
</div>
<a href="#">Buy Now</a>
</div>
</div>
</div>
Perché questa struttura?
imgBx
funge da contenitore per l’immagine, posizionata tramite CSS conposition: absolute
e animazioni basate sutransform
.contentBx
contiene il titolo, la selezione della taglia (size), la selezione del colore (color) e un link per l’acquisto.- I vari
span
all’interno di.size
e.color
sono usati come elementi cliccabili o comunque visualizzano informazioni aggiuntive (p.e. dimensioni, varianti di colore). - La
card
è incapsulata in undiv.container
che gestisce l’allineamento e lo “spazio” esterno conposition: relative
.
Questa separazione tra struttura (HTML) e presentazione (CSS) facilita la leggibilità del codice e l’estensibilità futura.
2. Impostazione del layout e sfondo
La parte iniziale del CSS si occupa di resettare lo stile base e di impostare un font globale:
* {
font-family: 'Poppins', sans-serif;
}
Successivamente, si definisce il layout del body
:
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #131313;
}
Usare display: flex
a livello di body
è un metodo semplice per centrare orizzontalmente e verticalmente il contenuto, impostando anche min-height: 100vh
in modo che la pagina utilizzi tutta l’altezza disponibile. Lo sfondo scuro (#131313
) enfatizza l’effetto hover e fa risaltare la card.
3. Le dimensioni e l’animazione della card
.container .card {
position: relative;
width: 320px;
height: 450px;
background: #232323;
border-radius: 20px;
overflow: hidden;
}
- Dimensioni fisse (320x450px) per una card di medie dimensioni.
border-radius: 20px
ammorbidisce gli angoli.overflow: hidden
fa sì che gli elementi in posizione assoluta (soprattutto lo pseudo-elemento colorato che vedremo tra poco) non escano fuori dal perimetro della card.
L’effetto clip-path
Uno degli elementi più interessanti è l’effetto che il codice crea con lo pseudo-elemento :before
. Ecco uno scorcio del CSS corrispondente:
.container .card:before {
content: '';
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background: #9bdc28;
clip-path: circle(150px at 80% 20%);
transition: 0.5s ease-in-out;
}
.container .card:hover:before {
clip-path: circle(300px at 80% -20%);
}
:before
crea un livello in sovrimpressione colorato di verde lime (#9bdc28
).- Usando
clip-path: circle()
, ritagliamo un cerchio di raggio 150px posizionato a80%
da sinistra e20%
dall’alto. - Al passaggio del mouse, il cerchio si espande fino a 300px e si sposta verticalmente (
-20%
dall’alto). In questo modo, il colore lime si diffonde creando un effetto di luce o “aura” attorno all’immagine.
Se vuoi approfondire clip-path
, puoi consultare la guida MDN o la sezione dedicata su CSS Tricks.
4. Lo pseudo-elemento :after
e il testo in trasparenza
.container .card:after {
content: 'Nike';
position: absolute;
top: 30%; left: -20%;
font-size: 12em;
font-weight: 800;
font-style: italic;
color: rgba(255,255,25,0.05);
}
Qui vediamo come un secondo pseudo-elemento (:after
) venga utilizzato per mostrare un testo gigante e quasi trasparente (“Nike”), donando un aspetto grafico “di sfondo”. Questa è una tecnica di design molto comune per aggiungere elementi decorativi senza appesantire l’HTML.
5. Gestione dell’immagine (la scarpa)
HTML dedicato
<div class="imgBx">
<img src="./shoes.png" alt="Nike Shoes">
</div>
CSS di .imgBx
.container .card .imgBx {
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 10000;
width: 100%;
height: 220px;
transition: 0.5s;
}
.container .card:hover .imgBx {
top: 0%;
transform: translateY(0%);
}
position: absolute;
e l’uso ditop: 50%; transform: translateY(-50%)
servono per centrare verticalmente l’immagine nella card.- In
hover
, laimgBx
passa atop: 0%
, quindi si sposta in alto, azzerando anche iltransform: translateY(0%)
.
Rotazione e dimensioni dell’immagine
.container .card .imgBx img {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%) rotate(-25deg);
width: 270px;
}
Questo “doppio transform” serve per centrare l’immagine al 50% di .imgBx
(sia in verticale che in orizzontale) e inclinarla leggermente con rotate(-25deg)
, dando un effetto dinamico. La larghezza è settata a 270px
; regola questo valore in base alla risoluzione dell’immagine.
6. Sezione contentBx
: titoli, taglie, colori e pulsante
Mostrare dettagli all’hover
L’idea è che, da default, l’area inferiore (con le taglie, i colori e il pulsante di acquisto) sia più piccola (100px) e con alcuni elementi a opacity: 0; visibility: hidden;
. Al passaggio del mouse, la card si espande fino a 210px di altezza e i dettagli appaiono gradualmente. Ecco uno snippet esemplificativo:
.container .card .contentBx {
position: absolute;
bottom: 0;
width: 100%;
height: 100px;
text-align: center;
transition: 1s;
z-index: 10;
}
.container .card:hover .contentBx {
height: 210px;
}
Allo stesso modo:
.container .card .contentBx .size,
.container .card .contentBx .color {
display: flex;
justify-content: center;
align-items: center;
padding: 8px 20px;
opacity: 0;
visibility: hidden;
transition: 0.5s;
}
.container .card:hover .contentBx .size {
opacity: 1;
visibility: visible;
transition-delay: 0.5s;
}
.container .card:hover .contentBx .color {
opacity: 1;
visibility: visible;
transition-delay: 0.6s;
}
opacity: 0; visibility: hidden;
nasconde completamente l’elemento e evita che possa interferire con altri elementi sulla pagina.- In
hover
, questi valori passano aopacity: 1; visibility: visible;
, con un ritardo (transition-delay
) per creare un arrivo sfalsato e più “naturale”.
Infine, il link “Buy Now” compare con una transizione simile. Invece di animarne l’opacità e la visibilità, si aggiunge anche un transform: translateY(50px)
-> translateY(0px)
per un effetto di “slittamento verso l’alto”:
.container .card .contentBx a {
display: inline-block;
padding: 10px 20px;
background: #fff;
border-radius: 4px;
margin-top: 10px;
text-decoration: none;
font-weight: 600;
color: #111;
opacity: 0;
transform: translateY(50px);
transition: 0.5s;
}
.container .card:hover .contentBx a {
opacity: 1;
transform: translateY(0px);
transition-delay: 0.75s;
}
7. Use-case reali e adattabilità
- E-commerce: Perfetto per mostrare prodotti con poche info base, che diventano più visibili al passaggio del mouse (taglie, colore, pulsante d’acquisto).
- Landing page: Quando desideri un focus immediato su un’offerta o un prodotto hero. L’immagine in primo piano cattura l’attenzione e l’utente può interagire per vedere i dettagli.
- Portfolio: Potresti mostrare anteprime di progetti e, all’hover, rivelare descrizioni, link e data di realizzazione.
- Gallerie interattive: Un insieme di card simili su una pagina, ognuna con le proprie transizioni personalizzate (colori, immagini, testi diversi).
Personalizzazioni possibili
- Cambia la forma di
clip-path
: non solocircle()
, ma anchepolygon()
oellipse()
. - Ritocca durata e easing:
transition: 1s ease-in-out;
,transition-delay: 0.2s;
ecc. per un feeling diverso. - Mobile-first: Su dispositivi touch, l’hover non esiste. Potresti implementare un tap per espandere la card. Usa media query o JS per adattare il comportamento su schermi più piccoli.
- Palette colore e tipografia: Se preferisci un brand color diverso, basta sostituire
#9bdc28
. Seleziona i tuoi font da Google Fonts aggiungendoli nella sezione@import
.
Se vuoi approfondire come gestire animazioni e transizioni in maniera efficiente, dai uno sguardo alla guida web.dev su animazioni CSS e ai tutorial su transizioni di CSS Tricks.
8. Codice completo (HTML + CSS) per questo effetto hover card prodotto!
Riassumendo tutti gli snippet visti finora, ecco il codice completo pronto per essere copiato e incollato nei tuoi progetti. Ricorda di includere il link a Google Fonts per Poppins o qualsiasi altro font desideri usare.
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Card Hover Effect - Esempio</title>
</head>
<body>
<div class="container">
<div class="card">
<div class="imgBx">
<img src="./shoes.png" alt="Nike Shoes">
</div>
<div class="contentBx">
<h2>Nike Shoes</h2>
<div class="size">
<h3>Size :</h3>
<span>7</span>
<span>8</span>
<span>9</span>
<span>10</span>
</div>
<div class="color">
<h3>Color :</h3>
<span></span>
<span></span>
<span></span>
</div>
<a href="#">Buy Now</a>
</div>
</div>
</div>
</body>
</html>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@100;200;300;400;500;600;700;800;900&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #131313;
}
.container {
position: relative;
}
.container .card {
position: relative;
width: 320px;
height: 450px;
background: #232323;
border-radius: 20px;
overflow: hidden;
}
.container .card:before {
content: '';
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background: #9bdc28;
clip-path: circle(150px at 80% 20%);
transition: 0.5s ease-in-out;
}
.container .card:hover:before {
clip-path: circle(300px at 80% -20%);
}
.container .card:after {
content: 'Nike';
position: absolute;
top: 30%;
left: -20%;
font-size: 12em;
font-weight: 800;
font-style: italic;
color: rgba(255,255,25,0.05);
}
.container .card .imgBx {
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 10000;
width: 100%;
height: 220px;
transition: 0.5s;
}
.container .card:hover .imgBx {
top: 0%;
transform: translateY(0%);
}
.container .card .imgBx img {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%) rotate(-25deg);
width: 270px;
}
.container .card .contentBx {
position: absolute;
bottom: 0;
width: 100%;
height: 100px;
text-align: center;
transition: 1s;
z-index: 10;
}
.container .card:hover .contentBx {
height: 210px;
}
.container .card .contentBx h2 {
font-weight: 600;
letter-spacing: 1px;
color: #fff;
margin: 10px 0;
}
.container .card .contentBx .size,
.container .card .contentBx .color {
display: flex;
justify-content: center;
align-items: center;
padding: 8px 20px;
opacity: 0;
visibility: hidden;
transition: 0.5s;
}
.container .card:hover .contentBx .size {
opacity: 1;
visibility: visible;
transition-delay: 0.5s;
}
.container .card:hover .contentBx .color {
opacity: 1;
visibility: visible;
transition-delay: 0.6s;
}
.container .card .contentBx .size h3,
.container .card .contentBx .color h3 {
color: #fff;
font-weight: 300;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 2px;
margin-right: 10px;
}
.container .card .contentBx .size span {
width: 26px;
height: 26px;
text-align: center;
line-height: 26px;
font-size: 14px;
display: inline-block;
background: #fff;
color: #111;
margin: 0 5px;
border-radius: 4px;
cursor: pointer;
transition: 0.5s;
}
.container .card .contentBx .size span:hover {
background: #9bdc28;
}
.container .card .contentBx .color span {
width: 20px;
height: 20px;
background: #ff0;
border-radius: 50%;
margin: 0 5px;
cursor: pointer;
}
.container .card .contentBx .color span:nth-child(2) {
background: #9bdc28;
}
.container .card .contentBx .color span:nth-child(3) {
background: #03a9f4;
}
.container .card .contentBx a {
display: inline-block;
padding: 10px 20px;
background: #fff;
border-radius: 4px;
margin-top: 10px;
text-decoration: none;
font-weight: 600;
color: #111;
opacity: 0;
transform: translateY(50px);
transition: 0.5s;
}
.container .card:hover .contentBx a {
opacity: 1;
transform: translateY(0px);
transition-delay: 0.75s;
}
Puoi adattare facilmente questo layout a un contesto con più card (e più prodotti), oppure trasformarlo in un componente di React/Vue/Angular, mantenendo la stessa logica di base e integrandolo nei tuoi processi di build.
Conclusione
L’effetto hover che abbiamo analizzato conferma come sia possibile ottenere risultati sorprendenti usando solo HTML e CSS, senza necessità di JavaScript per animazioni di base. L’approccio si presta a:
- Migliorare la UX: L’utente “scopre” i dettagli del prodotto in modo graduale, riducendo il disordine visivo.
- Ridurre la complessità: Meno dipendenze esterne, meno overhead.
- Personalizzare a volontà: Forme, durate, testi, colori e layout possono essere modificati per adattarsi al tuo brand o progetto.
Se vuoi ulteriori spunti, ti consiglio di esplorare l’uso di clip-path
con altre forme, leggere la guida di CSS Tricks sulle animazioni e approfondire le best practice di performance su web.dev.
Con questo hai a disposizione un progetto di base da cui partire. Sperimenta con i parametri e integra la card nel tuo e-commerce o portfolio. Vedrai che l’effetto visivo e l’esperienza utente ne trarranno grande beneficio.