Split Color
Un pseudo-élément ::before clipé par clip-path: inset() divise le texte en deux teintes ; @keyframes splitWave fait onduler la frontière en continu — animation CSS pure, zéro dépendance.
Vous aurez accès à la démo interactive avec un compte gratuit.
Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Texte comprend 56 effets, dont 4 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
Le texte est rendu deux fois en superposition pixel-parfaite. L'élément <span class="text-split"> affiche la moitié supérieure dans sa couleur de base (color: #6366f1). Son pseudo-élément ::before reproduit le même contenu via content: attr(data-text), positionné en position: absolute; left: 0; top: 0, et masqué par clip-path: inset(50% 0 0) qui coupe les 50 % supérieurs — seule la moitié inférieure du pseudo-élément reste visible, dans la couleur secondaire (color: #d946ef). Le résultat visuel est un texte unique dont les deux moitiés ont des couleurs différentes.
L'animation @keyframes splitWave fait osciller le clip-path du pseudo-élément entre deux états : inset(50% 0 0) (frontière à exactement 50 % de la hauteur) et inset(40% 0 10%) (bande visible remontée de 10 %, bord bas remonté de 10 % également). La bande colorée se déplace légèrement de bas en haut et revient, créant une ondulation douce sur une période de 2 s en ease-in-out infini. La frontière n'est jamais une ligne nette mais une transition portée par la forme même des glyphes.
Le code JS expose une fonction utilitaire splitChars(el) qui décompose le texte de l'élément en <span class="char"> individuels. En combinant la classe text-split-hover sur l'élément et la classe scattered (ajoutée via JS), chaque caractère peut s'estomper (opacity: 0.3) et se déplacer (transform) avec les transitions définies — cubic-bezier(.68, -.55, .265, 1.55) pour le rebond. Le pseudo-élément ::before continue d'afficher le texte complet via data-text, maintenant l'effet bicolore même pendant la dispersion.
La variable el = getElementById('fadeInText') présente au niveau racine du script est dormante : elle retourne null si aucun élément ne porte cet id, sans déclencher d'erreur. L'animation bicolore démarrant uniquement via CSS, il n'est pas nécessaire d'appeler de fonction JS pour l'initialiser — l'ajout des classes demo-text text-split et de l'attribut data-text suffit.
Accessibilité
- prefers-reduced-motion : absent du code — l'animation
splitWaves'exécute même si l'OS préfère réduire le mouvement. Correctif recommandé :@media (prefers-reduced-motion: reduce) { .text-split::before { animation: none; } }. - L'attribut
data-textduplique le contenu texte visible : les lecteurs d'écran peuvent annoncer le texte deux fois (élément + pseudo-élément ou titre du conteneur). Enveloppez l'élément dans un conteneur portantaria-labelet ajoutezaria-hidden="true"sur le<span>bicolore pour éviter la duplication. - Contraste couleurs par défaut sur fond
#0a0a0f:#6366f1(moitié haute) → ratio ≈ 5,8 : 1 (WCAG AA ✓) ;#d946ef(moitié basse) → ratio ≈ 5,1 : 1 (WCAG AA ✓). Ces ratios varient selon votre fond — vérifiez avec vos couleurs personnalisées. - Navigation clavier : l'effet est purement décoratif par défaut, aucun focus management n'est requis. Si vous activez le mode hover/scatter (
text-split-hover), rendez l'élément focusable (tabindex="0") et ajoutez un état:focus-visibleexplicite. - Sémantique :
<span>est un élément neutre (pas de rôle implicite). Si le texte bicolore est un titre de page ou de section, enveloppez-le dans la balise appropriée (<h1>–<h3>) et appliquez les classes sur un<span>intérieur.
Compatibilité navigateur
Repose sur clip-path: inset() et content: attr() — supportés dans tous les navigateurs modernes depuis 2017–2018. Zéro dépendance externe.
Si <code>clip-path</code> n'est pas supporté (IE 11, très anciens navigateurs), le texte s'affiche dans la couleur du pseudo-élément (<code>#d946ef</code>) sans découpe — lisible et sans erreur JS.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="demo-preview">
<!-- Texte bicolore de base (animation CSS autonome) -->
<span class="demo-text text-split" data-text="VOTRE TEXTE">VOTRE TEXTE</span>
<!-- Variante hover/scatter (ajouter la classe + appeler splitChars(el) en JS) -->
<!-- <span class="demo-text text-split text-split-hover"
data-text="VOTRE TEXTE">VOTRE TEXTE</span> -->
</div>
HTML + CSS + JS complet, prêt à coller — avec des centaines d'effets premium.
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
| color sur .text-split | #6366f1 | Couleur de la moitié supérieure du texte (élément de base). Changez directement la valeur hex dans le CSS. |
| color sur .text-split::before | #d946ef | Couleur de la moitié inférieure (pseudo-élément ::before). Doit contraster avec la couleur de base pour que l'effet soit lisible. |
| font-size sur .demo-text | 2.5rem | Taille du texte. L'effet est plus impressionnant à grande taille (4–10 rem) — la frontière bicolore y est nettement visible. |
| animation-duration dans .text-split::before | 2s | Durée d'un cycle d'ondulation. 1 s = rapide et dynamique ; 4–6 s = lent et ambiant. Remplacez la première valeur de la propriété animation. |
| inset() dans @keyframes splitWave | inset(50% 0 0) / inset(40% 0 10%) | Première valeur = position de la frontière (50 % = milieu). Augmentez pour réduire la zone inférieure, diminuez pour l'agrandir. Supprimez l'animation et fixez une valeur unique pour une frontière statique. |
| data-text sur l'élément | "SPLIT" | Contenu textuel du pseudo-élément ::before. Doit toujours correspondre au textContent visible de l'élément — sinon les deux couches se décalent. |
| font-weight sur .demo-text | 800 | Graisse typographique. À 800–900, les deux couleurs sont bien distinctes. En dessous de 600, la frontière peut paraître floue sur des polices à faibles contrastes de graisse. |
| classe .text-split-hover | absente | Ajoutez cette classe à l'élément et appelez splitChars(el) en JS pour activer la dispersion par caractère au survol. Ajoutez ensuite .scattered via JS pour déclencher l'animation de dispersion (opacity + transform). |
FAQ
splitWave est pilotée uniquement par CSS. L'attribut data-text doit correspondre au texte visible de l'élément, et les deux classes demo-text text-split suffisent. Le JS fourni n'est utile que si vous souhaitez activer l'effet de dispersion par caractère via splitChars(el).clip-path dans @keyframes splitWave. Par exemple, inset(30% 0 0) élargit la zone inférieure à 70 % de la hauteur, inset(70% 0 0) la réduit à 30 %. Pour supprimer l'animation et fixer une frontière statique, retirez la propriété animation et écrivez directement .text-split::before { clip-path: inset(50% 0 0); }.clip-path: inset() applique une découpe rectangulaire unique sur l'ensemble du pseudo-élément. Sur deux lignes, la frontière coupe au même niveau absolu — la ligne 1 peut être entièrement supérieure et la ligne 2 entièrement inférieure selon la valeur choisie. Pour un découpage plus fin ligne par ligne, préférez une approche background: linear-gradient() combinée à -webkit-background-clip: text; -webkit-text-fill-color: transparent.