Boutons✨ Premium

Border Draw

Au survol, quatre traits de 2 px dessinent un cadre indigo autour du bouton : le haut et le bas en 300 ms, puis les deux côtés en 300 ms de plus. Deux pseudo-éléments, deux spans, aucune ligne de JavaScript.

CSSHoverBorder

Mis à jour le

Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Boutons comprend 27 effets, dont 2 gratuits. Découvrir la catégorie →

3 exemples d'usage

S'abonner — bloc newsletter d'un pied de page — Border Draw exemple 1

① S'abonner — bloc newsletter d'un pied de page

QuandPied de page sombre : un titre, un champ e-mail et le bouton d'envoi, sur une colonne.
PourquoiLe bouton transparent ne concurrence pas le champ ; le cadre qui se trace au survol confirme la cible sans ajouter de couleur pleine dans une zone déjà dense. Le cas d'usage était déjà noté sur l'ancienne fiche.
RéglagesCouleur #818cf8 (6,6:1 sur fond sombre), border-radius: 0 pour un cadre fermé, .25s par phase.
Voir la démo — action secondaire d'un hero — Border Draw exemple 2

② Voir la démo — action secondaire d'un hero

QuandHero de produit avec deux boutons : un plein pour commencer, un transparent pour la démo.
PourquoiLa hiérarchie primaire / secondaire tient toute seule : le bouton plein attire le premier regard, le bouton contour ne prend de la présence qu'au survol. Le cadre ouvert aux angles rappelle la forme arrondie du bouton plein voisin.
RéglagesTraits de 1 px (height: 1px / width: 1px), couleur currentColor pour hériter du texte, 400 ms par phase.
Essayer 14 jours — carte de tarif non mise en avant — Border Draw exemple 3

③ Essayer 14 jours — carte de tarif non mise en avant

QuandGrille de tarifs : le plan recommandé a un bouton plein, les autres un bouton contour.
PourquoiLe plan secondaire garde un appel à l'action visible sans voler la vedette ; au survol, le cadre se dessine sur toute la largeur de la carte et donne au plan une bordure — le geste dit « ce plan aussi est un choix ».
Réglageswidth: 100%, border-radius: 8px, délai des côtés ramené à .2s avec des phases de .2s (400 ms au total).

Comment ça marche

Le bouton .btn-border-draw est transparent (background: 0 0), en texte indigo #6366f1, avec un border: 2px solid transparent qui réserve 2 px tout autour. Les quatre côtés du cadre sont quatre boîtes distinctes : ::before (haut, top: 0; left: 0) et ::after (bas, bottom: 0; right: 0) font 2 px de haut pour 0 de large ; les deux <span> du HTML, .border-left (left: 0; bottom: 0) et .border-right (right: 0; top: 0), font 2 px de large pour 0 de haut. Un bouton n'a que deux pseudo-éléments : les spans fournissent les deux boîtes manquantes.

Au :hover, les pseudo-éléments passent à width: 100% et les spans à height: 100%. La séquence vient des transitions : transition: width .3s sur les traits horizontaux, transition: height .3s .3s sur les verticaux — même durée, mais un délai de 300 ms égal à la première phase. Le haut se trace de gauche à droite et le bas de droite à gauche (0 → 300 ms), puis la droite de haut en bas et la gauche de bas en haut (300 → 600 ms) : le cadre se dessine dans le sens des aiguilles d'une montre, deux côtés opposés à la fois. Courbe ease par défaut.

Mesuré dans Chromium sur le bouton livré (164 × 54 px) : les traits horizontaux atteignent 160 px et les verticaux 50 px, soit la boîte de padding — les quatre boîtes sont positionnées par rapport à elle, donc 2 px à l'intérieur du bord extérieur, dans l'espace de la bordure transparente. Et comme .demo-btn impose border-radius: 12px et overflow: hidden, la découpe arrondie (rayon intérieur 10 px) rogne les extrémités des traits droits : ils ne se rejoignent jamais, les quatre angles restent ouverts sur environ 6 px. C'est le rendu de la version livrée ; avec border-radius: 0 le cadre se ferme.

À la sortie du curseur, les mêmes transitions se rejouent à l'envers avec leurs délais : les traits horizontaux se rétractent aussitôt, les verticaux 300 ms plus tard — le cadre s'efface dans le même ordre qu'il s'est dessiné, pas en marche arrière. Rien d'autre ne change : ni fond, ni ombre, ni couleur de texte, ni :active. Le mouvement porte sur width et height, deux propriétés de mise en page recalculées à chaque image — sans conséquence pour quatre boîtes de 2 px, mais pas composées par le GPU comme le serait transform: scaleX().

