Text Color Animation Code Component

Text Color Animation Code Component

Text Color Animation Code Component

Text Color Animation Code Component

Component

Component

Component

Component

Text Color Animation Code Component

Text Color Animation Code Component

Text Color Animation Code Component

Text Color Animation Code Component

This is a code component for creating a text color animation in Framer. This effect looks stunning on all websites and could be a fantastic addition to yours too. However, make sure not to overdo it.

This effect was inspired by the Minhpham website.

This is a code component for creating a text color animation in Framer. This effect looks stunning on all websites and could be a fantastic addition to yours too. However, make sure not to overdo it.

This effect was inspired by the Minhpham website.

This is a code component for creating a text color animation in Framer. This effect looks stunning on all websites and could be a fantastic addition to yours too. However, make sure not to overdo it.

This effect was inspired by the Minhpham website.

This is a code component for creating a text color animation in Framer. This effect looks stunning on all websites and could be a fantastic addition to yours too. However, make sure not to overdo it.

This effect was inspired by the Minhpham website.

Text Color Animation Code Component
Text Color Animation Code Component
Text Color Animation Code Component
Text Color Animation Code Component

Copy component

Copy component

Copy component

Copy component

Features

Fully customizable through component properties, here's what you can do:

  • Set text.

  • Adjust the font size.

  • Alter text colors one and two.

  • Choose your font family and weight.

  • Set the animation duration.

  • Apply a delay, if needed.

  • Toggle replaying.

The animation will always play when the component comes into the viewport. If you want, you can delay this animation.

Just remember, the text stays on a single line. If you need multiple lines, you'll have to use separate components for each line of text.

Step 01 outline

Step / 01

Remix the project.

Step 2 outline

Step / 02

Copy the component to your website.

Step 3 outline

Step / 03

Or just make a code component from scratch and use the code from below.

Source code

If you want to take a look at how such a code component is built in Framer, feel free to copy this code from below and dig into it.

// © Framer University. All rights reserved.

import React, { useEffect, useRef } from "react"
import { motion, useAnimation } from "framer-motion"
import { addPropertyControls, ControlType } from "framer"

export default function TextColorAnimation({
    text,
    fontSize,
    fontFamily,
    fontWeight,
    textAlign,
    color01,
    color02,
    Duration,
    delay,
    replays,
}) {
    const controls = useAnimation()
    const textRef = useRef()

    useEffect(() => {
        const observer = new IntersectionObserver(async ([entry]) => {
            if (entry.isIntersecting) {
                await new Promise((resolve) =>
                    setTimeout(resolve, delay * 1000)
                ) // delay before animation starts
                controls.start("visible")
            } else if (!entry.isIntersecting && replays) {
                controls.start("hidden")
            }
        })

        observer.observe(textRef.current)

        return () => observer.disconnect()
    }, [Duration, controls, color01, delay, replays])

    return (
        <div
            style={{
                fontSize: `${fontSize}px`,
                fontFamily: fontFamily,
                fontWeight: fontWeight,
                width: "100%",
                whiteSpace: "nowrap",
                color: color01,
                textAlign: textAlign,
            }}
            ref={textRef}
        >
            <span style={{ position: "relative", display: "inline-block" }}>
                {text}
                <motion.span
                    style={{
                        position: "absolute",
                        overflow: "hidden",
                        whiteSpace: "nowrap",
                        color: color02,
                        top: 0,
                        left: 0,
                        width: "0%",
                    }}
                    animate={controls}
                    initial={{ width: "0%" }}
                    variants={{
                        visible: { width: "100%" },
                        hidden: { width: "0%" },
                    }}
                    transition={{ duration: Duration }}
                >
                    {text}
                </motion.span>
            </span>
        </div>
    )
}

