GalerieGratuit

Hover Zoom

Votre image grossit doucement dans son cadre quand la souris passe dessus ou quand le lien qui l'entoure reçoit le focus clavier, sans une ligne de JavaScript.

CSSTransform

Mis à jour le

Survolez ou cliquez la scène pour interagir

Cet effet est gratuit — la catégorie Galerie en contient 44 au total, dont 6 gratuits. Effect.Labs regroupe 840 effets vanilla. Découvrir la catégorie →

Exemples d'usage

① Cartes d'un carnet de randonnée — la photo s'approche au survol

QuandSur Talmerine, trois récits de randonnée sont alignés en cartes : photo, titre, une phrase, niveau, durée et dénivelé. Survoler une carte, n'importe où, rapproche la photo et souligne le titre.
PourquoiLe léger rapprochement dit « cette carte s'ouvre » sans bouton de plus ; l'effet porte sur la photo, la partie de la carte qui donne envie de partir.
RéglagesChaque carte est un lien qui entoure le cadre (.hzm-frame en <div>), --hzm-width: 100%, --hzm-ratio: 16/10, --hzm-radius: 8px, --hzm-scale: 1.12.
Atelier Lirandelle — rendus à corrigerTab pour parcourir les rendus
Taches d'aquarelle

Lavis humides — Clara M.

Aquarelle · exercice 3 sur 8 · déposé hier

À corriger
Lettres Ag en didone

Contraste des didones — Yanis B.

Typographie · exercice 4 sur 8 · déposé ce matin

Nouveau
Vase en terre cuite

Centrer la terre — Maëlle R.

Céramique · exercice 2 sur 8 · déposé lundi

Noté 15/20

② Rendus d'élèves d'une école d'art en ligne — corriger au Tab

QuandDans l'espace enseignant de l'Atelier Lirandelle, chaque rendu tient sur une ligne : vignette de l'œuvre, exercice et élève, avancement dans le cursus, étiquette « À corriger », « Nouveau » ou « Noté 15/20 ». En parcourant la liste au Tab, la vignette qui a le focus s'avance.
PourquoiLe professeur corrige souvent au clavier, d'un rendu à l'autre : sur une petite vignette, le zoom sert d'indicateur et montre où l'on est dans la liste, au clavier comme à la souris, sans cadre de surbrillance de plus.
Réglages.hzm-frame en lien, --hzm-width: 128px, --hzm-ratio: 16/9, --hzm-scale: 1.18, --hzm-duration: .35s ; contour de focus bleu clair ajouté par la scène.
Rayonnages de livres colorés
12e édition

Salon du livre de Brumerande

21 – 23 mars · Halle couverte · 140 éditeurs · entrée libre le dimanche

Billetterie

ProgrammeDédicacesVenir au salon

③ Bandeau d'un salon du livre — les rayonnages s'avancent

QuandLa page du Salon du livre de Brumerande s'ouvre sur un bandeau de rayonnages pleine largeur, avec l'étiquette « 12e édition », puis le nom du salon, les dates et le bouton « Billetterie ».
PourquoiSur une grande image, un zoom lent et faible donne de la profondeur sans distraire de la lecture des informations pratiques.
Réglages.hzm-frame en <div> (image non cliquable), --hzm-width: 100%, --hzm-ratio: 540/200, --hzm-radius: 0, --hzm-scale: 1.08, --hzm-duration: 1.2s.

Comment ça marche

Le cadre .hzm-frame coupe ce qui dépasse (overflow: hidden) et contient votre <img class="hzm-image">, recadrée comme une photo de couverture (object-fit: cover). Au survol, l'image passe à scale(var(--hzm-scale)), soit 1,3, en --hzm-duration (0,5 s) avec une courbe qui ralentit à la fin.

Par défaut le cadre est un lien <a> : remplacez href="#" par votre adresse. Le zoom se déclenche aussi quand le lien reçoit le focus au clavier, et quand on survole ou atteint au Tab un lien qui entoure le cadre, par exemple toute une carte d'article. Si l'image n'est pas cliquable, changez le <a> en <div> : le survol reste, le focus n'a plus lieu d'être.