Accessibilité

  • Contraste au repos insuffisant : le texte #6366f1 sur le fond de démo #0a0a0f mesure 4,42:1, sous le seuil AA de 4,5:1 pour 16 px — et 4,47:1 sur blanc, tout aussi juste. Le fond du bouton est transparent : c'est votre page qui décide. Sur fond sombre, prenez #818cf8 (6,6:1) ; sur fond clair, #4f46e5 (6,3:1). Les traits reprennent la même couleur : au-dessus de 3:1 dans les deux cas, le cadre reste perceptible (WCAG 1.4.11).
  • prefers-reduced-motion absent du code : ajoutez @media (prefers-reduced-motion: reduce) { .btn-border-draw::before, .btn-border-draw::after, .btn-border-draw .border-left, .btn-border-draw .border-right { transition: none } } — le cadre apparaît d'un bloc au survol, l'information est conservée.
  • Clavier : aucun :hover à la navigation Tab. Dupliquez les deux règles de survol vers :focus-visible (.btn-border-draw:focus-visible::before, .btn-border-draw:focus-visible::after { width: 100% } et l'équivalent height pour les spans) : le cadre qui se dessine devient un indicateur de focus, en plus de l'outline natif que le code ne retire pas.
  • Lecteurs d'écran : les deux <span> ne contiennent que des retours à la ligne, sans texte — le nom accessible reste le libellé. Par sécurité, posez aria-hidden="true" sur chacun, pour qu'aucune technologie d'assistance ne s'arrête sur des boîtes vides.
  • Tactile : pas de survol sur mobile, le cadre se trace au tap et reste affiché (iOS) — @media (hover: hover) pour l'éviter. Un bouton transparent au repos se lit comme un lien : réservez-le aux actions secondaires. Cible 54 px de haut (padding 16 px, texte 18 px, bordure 2 × 2 px), au-dessus du minimum de 44 px, et aucun décalage de mise en page au survol grâce à la bordure transparente déjà réservée.

Compatibilité navigateur

Requiert les transitions CSS sur width/height, les pseudo-éléments ::before/::after et le positionnement absolu — tous les navigateurs depuis 2012. Aucun JavaScript, zéro dépendance.

Chrome 26+✓ Complet
Firefox 16+✓ Complet
Safari 9+✓ Complet
Edge 12+✓ Complet
Mobile iOS✓ Complet (cadre tracé au tap, reste affiché)
Android Chrome✓ Complet (au tap)

Sans transitions, le cadre apparaît et disparaît d'un coup au survol ; sans pseudo-éléments (navigateurs préhistoriques), seuls les deux côtés portés par les spans se dessinent.

Le code

Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :

index.html — structure
<button class="demo-btn btn-border-draw">
  Border Draw
  <span class="border-left"></span>
  <span class="border-right"></span>
</button>
Débloquer le code complet — 9,90 € TTC/mois

Le code complet HTML + CSS + JS de Border Draw, prêt à coller — et les 840 effets. Ou 299 € TTC une fois, accès à vie.

Personnaliser

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

Option / propriétéDéfautEffet
Couleur #6366f1 (CSS — color + background des 4 traits) #6366f1 Cinq occurrences à changer ensemble. Mettez background: currentColor sur les quatre traits : la couleur du texte gouverne tout, et une seule déclaration suffit pour la marque ou pour le contraste (#818cf8 sur sombre, #4f46e5 sur clair).
transition: width .3s (CSS — ::before, ::after) .3s Durée de la première phase (haut et bas). Si vous la changez, alignez le délai des côtés dessus, sinon les phases se chevauchent ou laissent un trou.
transition: height .3s .3s (CSS — .border-left, .border-right) .3s de durée, .3s de délai Le délai est le séquenceur. 0s : les quatre côtés se tracent en même temps (300 ms au total). .15s : les côtés partent à mi-course des traits horizontaux, plus fluide.
Épaisseur height: 2px / width: 2px (CSS — les 4 traits) 2 px 1 px : filet fin ; 3 à 4 px : cadre affirmé. Ajustez la bordure transparente du bouton à la même valeur pour que le trait reste à la même distance du bord.
border-radius (CSS — .demo-btn) 12px Décide des angles. 0 : les traits se rejoignent, cadre fermé. Au-delà de 12 px, les coins ouverts s'élargissent — un style en soi (cadre « à coins coupés »).
Ancres left/right et top/bottom (CSS — position de chaque trait) haut : left 0 · bas : right 0 · gauche : bottom 0 · droite : top 0 Le point d'ancrage fixe le sens du tracé. Mettez right: 0 sur ::before et left: 0 sur ::after, top: 0 sur .border-left et bottom: 0 sur .border-right : le cadre se dessine dans le sens inverse.
border: 2px solid transparent (CSS — .btn-border-draw) transparent Remplacez transparent par rgba(99, 102, 241, .25) : un cadre fantôme est visible au repos, que les traits viennent souligner au survol — plus lisible comme bouton pour un élément transparent.

FAQ

Parce que les quatre traits sont droits et que overflow: hidden les découpe selon le border-radius: 12px du bouton (10 px à l'intérieur de la bordure). Aux angles, l'arc s'éloigne des bords de plus de 2 px : le trait y est rogné en biseau sur environ 6 px et ne rencontre pas son voisin. Trois issues : border-radius: 0 pour un cadre fermé, assumer les coins ouverts comme signature, ou passer par un <svg> avec un <rect rx="12"> animé en stroke-dashoffset si vous voulez un tracé qui suive vraiment la courbe.
Oui, avec la technique des deux pseudo-éléments en « L » : ::before porte border-top et border-right, ::after porte border-bottom et border-left, chacun passant de width: 0; height: 0 à 100%. Deux boîtes suffisent alors, au prix d'un tracé en deux L symétriques plutôt qu'en quatre côtés séquencés. Le code livré garde les spans pour contrôler chaque côté séparément.
Donnez à chaque côté sa propre fenêtre : ::before en transition: width .15s, .border-right en height .15s .15s, ::after en width .15s .3s, .border-left en height .15s .45s. Le tracé enchaîne haut → droite → bas → gauche en 600 ms, comme un stylo qui ne se lève pas — les ancres livrées s'y prêtent déjà : le bas part de la droite (right: 0) et la gauche part du bas (bottom: 0).