addPropertyControls(TextColorAnimation, {
    text: { type: ControlType.String, defaultValue: "Hello, World!" },
    fontSize: {
        type: ControlType.Number,
        defaultValue: 16,
        min: 1,
        max: 200,
        unit: "px",
    },
    fontFamily: { type: ControlType.String, defaultValue: "Arial" },
    fontWeight: {
        type: ControlType.Enum,
        defaultValue: "400",
        options: [
            "100",
            "200",
            "300",
            "400",
            "500",
            "600",
            "700",
            "800",
            "900",
        ],
    },
    textAlign: {
        title: "Text Align",
        type: ControlType.Enum,
        displaySegmentedControl: true,
        optionTitles: ["Left", "Center", "Right"],
        options: ["left", "center", "right"],
    },
    color01: {
        title: "Color 01",
        type: ControlType.Color,
        defaultValue: "#333",
    },
    color02: {
        title: "Color 02",
        type: ControlType.Color,
        defaultValue: "#fff",
    },
    Duration: {
        type: ControlType.Number,
        defaultValue: 1.0,
        min: 0.1,
        max: 10.0,
        step: 0.1,
    },
    delay: {
        title: "Delay",
        type: ControlType.Number,
        defaultValue: 0,
        min: 0,
        max: 10.0,
        step: 0.1,
    },
    replays: {
        title: "Replays",
        type: ControlType.Boolean,
        defaultValue: true,
    },
})
// © Framer University. All rights reserved.

import React, { useEffect, useRef } from "react"
import { motion, useAnimation } from "framer-motion"
import { addPropertyControls, ControlType } from "framer"

export default function TextColorAnimation({
    text,
    fontSize,
    fontFamily,
    fontWeight,
    textAlign,
    color01,
    color02,
    Duration,
    delay,
    replays,
}) {
    const controls = useAnimation()
    const textRef = useRef()

    useEffect(() => {
        const observer = new IntersectionObserver(async ([entry]) => {
            if (entry.isIntersecting) {
                await new Promise((resolve) =>
                    setTimeout(resolve, delay * 1000)
                ) // delay before animation starts
                controls.start("visible")
            } else if (!entry.isIntersecting && replays) {
                controls.start("hidden")
            }
        })

        observer.observe(textRef.current)

        return () => observer.disconnect()
    }, [Duration, controls, color01, delay, replays])

    return (
        <div
            style={{
                fontSize: `${fontSize}px`,
                fontFamily: fontFamily,
                fontWeight: fontWeight,
                width: "100%",
                whiteSpace: "nowrap",
                color: color01,
                textAlign: textAlign,
            }}
            ref={textRef}
        >
            <span style={{ position: "relative", display: "inline-block" }}>
                {text}
                <motion.span
                    style={{
                        position: "absolute",
                        overflow: "hidden",
                        whiteSpace: "nowrap",
                        color: color02,
                        top: 0,
                        left: 0,
                        width: "0%",
                    }}
                    animate={controls}
                    initial={{ width: "0%" }}
                    variants={{
                        visible: { width: "100%" },
                        hidden: { width: "0%" },
                    }}
                    transition={{ duration: Duration }}
                >
                    {text}
                </motion.span>
            </span>
        </div>
    )
}

addPropertyControls(TextColorAnimation, {
    text: { type: ControlType.String, defaultValue: "Hello, World!" },
    fontSize: {
        type: ControlType.Number,
        defaultValue: 16,
        min: 1,
        max: 200,
        unit: "px",
    },
    fontFamily: { type: ControlType.String, defaultValue: "Arial" },
    fontWeight: {
        type: ControlType.Enum,
        defaultValue: "400",
        options: [
            "100",
            "200",
            "300",
            "400",
            "500",
            "600",
            "700",
            "800",
            "900",
        ],
    },
    textAlign: {
        title: "Text Align",
        type: ControlType.Enum,
        displaySegmentedControl: true,
        optionTitles: ["Left", "Center", "Right"],
        options: ["left", "center", "right"],
    },
    color01: {
        title: "Color 01",
        type: ControlType.Color,
        defaultValue: "#333",
    },
    color02: {
        title: "Color 02",
        type: ControlType.Color,
        defaultValue: "#fff",
    },
    Duration: {
        type: ControlType.Number,
        defaultValue: 1.0,
        min: 0.1,
        max: 10.0,
        step: 0.1,
    },
    delay: {
        title: "Delay",
        type: ControlType.Number,
        defaultValue: 0,
        min: 0,
        max: 10.0,
        step: 0.1,
    },
    replays: {
        title: "Replays",
        type: ControlType.Boolean,
        defaultValue: true,
    },
})

Free Framer Course

Learn how to create stunning websites with ease by learning the fundamentals of Framer.

Free
Framer Course

Learn how to create stunning websites with ease by learning the fundamentals of Framer.

Free Framer Course

Learn how to create stunning websites with ease by learning the fundamentals of Framer.