Countdown Widget

Copy component

Countdown Widget

Copy component

Nandi Muzsik

How can I improve Framer Uni?

Let me know if there’s a missing feature or something that could be improved.

Share feedback

Nandi Muzsik

How can I improve Framer Uni?

Let me know if there’s a missing feature or something that could be improved.

Share feedback

Component

Countdown Widget

Use this widget (code component) on your Framer website to add a customizable countdown element to it. This can be used for product launches, limited time offers, and more.

image of Nandi Muzsik

Created by

countdown component in Framer
countdown component in Framer
countdown component in Framer

About the resource

Fully customizable through component properties.

You can:

  • Change font size.

  • Change text color.

  • Specify font family & weight.

  • Toggle days, hours, minutes, and seconds.

  • Specify an end date.

  • Specify an end message.

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.

About the resource

Fully customizable through component properties.

You can:

  • Change font size.

  • Change text color.

  • Specify font family & weight.

  • Toggle days, hours, minutes, and seconds.

  • Specify an end date.

  • Specify an end message.

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.

About the resource

Fully customizable through component properties.

You can:

  • Change font size.

  • Change text color.

  • Specify font family & weight.

  • Toggle days, hours, minutes, and seconds.

  • Specify an end date.

  • Specify an end message.

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.

import React, { useState, useEffect } from "react"
import { addPropertyControls, ControlType } from "framer"

export default function Countdown({
    fontSize,
    fontFamily,
    fontColor,
    fontWeight,
    displayDays,
    displayHours,
    displayMinutes,
    displaySeconds,
    endDate,
    endTime,
    endMessage,
}) {
    const [timeLeft, setTimeLeft] = useState(calculateTimeLeft())

    useEffect(() => {
        const timer = setTimeout(() => {
            setTimeLeft(calculateTimeLeft())
        }, 1000)

        return () => clearTimeout(timer)
    })

    function calculateTimeLeft() {
        const difference = +new Date(`${endDate}T${endTime}`) - +new Date()
        let timeLeft = {}

        if (difference > 0) {
            if (difference < 60 * 60 * 1000) {
                // Less than 60 minutes remaining
                const minutes = Math.floor((difference / (1000 * 60)) % 60)
                const seconds = Math.floor((difference / 1000) % 60)

                timeLeft = {
                    days: displayDays ? 0 : null,
                    hours: displayHours ? 0 : null,
                    minutes: displayMinutes ? minutes : null,
                    seconds: displaySeconds ? seconds : null,
                }
            } else {
                const time = {
                    d: Math.floor(difference / (1000 * 60 * 60 * 24)),
                    h: Math.floor((difference / (1000 * 60 * 60)) % 24),
                    m: Math.floor((difference / (1000 * 60)) % 60),
                    s: Math.floor((difference / 1000) % 60),
                }

                timeLeft = {
                    days: displayDays ? time.d : 0,
                    hours: displayHours ? time.h : null,
                    minutes: displayMinutes ? time.m : null,
                    seconds: displaySeconds ? time.s : null,
                }
            }
        }

        return timeLeft
    }

    const timerComponents = []

    Object.keys(timeLeft).forEach((interval) => {
        if (!timeLeft[interval]) {
            return
        }

        timerComponents.push(
            <span
                key={interval}
                style={{
                    display: "flex",
                    alignItems: "center",
                    flexDirection: "column",
                }}
            >
                {timeLeft[interval]}
                <span style={{ fontSize: `${fontSize / 2.5}px` }}>
                    {interval.toLowerCase()}
                </span>
            </span>
        )
    })

    return (
        <div
            style={{
                fontSize,
                fontFamily,
                color: fontColor,
                fontWeight,
                display: "flex",
                gap: "20px",
            }}
        >
            {timerComponents.length ? (
                timerComponents
            ) : (
                <span>{endMessage}</span>
            )}
        </div>
    )
}

addPropertyControls(Countdown, {
    fontSize: {
        type: ControlType.Number,
        unit: "px",
        defaultValue: 30,
    },
    fontFamily: {
        type: ControlType.String,
        defaultValue: "Inter",
    },
    fontColor: {
        type: ControlType.Color,
        defaultValue: "black",
    },
    fontWeight: {
        type: ControlType.Enum,
        defaultValue: 400,
        options: [
            "normal",
            "bold",
            "bolder",
            "lighter",
            100,
            200,
            300,
            400,
            500,
            600,
            700,
            800,
            900,
        ],
    },
    displayDays: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    displayHours: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    displayMinutes: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    displaySeconds: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    endDate: {
        type: ControlType.String,
        defaultValue: "2023-04-25",
        description: "YYYY-MM-DD",
    },
    endTime: {
        type: ControlType.String,
        defaultValue: "00:00:00",
        description: "HH:MM:SS",
    },
    endMessage: {
        type: ControlType.String,
        defaultValue: "Time's up!",
    },
})

