FormulairesGratuit

Underline Focus

Un champ réduit à une ligne : au clic, un trait dégradé indigo-magenta part du milieu et file vers les deux bords pendant que le libellé monte au-dessus.

CSSFocusGradient

Mis à jour le

Survolez ou cliquez la scène pour interagir

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

Exemples d'usage

BrunelysFrançais · 5eExercice 4 sur 10

Conjuguez les verbes entre parenthèses au passé composé.

Hier, nous au cinéma et nous du début à la fin.

① Texte à trous d'un exercice de conjugaison — plateforme Brunelys

QuandL'élève lit « Hier, nous (aller) au cinéma et nous (rire)… » : chaque infinitif est le libellé d'un trou. En cliquant ou avec Tab, le verbe monte au-dessus du trou et le trait coloré montre où il écrit ; « Corriger » note chaque réponse.
PourquoiUn champ réduit à une ligne se fond dans une phrase comme un blanc d'exercice papier, et le libellé qui monte garde l'infinitif sous les yeux pendant que l'élève conjugue.
Réglages--udl-width: 128px sur la racine, champs passés en display: inline-block par la scène pour couler dans le paragraphe (texte en Georgia 19 px, interligne 1,9). La racine sert de carte, fond par défaut.
TessalyMes fichiers › Clients
NomÉlémentsModifié
  • Charte graphique14 éléments3 nov.
  • Devis 202632 élémentsHier
  • Photos atelier208 éléments28 oct.
  • Factures57 éléments12 oct.

② Renommer un dossier sur place — gestionnaire de fichiers Tessaly

QuandUn clic sur « Renommer » remplace le nom de la ligne par le champ, déjà rempli et sélectionné : le libellé « Nouveau nom » est en haut d'emblée, le trait s'ouvre sous le nom. Entrée ou un clic ailleurs enregistre, Échap annule.
PourquoiLe renommage ne doit pas ouvrir de fenêtre : un champ sans cadre garde la ligne alignée avec ses voisines, et seul le trait signale qu'elle est en édition.
Réglages--udl-width: 100%, un champ par ligne affiché seulement en édition, lignes de 62 px pour que le libellé remonté tienne sans décaler la liste. Racine sans fond (la liste a le sien).

Maison Ferbaline · Bistrot

Une table pour ce soir ?

Cuisine du marché, 28 couverts. Service de 19 h à 22 h, du mardi au samedi.

Plus de 8 personnes ? Appelez-nous.

③ Réservation d'une table, page au ton éditorial — Maison Ferbaline

QuandÀ droite du texte de présentation du bistrot, trois lignes fines : nom, date et heure, couverts, puis le bouton Réserver. Le trait suit la personne d'une ligne à l'autre.
PourquoiDes cadres pleins casseraient la mise en page de magazine ; des lignes simples s'accordent à la typographie, et le dégradé suffit à indiquer où l'on tape.
Réglages--udl-width: 100%, racine en <form> transparente sur fond brun, champs required (le navigateur bloque l'envoi d'une ligne vide), couverts en type="number" de 1 à 8.

Comment ça marche

Le champ .udl-input n'a ni fond ni cadre, seulement un filet bas de 2 px en rgba(255, 255, 255, .2). Juste derrière lui dans le <label class="udl-field"> viennent le texte .udl-label puis un <span class="udl-line"> vide, placé en absolu sur ce filet : il démarre à left: 50% avec une largeur nulle.

Quand le champ prend le focus, .udl-input:focus ~ .udl-line fait passer le trait à left: 0 et width: 100%. Les deux valeurs changent ensemble en 0,4 s avec la courbe cubic-bezier(.4, 0, .2, 1) : le dégradé #6366f1 → #d946ef semble naître au centre et s'ouvrir des deux côtés. Au départ du focus, la même transition le referme vers le milieu.

Le libellé suit une autre règle. Il est posé à hauteur du texte (top: 30px) et monte à top: 2px, en 0.75rem indigo, dès que :focus ou :not(:placeholder-shown) s'applique ; le placeholder=" " invisible sert uniquement à savoir si le champ contient quelque chose. Un champ rempli garde donc son libellé en haut alors que le trait coloré est déjà reparti.

Le padding-top: 18px de .udl-field réserve la place du libellé remonté : empilés dans un formulaire, deux champs ne se chevauchent pas. La racine .fx-0282-root (fond sombre, 250 px de haut minimum) sert seulement à la démonstration.

Accessibilité

  • Libellé réel : le <label> enveloppe le champ, « Nom complet » est donc son nom accessible, sans id à dédoublonner quand la page en contient plusieurs.
  • Attributs de formulaire : name="name" et autocomplete="name" sont fournis ; le navigateur propose le nom enregistré et la valeur part avec le formulaire.
  • Repérer le champ actif : le trait coloré n'existe que pendant le focus. Un champ rempli mais quitté retrouve le filet gris, ce qui le distingue du champ en cours.
  • Mouvement réduit : sous prefers-reduced-motion: reduce, ni le trait ni le libellé ne glissent ; ils apparaissent directement à leur place finale.
  • Contraste : au repos, #8b8b93 sur rgb(26, 26, 36) atteint 5,1:1 ; le libellé remonté, en #818cf8 à 12 px, atteint 5,8:1. Mesuré dans Chromium, Firefox et WebKit, au repos, au focus et rempli.

