Floating Footer

A footer that detaches from the side and floats as you scroll

Installation

1

Install dependencies

npm install framer-motion tailwind-merge clsx
2

Add util file

lib/utils.ts

import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
3

Copy the source code

components/ui/floating-footer.tsx
'use client';
import React, { useRef } from 'react';
import { motion, useScroll, useTransform } from 'framer-motion';

interface FooterProps {
    children?: React.ReactNode;
    height?: string;
    className?: string;
}

export function Footer({
    children,
    height = "100vh",
    className
}: FooterProps) {
    const footerRef = useRef(null)
    const { scrollYProgress } = useScroll({
        target: footerRef,
        offset: ["start center", "end end"]
    });

    const borderRadius = useTransform(
        scrollYProgress,
        [0, 0.2, 0.8, 1],
        [0, 24, 24, 24]
    );

    const marginX = useTransform(
        scrollYProgress,
        [0, 0.1, 0.2, 0.3, 0.7, 0.8, 0.9, 1],
        ["0%", "1%", "2%", "4%", "6%", "7%", "7.5%", "8%"]
    );

    return (
        <div 
        ref={footerRef}
        className={`bottom-0 w-full relative h-[${height}]`}>
            <motion.footer
                style={{
                    borderRadius,
                    marginLeft: marginX,
                    marginRight: marginX,
                    marginBottom: marginX
                }}
                className={`bottom-0 left-0 right-0 sticky bg-neutral-800 transition-all p-8 ${className}`}
            >
                {children}
            </motion.footer>
        </div>
    );
};

export default Footer;

Props

PropTypeDescriptionDefault Value
childrenReactNodeThe actual content of the footer that you wantundefined
heightstringThe total scrolling height of the footer"100vh"
classNamestringClass names for the footerundefined

Inspired by kyu