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.
Created by
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!", }, })