Tout est en CSS rattaché à .fx-0179-root et au préfixe hzm- : autant de copies que voulu sur une page, aucun conflit avec vos propres classes. Le cadre prend la largeur disponible jusqu'à --hzm-width (280 px) et garde --hzm-ratio.

Accessibilité

  • Clavier : le lien se reçoit au Tab et le zoom s'affiche avec un contour blanc de focus (:focus-visible). Dans Safari, Tab n'atteint les liens que si l'option « Tab pour sélectionner chaque élément » est active (Option + Tab sinon).
  • Toucher : il n'y a pas de survol au doigt ; les navigateurs mobiles appliquent le survol au moment de la tape, juste avant d'ouvrir le lien. Le zoom n'est qu'un signe visuel, rien ne s'y cache.
  • Lecteurs d'écran : le lien prend pour nom le texte alternatif de l'image ; la légende « Hover Me » est masquée (aria-hidden).
  • Mouvement réduit : sous prefers-reduced-motion: reduce, la transition est retirée ; l'image passe directement à sa taille agrandie.

Compatibilité navigateur

CSS seul : transform, object-fit, aspect-ratio, :focus-visible (règle séparée pour ne pas faire tomber le survol dans les navigateurs qui ne la connaissent pas). Mesuré dans Chromium 151, Firefox 153 et WebKit 26.5 : deux copies indépendantes, zoom au survol et au focus clavier, mouvement réduit sans transition, aucun débordement à 390 px.

Chrome 88+✓ Complet (mesuré)
Firefox 89+✓ Complet (mesuré)
Safari 15+✓ Complet (moteur WebKit mesuré)
Edge 88+✓ Complet (moteur Chromium)
Mobile iOS 15+✓ Complet (moteur WebKit mesuré) — focus clavier dès 15.4
Android Chrome 88+✓ Complet (moteur Chromium)

Avant Safari 15.4, le zoom au focus clavier ne s'applique pas (le survol, si). Sans aspect-ratio, le cadre prend la hauteur de l'image.

Le code

Copiez les deux blocs (HTML et CSS) dans votre page. Aucun JavaScript, aucune dépendance.

HTML
<div class="fx-0179-root">
  <a class="hzm-frame" href="#">
    <img class="hzm-image" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='560' height='400' viewBox='0 0 560 400'%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop stop-color='%23667eea'/%3E%3Cstop offset='.5' stop-color='%23764ba2'/%3E%3Cstop offset='1' stop-color='%23f093fb'/%3E%3C/linearGradient%3E%3Cpattern id='s' width='20' height='20' patternUnits='userSpaceOnUse' patternTransform='rotate(45)'%3E%3Crect x='10' width='10' height='20' fill='%236366f1' fill-opacity='.1'/%3E%3C/pattern%3E%3Cpattern id='q' width='20' height='20' patternUnits='userSpaceOnUse'%3E%3Cpath d='M0 .5H20M.5 0V20' stroke='%23fff' stroke-opacity='.1'/%3E%3C/pattern%3E%3CradialGradient id='l' cx='168' cy='120' r='241' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23fff' stop-opacity='.3'/%3E%3Cstop offset='1' stop-color='%23fff' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='d' cx='392' cy='280' r='241' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-opacity='.2'/%3E%3Cstop offset='1' stop-opacity='0'/%3E%3C/radialGradient%3E%3Crect width='560' height='400' fill='url(%23g)'/%3E%3Crect width='560' height='400' fill='url(%23s)'/%3E%3Crect width='560' height='400' fill='url(%23q)'/%3E%3Crect width='560' height='400' fill='url(%23l)'/%3E%3Crect width='560' height='400' fill='url(%23d)'/%3E%3C/svg%3E" alt="Motif dégradé violet quadrillé" width="560" height="400">
    <span class="hzm-label" aria-hidden="true">Hover Me</span>
  </a>