import React, { useState, useEffect } from "react"
import { addPropertyControls, ControlType } from "framer"

export default function Countdown({
    fontSize,
    fontFamily,
    fontColor,
    fontWeight,
    displayDays,
    displayHours,
    displayMinutes,
    displaySeconds,
    endDate,
    endTime,
    endMessage,
}) {
    const [timeLeft, setTimeLeft] = useState(calculateTimeLeft())

    useEffect(() => {
        const timer = setTimeout(() => {
            setTimeLeft(calculateTimeLeft())
        }, 1000)

        return () => clearTimeout(timer)
    })

    function calculateTimeLeft() {
        const difference = +new Date(`${endDate}T${endTime}`) - +new Date()
        let timeLeft = {}

        if (difference > 0) {
            if (difference < 60 * 60 * 1000) {
                // Less than 60 minutes remaining
                const minutes = Math.floor((difference / (1000 * 60)) % 60)
                const seconds = Math.floor((difference / 1000) % 60)

                timeLeft = {
                    days: displayDays ? 0 : null,
                    hours: displayHours ? 0 : null,
                    minutes: displayMinutes ? minutes : null,
                    seconds: displaySeconds ? seconds : null,
                }
            } else {
                const time = {
                    d: Math.floor(difference / (1000 * 60 * 60 * 24)),
                    h: Math.floor((difference / (1000 * 60 * 60)) % 24),
                    m: Math.floor((difference / (1000 * 60)) % 60),
                    s: Math.floor((difference / 1000) % 60),
                }

                timeLeft = {
                    days: displayDays ? time.d : 0,
                    hours: displayHours ? time.h : null,
                    minutes: displayMinutes ? time.m : null,
                    seconds: displaySeconds ? time.s : null,
                }
            }
        }

        return timeLeft
    }

    const timerComponents = []

    Object.keys(timeLeft).forEach((interval) => {
        if (!timeLeft[interval]) {
            return
        }

        timerComponents.push(
            <span
                key={interval}
                style={{
                    display: "flex",
                    alignItems: "center",
                    flexDirection: "column",
                }}
            >
                {timeLeft[interval]}
                <span style={{ fontSize: `${fontSize / 2.5}px` }}>
                    {interval.toLowerCase()}
                </span>
            </span>
        )
    })

    return (
        <div
            style={{
                fontSize,
                fontFamily,
                color: fontColor,
                fontWeight,
                display: "flex",
                gap: "20px",
            }}
        >
            {timerComponents.length ? (
                timerComponents
            ) : (
                <span>{endMessage}</span>
            )}
        </div>
    )
}

addPropertyControls(Countdown, {
    fontSize: {
        type: ControlType.Number,
        unit: "px",
        defaultValue: 30,
    },
    fontFamily: {
        type: ControlType.String,
        defaultValue: "Inter",
    },
    fontColor: {
        type: ControlType.Color,
        defaultValue: "black",
    },
    fontWeight: {
        type: ControlType.Enum,
        defaultValue: 400,
        options: [
            "normal",
            "bold",
            "bolder",
            "lighter",
            100,
            200,
            300,
            400,
            500,
            600,
            700,
            800,
            900,
        ],
    },
    displayDays: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    displayHours: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    displayMinutes: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    displaySeconds: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    endDate: {
        type: ControlType.String,
        defaultValue: "2023-04-25",
        description: "YYYY-MM-DD",
    },
    endTime: {
        type: ControlType.String,
        defaultValue: "00:00:00",
        description: "HH:MM:SS",
    },
    endMessage: {
        type: ControlType.String,
        defaultValue: "Time's up!",
    },
})

import React, { useState, useEffect } from "react"
import { addPropertyControls, ControlType } from "framer"