Compatibilité navigateur

Utilise :placeholder-shown (Chrome 47, Firefox 51, Safari 9), le sélecteur de frère ~, un dégradé linéaire et des variables CSS (Chrome 49, Firefox 31, Safari 9.1). Contrôlé dans Chromium, Firefox et WebKit : deux champs côte à côte qui s'animent chacun de leur côté, Tab, toucher, envoi dans un formulaire, 390 px de large, mouvement réduit.

Chrome 49+✓ Complet (mesuré)
Firefox 51+✓ Complet (mesuré)
Safari 9.1+✓ Complet (moteur WebKit mesuré)
Edge 79+✓ Complet (moteur Chromium)
Mobile iOS 9.3+✓ Complet
Android Chrome 49+✓ Complet (moteur Chromium)

Sans transitions, le trait et le libellé sautent d'un état à l'autre, le champ reste utilisable. Sans :placeholder-shown, le libellé redescend sur le texte saisi quand on quitte le champ.

Le code

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

HTML
<div class="fx-0282-root">
  <label class="udl-field">
    <input class="udl-input" type="text" name="name" autocomplete="name" placeholder=" ">
    <span class="udl-label">Nom complet</span>
    <span class="udl-line" aria-hidden="true"></span>
  </label>
</div>
CSS
.fx-0282-root,
.fx-0282-root *,
.fx-0282-root *::before,
.fx-0282-root *::after {
  box-sizing: border-box
}

.fx-0282-root {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 250px;
  padding: 24px 16px;
  position: relative;
  background: rgb(26, 26, 36);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.udl-field {
  position: relative;
  display: block;
  width: var(--udl-width, 280px);
  max-width: 100%;
  padding-top: 18px;
}

.udl-input {
  width: 100%;
  padding: 12px 0;
  font-size: 1rem;
  font-family: inherit;
  background: transparent;
  border: none;
  border-bottom: 2px solid rgba(255, 255, 255, 0.2);
  color: white;
  outline: none;
}

.udl-line {
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 0;
  height: 2px;
  background: linear-gradient(90deg, #6366f1, #d946ef);
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.udl-input:focus ~ .udl-line {
  left: 0;
  width: 100%;
}

.udl-label {
  position: absolute;
  left: 0;
  top: 30px;
  color: var(--udl-muted, #8b8b93);
  pointer-events: none;
  transition: all 0.3s ease;
}

.udl-input:focus + .udl-label,
.udl-input:not(:placeholder-shown) + .udl-label {
  top: 2px;
  font-size: 0.75rem;
  color: #818cf8;
}

@media (prefers-reduced-motion: reduce) {
  .udl-line,
  .udl-label {
    transition: none;
  }
}
JavaScript

CSS pur — aucun JavaScript requis.

Personnaliser

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

Option / propriétéDéfautEffet
Largeur (CSS — --udl-width) 280 px 100% pour suivre la colonne, une valeur courte (100 à 140 px) pour un champ glissé dans une phrase. Le champ ne dépasse jamais son conteneur (max-width: 100%).
Dégradé du trait (CSS — background de .udl-line) linear-gradient(90deg, #6366f1, #d946ef) Une couleur unie fonctionne aussi. Gardez une teinte nettement plus vive que le filet gris pour que le champ actif se voie.
Épaisseur (CSS — height de .udl-line et border-bottom de .udl-input) 2 px Changez les deux valeurs ensemble : le trait recouvre exactement le filet du bas.
Vitesse d'ouverture (CSS — transition de .udl-line) 0,4 s Le libellé, lui, se déplace en 0,3 s. Un trait un peu plus lent que le libellé donne l'impression que la ligne « suit » la montée du texte.
Couleur du libellé au repos (CSS — --udl-muted) #8b8b93 Le libellé remonté garde #818cf8, écrit en dur dans la règle :focus + .udl-label.
Place réservée au-dessus (CSS — padding-top de .udl-field) 18 px Si vous agrandissez le libellé remonté, augmentez cette marge et le top du libellé au repos (30 px) d'autant.

FAQ

Pourquoi le trait part-il du centre et pas de la gauche ?

Parce que deux propriétés changent à la fois : left passe de 50 % à 0 pendant que width passe de 0 à 100 %. Pour un trait qui part de la gauche, laissez left: 0 au repos et ne faites varier que la largeur.

Le champ fonctionne-t-il sur fond clair ?

Le texte saisi est blanc et le filet est un blanc transparent : sur fond clair, passez color de .udl-input en sombre et le filet en rgba(0, 0, 0, .2). Le dégradé indigo-magenta reste lisible tel quel.

Peut-on mettre un champ au milieu d'une phrase ?

Oui : donnez à .udl-field un display: inline-block et une largeur courte via --udl-width. La ligne du texte s'agrandit pour loger l'espace réservé au libellé ; prévoyez un interligne d'environ 1,9.