</div>
CSS
/* fx-0179 — Hover Zoom: the image grows inside its frame on hover or keyboard focus (CSS only).
   Everything is scoped to .fx-0179-root and the hzm- prefix: two copies on one page stay independent. */
.fx-0179-root,
.fx-0179-root *,
.fx-0179-root *::before,
.fx-0179-root *::after {
  box-sizing: border-box;
}

.fx-0179-root {
  --hzm-scale: 1.3;          /* zoom level on hover / keyboard focus */
  --hzm-duration: 0.5s;      /* zoom-in and zoom-out time */
  --hzm-width: 280px;        /* maximum frame width (the frame shrinks on small screens) */
  --hzm-ratio: 7 / 5;        /* frame shape */
  --hzm-radius: 0.75rem;     /* frame corners */
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 250px;
  padding: 16px;
  position: relative;
  background: #0a0a0f;
  color: #fff;
  font-family: sans-serif;
}

/* Frame: fluid width (capped by --hzm-width), height from --hzm-ratio */
.hzm-frame {
  position: relative;
  display: block;
  width: 100%;
  max-width: var(--hzm-width);
  aspect-ratio: var(--hzm-ratio);
  border-radius: var(--hzm-radius);
  overflow: hidden;
  isolation: isolate;
  background: #12121a;
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.hzm-frame:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
}

/* Your image: any <img>, cropped to the frame like a cover photo */
.hzm-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  -webkit-user-select: none;
  user-select: none;
}

/* Optional caption over the image (delete the span if you do not want it) */
.hzm-label {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 600;
  font-size: 1.2rem;
  text-shadow: rgba(0, 0, 0, 0.3) 0 2px 4px;
  pointer-events: none;
}

.hzm-frame {
  cursor: pointer;
  color: inherit;
  text-decoration: none;
}

.hzm-image {
  transition: transform var(--hzm-duration) cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

/* Hover on the frame or on a link that wraps it */
.hzm-frame:hover .hzm-image,
.fx-0179-root a:hover .hzm-image {
  transform: scale(var(--hzm-scale));
}
/* Keyboard focus on the frame (a link) or on a link that wraps it (separate rule: older browsers skip it alone) */
.hzm-frame:focus-visible .hzm-image,
.fx-0179-root a:focus-visible .hzm-image {
  transform: scale(var(--hzm-scale));
}

/* Reduced motion: the image still zooms, without the transition */
@media (prefers-reduced-motion: reduce) {
  .hzm-image {
    transition: none;
  }
}
JavaScript

CSS pur — aucun JavaScript requis.

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
Image (HTML — src de .hzm-image) motif violet quadrillé (SVG intégré) Votre photo et son alt, qui nomme aussi le lien.
--hzm-scale 1.3 Grossissement au survol ; 1.05 à 1.15 pour des cartes, 1.3 pour un effet marqué.
--hzm-duration 0.5s Durée de l'aller et du retour ; 1s et plus pour une grande image.
--hzm-width · --hzm-ratio · --hzm-radius 280px · 7 / 5 · 0.75rem Largeur maximale du cadre (il rétrécit sur petit écran), proportions et arrondi.
Balise du cadre <a href="#"> Mettez votre adresse ; ou une <div> si l'image n'est pas un lien, ou placez le cadre dans un lien plus large (carte entière).
Légende .hzm-label « Hover Me » Texte centré sur l'image ; supprimez le <span> sur une vraie photo.

FAQ

Faut-il du JavaScript ?

Non. Tout tient dans le CSS : :hover et :focus-visible déclenchent le transform, le cadre coupe l'excédent.

Comment zoomer quand on survole toute la carte ?

Entourez le cadre et le texte d'un même lien placé dans .fx-0179-root : la règle .fx-0179-root a:hover .hzm-image agrandit l'image dès que la carte est survolée.

L'image devient-elle floue ?

Seulement si le fichier est juste à la taille du cadre. Prévoyez une image 1,3 fois plus large (ou la valeur de --hzm-scale).