export default function Countdown({
    fontSize,
    fontFamily,
    fontColor,
    fontWeight,
    displayDays,
    displayHours,
    displayMinutes,
    displaySeconds,
    endDate,
    endTime,
    endMessage,
}) {
    const [timeLeft, setTimeLeft] = useState(calculateTimeLeft())

    useEffect(() => {
        const timer = setTimeout(() => {
            setTimeLeft(calculateTimeLeft())
        }, 1000)

        return () => clearTimeout(timer)
    })

    function calculateTimeLeft() {
        const difference = +new Date(`${endDate}T${endTime}`) - +new Date()
        let timeLeft = {}

        if (difference > 0) {
            if (difference < 60 * 60 * 1000) {
                // Less than 60 minutes remaining
                const minutes = Math.floor((difference / (1000 * 60)) % 60)
                const seconds = Math.floor((difference / 1000) % 60)

                timeLeft = {
                    days: displayDays ? 0 : null,
                    hours: displayHours ? 0 : null,
                    minutes: displayMinutes ? minutes : null,
                    seconds: displaySeconds ? seconds : null,
                }
            } else {
                const time = {
                    d: Math.floor(difference / (1000 * 60 * 60 * 24)),
                    h: Math.floor((difference / (1000 * 60 * 60)) % 24),
                    m: Math.floor((difference / (1000 * 60)) % 60),
                    s: Math.floor((difference / 1000) % 60),
                }

                timeLeft = {
                    days: displayDays ? time.d : 0,
                    hours: displayHours ? time.h : null,
                    minutes: displayMinutes ? time.m : null,
                    seconds: displaySeconds ? time.s : null,
                }
            }
        }

        return timeLeft
    }

    const timerComponents = []

    Object.keys(timeLeft).forEach((interval) => {
        if (!timeLeft[interval]) {
            return
        }

        timerComponents.push(
            <span
                key={interval}
                style={{
                    display: "flex",
                    alignItems: "center",
                    flexDirection: "column",
                }}
            >
                {timeLeft[interval]}
                <span style={{ fontSize: `${fontSize / 2.5}px` }}>
                    {interval.toLowerCase()}
                </span>
            </span>
        )
    })

    return (
        <div
            style={{
                fontSize,
                fontFamily,
                color: fontColor,
                fontWeight,
                display: "flex",
                gap: "20px",
            }}
        >
            {timerComponents.length ? (
                timerComponents
            ) : (
                <span>{endMessage}</span>
            )}
        </div>
    )
}

addPropertyControls(Countdown, {
    fontSize: {
        type: ControlType.Number,
        unit: "px",
        defaultValue: 30,
    },
    fontFamily: {
        type: ControlType.String,
        defaultValue: "Inter",
    },
    fontColor: {
        type: ControlType.Color,
        defaultValue: "black",
    },
    fontWeight: {
        type: ControlType.Enum,
        defaultValue: 400,
        options: [
            "normal",
            "bold",
            "bolder",
            "lighter",
            100,
            200,
            300,
            400,
            500,
            600,
            700,
            800,
            900,
        ],
    },
    displayDays: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    displayHours: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    displayMinutes: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    displaySeconds: {
        type: ControlType.Boolean,
        defaultValue: true,
    },
    endDate: {
        type: ControlType.String,
        defaultValue: "2023-04-25",
        description: "YYYY-MM-DD",
    },
    endTime: {
        type: ControlType.String,
        defaultValue: "00:00:00",
        description: "HH:MM:SS",
    },
    endMessage: {
        type: ControlType.String,
        defaultValue: "Time's up!",
    },
})

Framer Navigator

Learn the fundamentals of Framer for free.

Build your ideas with ease by learning the basics of website building with Framer.

Nandi portrait's background
Nandi's portrait

Framer Navigator

Learn the fundamentals of Framer for free.

Build your ideas with ease by learning the basics of website building with Framer.

Nandi portrait's background
Nandi's portrait

Framer Navigator

Learn the fundamentals of Framer for free.

Build your ideas with ease by learning the basics of website building with Framer.

Nandi portrait's background
Nandi's portrait

More resources

More resources

  • Animated Dotted Video Component in Framer with circular halftone pattern on a black background and bold white text overlay

    Dotted Video Component for Framer

    Component

    Animated Dotted Video Component in Framer with circular halftone pattern on a black background and bold white text overlay

    Dotted Video Component for Framer

    Component

    Animated Dotted Video Component in Framer with circular halftone pattern on a black background and bold white text overlay

    Dotted Video Component for Framer

    Component

  • Metallic 3D call-to-action button with glowing blue arrow and text 'Lets Grow!' on dark background – modern UI design element with hover interaction

    Metallic 3D Button Interaction in Framer

    Component

    Metallic 3D call-to-action button with glowing blue arrow and text 'Lets Grow!' on dark background – modern UI design element with hover interaction

    Metallic 3D Button Interaction in Framer

    Component

    Metallic 3D call-to-action button with glowing blue arrow and text 'Lets Grow!' on dark background – modern UI design element with hover interaction

    Metallic 3D Button Interaction in Framer

    Component