Dia Browser H1
inspired by Dia Browser
Colorful animated ribbon text effect inspired by Dia Browser's H1, implemented in React and CSS.
Tutorial
H1AnimationHeroText Animation
React
CSS
React implementation
DiaH1.jsx
import { useState, useEffect } from "react";
import styles from "./DiaH1.module.css";
const words = ["Chat", "Write", "Plan", "Learn"];
export default function DiaH1() {
const [currentWordIndex, setCurrentWordIndex] = useState(0);
const [opacity, setOpacity] = useState(1);
useEffect(() => {
const interval = setInterval(() => {
setOpacity(0); // Fade out
setTimeout(() => {
setCurrentWordIndex((prev) => (prev + 1) % words.length);
setOpacity(1); // Fade in
}, 300);
}, 3000);
return () => clearInterval(interval);
}, []);
return (
<div className={styles.heading}>
<div className={styles.wordWrapper} style={{ opacity, transition: 'opacity 0.3s' }}>
<span key={currentWordIndex} className={styles.word}>
{words[currentWordIndex]}
</span>
</div>
with your tabs
</div>
);
}
import { useState, useEffect } from "react";
import styles from "./DiaH1.module.css";
const words = ["Chat", "Write", "Plan", "Learn"];
export default function DiaH1() {
const [currentWordIndex, setCurrentWordIndex] = useState(0);
const [opacity, setOpacity] = useState(1);
useEffect(() => {
const interval = setInterval(() => {
setOpacity(0); // Fade out
setTimeout(() => {
setCurrentWordIndex((prev) => (prev + 1) % words.length);
setOpacity(1); // Fade in
}, 300);
}, 3000);
return () => clearInterval(interval);
}, []);
return (
<div className={styles.heading}>
<div className={styles.wordWrapper} style={{ opacity, transition: 'opacity 0.3s' }}>
<span key={currentWordIndex} className={styles.word}>
{words[currentWordIndex]}
</span>
</div>
with your tabs
</div>
);
}
DiaH1.module.css
.heading {
font-size: 2rem;
font-weight: bold;
font-family: "Host Grotesk", sans-serif;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
gap: 0.5ch;
}
.wordWrapper {
width: 5ch;
text-align: right;
}
.word {
text-align: right;
white-space: nowrap;
overflow: hidden;
background-image: linear-gradient(
to right,
white 0,
white 33.33%,
#1FBFBA 40%,
#2D7FF9 45%,
#7A4FF1 50%,
#D741A7 55%,
#F48C2B 60%,
transparent 66.67%,
transparent 100%);
background-size: 300%;
background-position: 100%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
animation-name: ribbon-slide;
animation-delay: 100ms;
animation-duration: 900ms;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
@keyframes ribbon-slide {
0% { background-position-x: 100%; }
100% { background-position-x: 0%; }
}
.heading {
font-size: 2rem;
font-weight: bold;
font-family: "Host Grotesk", sans-serif;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
gap: 0.5ch;
}
.wordWrapper {
width: 5ch;
text-align: right;
}
.word {
text-align: right;
white-space: nowrap;
overflow: hidden;
background-image: linear-gradient(
to right,
white 0,
white 33.33%,
#1FBFBA 40%,
#2D7FF9 45%,
#7A4FF1 50%,
#D741A7 55%,
#F48C2B 60%,
transparent 66.67%,
transparent 100%);
background-size: 300%;
background-position: 100%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
animation-name: ribbon-slide;
animation-delay: 100ms;
animation-duration: 900ms;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
@keyframes ribbon-slide {
0% { background-position-x: 100%; }
100% { background-position-x: 0%; }
}