How Simple Animations Can Make a Big Impact on Your Website



This content originally appeared on DEV Community and was authored by Sushil

Animations aren’t just for fancy websites or landing pages. Even subtle, simple animations can make your site feel smoother, more polished, and more enjoyable to use.

In this post, I’ll show you how I used basic animations with Framer Motion and React to create a smooth experience on a component I call Smooth Reveal.

🎥 Live Demo

I made a small demo to show this in action.
👉 Check it out here

🔧 What’s Inside the Smooth Reveal Component?

Here’s what happens in the demo:

  • Navbar fades in from the top.
  • Main section smoothly reveals the text WI and LD, with a video expanding in the center.
  • Footer slides in with content and a CTA button.

🧩 Full Code Overview

  1. Navbar.tsx A simple navbar with animated hover effect and theme switcher:
"use client";

import Link from "next/link";
import React, { useState } from "react";
import { motion } from "motion/react";
import MotionDiv from "@/components/animation/motion-div";
import { MoonIcon, SunIcon } from "lucide-react";
import { useTheme } from "next-themes";

const links = [
  { name: "Home", href: "/" },
  { name: "About", href: "/about" },
  { name: "Contact", href: "/contact" },
];

const Navbar = () => {
  const [isHovered, setIsHovered] = useState<number | null>(null);
  const { theme, setTheme } = useTheme();

  return (
    <MotionDiv
      initial={{ y: -10, opacity: 0 }}
      animate={{ y: 0, opacity: 1 }}
      transition={{ duration: 0.5, delay: 0.6 }}
      className="flex w-full justify-between sm:h-10"
    >
      <div className="flex flex-col items-start sm:flex-row sm:items-center">
        {links.map((link, idx) => (
          <Link
            key={idx}
            href={link.href}
            className="relative flex gap-1 px-2.5 py-1.5 text-[14px] sm:px-4.5"
            onMouseEnter={() => setIsHovered(idx)}
            onMouseLeave={() => setIsHovered(null)}
          >
            {isHovered === idx && (
              <motion.span
                layoutId="hovered-span"
                className="absolute inset-0 h-full w-full rounded-2xl bg-neutral-900 backdrop-blur-sm dark:bg-neutral-100"
                transition={{ duration: 0.3 }}
              />
            )}
            <span className={`relative z-10 font-medium transition-colors duration-300 ${
              isHovered === idx
                ? "text-white dark:text-black"
                : "text-black dark:text-white"
            }`}>
              {link.name}
            </span>
          </Link>
        ))}
      </div>

      <div className="flex items-start justify-start gap-3 sm:items-center sm:gap-4">
        <Link
          href="/login"
          className="hidden items-center justify-center rounded-xl bg-neutral-200 px-4 py-1.5 text-sm font-medium text-neutral-900 hover:bg-neutral-300 sm:flex sm:px-6"
        >
          Login
        </Link>
        <Link
          href="/signup"
          className="hidden items-center justify-center rounded-xl bg-neutral-800 px-4 py-1.5 text-sm font-medium text-neutral-100 hover:bg-neutral-700 sm:flex sm:px-6"
        >
          Sign Up
        </Link>
        <motion.button
          onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
          className="ml-1 rounded-full border p-2 text-neutral-900 hover:bg-neutral-100 dark:text-neutral-100 hover:dark:bg-neutral-800"
          whileHover={{ scale: 1.05 }}
          whileTap={{ scale: 0.95 }}
        >
          <motion.span
            key={theme}
            initial={{ rotate: -180, opacity: 0 }}
            animate={{ rotate: 0, opacity: 1 }}
            transition={{ duration: 0.3 }}
            className="flex size-4 items-center justify-center"
          >
            {theme === "dark" ? <MoonIcon /> : <SunIcon />}
          </motion.span>
        </motion.button>
      </div>
    </MotionDiv>
  );
};

export default Navbar;

  1. Main.tsx The central text and animated video reveal section:
"use client";

import React, { useEffect, useState } from "react";
import { motion } from "framer-motion";

const Main = () => {
  const [isSmallScreen, setIsSmallScreen] = useState(false);

  useEffect(() => {
    const handleResize = () => {
      setIsSmallScreen(window.innerWidth < 640);
    };
    handleResize();
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  return (
    <div className="flex h-full w-full items-center justify-center text-[24vw] font-semibold text-neutral-900 md:text-[18vw] xl:text-[14vw] dark:text-white">
      <div className="flex w-full flex-col items-center sm:flex-row sm:justify-center">
        <motion.span
          initial={{ opacity: 0, x: -50, scale: 0.9 }}
          animate={{ opacity: 1, x: 0, scale: 1 }}
          transition={{ duration: 0.8, delay: 0.1 }}
        >
          WI
        </motion.span>

        <motion.div
          initial={{ width: "0px" }}
          animate={{ width: isSmallScreen ? "90%" : "35%" }}
          transition={{ duration: 0.7, delay: 0.3 }}
          className="mx-2 overflow-hidden rounded-full"
        >
          <motion.video
            initial={{ width: "0px" }}
            animate={{ width: "100%" }}
            transition={{ duration: 0.5, delay: 0.4 }}
            autoPlay
            muted
            loop
            playsInline
            className="h-full w-full object-cover"
          >
            <source src="/playground/car-shot.mp4" type="video/mp4" />
          </motion.video>
        </motion.div>

        <motion.span
          initial={{ opacity: 0, x: 50, scale: 0.9 }}
          animate={{ opacity: 1, x: 0, scale: 1 }}
          transition={{ duration: 0.8, delay: 0.1 }}
        >
          LD
        </motion.span>
      </div>
    </div>
  );
};

export default Main;
  1. Footer.tsx Simple fade-in footer with a message and CTA button:
import MotionDiv from "@/components/animation/motion-div";
import React from "react";

const Footer = () => {
  return (
    <MotionDiv
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.5, delay: 0.6 }}
      className="flex w-full flex-col items-start justify-between gap-4 px-4 sm:flex-row sm:items-center sm:gap-0"
    >
      <p className="text-xs leading-relaxed text-neutral-400 sm:max-w-md sm:text-sm lg:max-w-5xl">
        Discover extraordinary experiences that push the boundaries of innovation. Our platform connects visionaries with cutting-edge solutions, turning ideas into reality through seamless collaboration.
      </p>

      <button className="mb-4 rounded-xl bg-neutral-800 px-4 text-sm font-medium text-white hover:bg-neutral-700 sm:mb-0 sm:px-6 sm:py-2 dark:bg-neutral-100 dark:text-black">
        Explore More
      </button>
    </MotionDiv>
  );
};

export default Footer;
  1. SmoothReveal.tsx Combining everything into one complete component:
import React from "react";
import Navbar from "./navbar";
import Main from "./main";
import Footer from "./footer";

const SmoothReveal = () => {
  return (
    <div className="hide-scrollbar relative flex h-[85vh] w-full flex-col items-center justify-between rounded-2xl bg-neutral-50 p-4 dark:bg-neutral-900">
      <div className="absolute inset-0 h-full w-full bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:72px_72px]" />
      <div className="z-10 flex h-full w-full flex-col items-center justify-between">
        <Navbar />
        <Main />
        <Footer />
      </div>
    </div>
  );
};

export default SmoothReveal;

🧠 Final Thoughts

You don’t need overly complex animation libraries to make your website feel smooth and modern. Just a few well-placed transitions can make a huge difference.

Start small, stay consistent, and build from there.

👉 Live Demo – Smooth Reveal
Check out my full Portfolio
🐦 Follow me on Twitter for more frontend experiments and project updates.

Let me know what you think or share how you’re using animation in your own projects!


This content originally appeared on DEV Community and was authored by Sushil