Membuat Landing Page Sederhana dan Cepat dengan ReactJS, Vite, dan Tailwind CSS

RMAG news

Pendahuluan

Landing page yang efektif dapat menjadi alat yang ampuh untuk menarik perhatian audiens dan meningkatkan konversi. Dalam artikel ini, kita akan membahas cara membuat landing page modern menggunakan Vite sebagai build tool, ReactJS sebagai framework UI, dan Tailwind CSS untuk styling yang efisien.

Membuat Struktur Komponen Landing Page

Buat komponen dasar seperti LandingPage, Home, Footer, About dan OurFeatures. Contoh sederhana untuk komponen Appadalah sebagai berikut:

import { StrictMode } from react
import { createRoot } from react-dom/client
import LandingPage from ./LandingPage.tsx
import ./index.css

createRoot(document.getElementById(root)!).render(
<StrictMode>
<LandingPage />
</StrictMode>,
)

Landing Page

import React, { lazy } from react;
import { ChevronUp } from lucide-react;

const NavBar = lazy(() => import(./layout/NavBar));
const Home = lazy(() => import(./page/Home));
const OurFeatures = lazy(() => import(./page/OurFeatures));
const AboutUs = lazy(() => import(./page/AboutUs));
const Footer = lazy(() => import(./page/Footer));

const LandingPage = () => {

const windowScroll = () => {
const backToTop = document.getElementById(back-to-top);
if (backToTop) {
if (document.body.scrollTop >= 50 || document.documentElement.scrollTop >= 50) {
backToTop.style.opacity = 1;
} else {
backToTop.style.opacity = 0;
}
}
};

React.useEffect(() => {
window.addEventListener(scroll, windowScroll);

window.addEventListener(load, windowScroll);

return () => {
window.removeEventListener(scroll, windowScroll);
};
}, []);

const handleScroll = () => {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
};

React.useEffect(() => {
const bodyElement = document.body;

bodyElement.classList.add(text-base, bg-white, text-body, font-public);

return () => {
bodyElement.classList.remove(text-base, bg-white, text-body, font-public);
}
}, []);

React.useEffect(() => {
document.documentElement.classList.add(overflow-x-hidden, scroll-smooth, group);
return () => {
document.documentElement.classList.remove(overflow-x-hidden, scroll-smooth, group);
};
}, []);

return (
<React.Fragment>

<NavBar />
<Home />
<OurFeatures />
<AboutUs />
<Footer />

<button id=back-to-top
className=fixed flex items-center justify-center size-10 text-white bg-purple-500 rounded-md bottom-10 right-10
onClick={handleScroll}>
<ChevronUp className=animate animate-icons></ChevronUp>
</button>
</React.Fragment>
);
};

export default LandingPage;

Navbar

import React from react;
import { Menu } from lucide-react;

const NavBar = () => {

const [isToggle, setIsToggle] = React.useState<boolean>(false);
const [activeLink, setActiveLink] = React.useState<string>(/Home);

const handleLinkClick = (target: string) => {
setActiveLink(target);
};

React.useEffect(() => {
const defaultLinkElement = document.querySelector(`.navbar-menu li.active`);

if (defaultLinkElement) {
setActiveLink(defaultLinkElement.getAttribute(href) || /Home);
}
}, [activeLink]);

const [navClass, setNavClass] = React.useState<string>();

// scroll
const scrollNavigation = () => {
var scrollUp = document.documentElement.scrollTop;
if (scrollUp >= 50) {
setNavClass(is-sticky duration-700);
} else {
setNavClass();
}
};

React.useEffect(() => {
window.addEventListener(scroll, scrollNavigation, true);

// Cleanup function to remove the event listener
return () => {
window.removeEventListener(scroll, scrollNavigation, true);
};
}, []);

return (
<React.Fragment>
<nav className={`fixed inset-x-0 top-0 z-50 flex items-center justify-center h-20 py-3 [&.is-sticky]:bg-white border-b border-slate-200 [&.is-sticky]:shadow-lg [&.is-sticky]:shadow-slate-200/25 navbar ${navClass}`} id=navbar>
<div className=container 2xl:max-w-[87.5rem] px-4 mx-auto flex items-center self-center w-full>
<div className=mx-auto>
<ul id=navbar7 className={`absolute inset-x-0 z-20 items-center py-3 bg-white shadow-lg
md:z-0 navbar-menu rounded-b-md md:shadow-none md:flex top-full ltr:ml-auto rtl:mr-auto md:relative md:bg-transparent md:rounded-none md:top-auto md:py-0
${!isToggle ? hidden : “”}`}>
<li>
<a href=#home
className={`block md:inline-block px-4 md:px-3 py-2.5 md:py-0.5 text-15 font-medium text-slate-800 transition-all duration-300 ease-linear hover:text-custom-500 [&.active]:text-custom-500 ${activeLink === /Home ? active : “”}`}
onClick={() => handleLinkClick(/Home)}
>
Home</a>
</li>
<li>
<a href=#features
className={`block md:inline-block px-4 md:px-3 py-2.5 md:py-0.5 text-15 font-medium text-slate-800 transition-all duration-300 ease-linear hover:text-custom-500 [&.active]:text-custom-500 ${activeLink === /Features ? active : “”}`}
onClick={() => handleLinkClick(/Features)}
>
Layanan Kami</a>
</li>
<li>
<a href=#about
className={`block md:inline-block px-4 md:px-3 py-2.5 md:py-0.5 text-15 font-medium text-slate-800 transition-all duration-300 ease-linear hover:text-custom-500 [&.active]:text-custom-500 ${activeLink === /About ? active : “”}`}
onClick={() => handleLinkClick(/About)}
>
Tentang Kami</a>
</li>
<li>
<a href=#contact
className={`block md:inline-block px-4 md:px-3 py-2.5 md:py-0.5 text-15 font-medium text-slate-800 transition-all duration-300 ease-linear hover:text-custom-500 [&.active]:text-custom-500 ${activeLink === /Contact ? active : “”}`}
onClick={() => handleLinkClick(/Contact)}
>
Kontak</a>
</li>
</ul>
</div>
<div className=flex gap-2>
<div className=ltr:ml-auto rtl:mr-auto md:hidden navbar-toggale-button>
<button type=button
className=flex items-center justify-center size-[37.5px] p-0 text-white btn bg-custom-500 border-custom-500 hover:text-white hover:bg-custom-600 hover:border-custom-600 focus:text-white focus:bg-custom-600 focus:border-custom-600 focus:ring focus:ring-custom-100 active:text-white active:bg-custom-600 active:border-custom-600 active:ring active:ring-custom-100
onClick={() => setIsToggle(!isToggle)}
>
<Menu></Menu></button>
</div>

</div>
</div>
</nav>
</React.Fragment>
);
}

export default NavBar;

Home

import React from react;

const Home = () => {
return (
<React.Fragment>
<section className=relative pb-36 pt-44 id=home>

<div className=container 2xl:max-w-[87.5rem] px-4 mx-auto>
<div className=grid grid-cols-12 2xl:grid-cols-2>
<div className=col-span-12 lg:col-span-7 2xl:col-span-1>
<h1 className=mb-8 !leading-relaxed md:text-5xl>Belajar membaut aplikasi <span className=relative inline-block px-2 mx-2 before:block before:absolute before:-inset-1 before:-skew-y-6 before:bg-sky-50 before:rounded-md before:backdrop-blur-xl><span className=relative text-sky-500>Dashboard</span></span></h1>
<p className=mb-6 text-lg text-slate-500>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Rem eligendi soluta animi tempora, porro eaque aliquam ea provident delectus dolorem explicabo consectetur culpa fugiat illum vitae veniam enim corrupti. Libero.</p>

</div>
</div>
</div>
</section>

</React.Fragment>
);
}

export default Home;

OurFeatures

import React from react;

// Image
import widgets from ./../assets/card-1.png;
import widgets2 from ./../assets/card-2.png;
import widgets3 from ./../assets/chart-1.png;
import widgets4 from ./../assets/chart-2.png;
import home from ./../assets/table.png;
import achievement from ./../assets/achievement.png;

const OurFeatures = () => {
return (
<React.Fragment>
<section className=relative py-32 bg-slate-900 id=features>
<div className=container 2xl:max-w-[87.5rem] px-4 mx-auto>
<div className=grid grid-cols-1 gap-5 xl:grid-cols-12>
<div className=order-2 xl:col-span-5 xl:order-1>
<div className=relative z-10 grid grid-cols-3 gap-5 xl:grid-cols-12>
<div className=xl:col-span-12>
<img src={widgets} alt=“” className=shadow-xl rtl:mr-auto ltr:ml-auto rounded-xl />
</div>
<div className=xl:col-span-6>
<img src={widgets3} alt=“” className=shadow-xl xl:mt-5 rtl:mr-auto ltr:ml-auto rounded-xl />
</div>
<div className=xl:col-span-6>
<img src={widgets2} alt=“” className=shadow-xl xl:mt-5 rtl:mr-auto ltr:ml-auto rounded-xl />
<img src={widgets4} alt=“” className=shadow-xl xl:mt-5 rtl:mr-auto ltr:ml-auto rounded-xl mt-2 />
</div>
</div>
</div>
<div className=relative z-20 order-1 xl:-mt-72 xl:col-span-7 xl:order-last>
<img src={home} alt=“” className=shadow-2xl rounded-xl />
<img src={achievement} alt=“” className=shadow-2xl rounded-xl mt-2 />
</div>
</div>
</div>
</section>

</React.Fragment>
);
}

export default OurFeatures;

AboutUs

import React from react;
import { MoveRight } from lucide-react;

// Image
import widgets from ./../assets/widgets.jpg;
import widgets2 from ./../assets/widgets-2.jpg;
import widgets4 from ./../assets/widgets-4.jpg;
import widgets5 from ./../assets/widgets-5.jpg;

const AboutUs = () => {
return (
<React.Fragment>
<section className=relative py-10 id=about>
<div className=container 2xl:max-w-[87.5rem] px-4 mx-auto>

<div className=grid items-center grid-cols-1 gap-6 mt-20 lg:grid-cols-12>
<div className=lg:col-span-5>
<h1 className=mb-3 leading-normal capitalize>Craft a Complete Website Quickly with the Help of Design Blocks</h1>
<p className=mb-6 text-lg text-slate-500 >The block design approach basically breaks the design into small parts. These are built independently and then later combine into a customizable page which makes a website more flexible in terms of layout and content.</p>
<button type=button className=py-2.5 px-6 bg-white text-custom-500 btn border-custom-500 hover:text-white hover:bg-custom-600 hover:border-custom-600 focus:text-white focus:bg-custom-600 focus:border-custom-600 focus:ring focus:ring-custom-100 active:text-white active:bg-custom-600 active:border-custom-600 active:ring active:ring-custom-100 >
<span className=align-middle>Discover Now</span> <MoveRight className=”inline-block size-4 align-middle ltr:ml-1 rtl:mr-1 rtl:rotate-180″></MoveRight></button>
</div>
<div className=text-center lg:col-span-6>
<img src={widgets4} alt=“” className=shadow-lg ltr:lg:ml-auto rtl:lg:mr-auto rounded-xl />
<img src={widgets5} alt=“” className=relative -mt-24 shadow-lg ltr:ml-auto ltr:mr-24 rtl:mr-auto rtl:ml-24 rounded-xl />
</div>
</div>

<div className=grid items-center grid-cols-1 gap-6 mt-32 lg:grid-cols-12>
<div className=text-center lg:col-span-6>
<img src={widgets2} alt=“” className=shadow-lg ltr:ml-auto rtl:mr-auto rounded-xl />
<img src={widgets} alt=“” className=relative -mt-24 ml-[30%] shadow-lg ltr:ml-auto rtl:mr-auto ltr:mr-24 rtl:ml-24 rounded-xl />
</div>
<div className=lg:col-span-5>
<h1 className=mb-3 leading-normal capitalize>Boost Your Business Using Our Potent Tools</h1>
<p className=mb-6 text-lg text-slate-500 >The block design approach basically breaks the design into small parts. These are built independently and then later combine into a customizable page which makes a website more flexible in terms of layout and content.</p>
<button type=button className=py-2.5 px-6 bg-white text-custom-500 btn border-custom-500 hover:text-white hover:bg-custom-600 hover:border-custom-600 focus:text-white focus:bg-custom-600 focus:border-custom-600 focus:ring focus:ring-custom-100 active:text-white active:bg-custom-600 active:border-custom-600 active:ring active:ring-custom-100 >
<span className=align-middle>Discover Now</span> <MoveRight className=”inline-block size-4 align-middle ltr:ml-1 rtl:mr-1 rtl:rotate-180″></MoveRight></button>
</div>
</div>

</div>
</section>
</React.Fragment>
);
}

export default AboutUs;

Footer

import React from “react”;
import { Facebook, Instagram, Linkedin, Twitter, Youtube } from “lucide-react”;

// Image

const Footer = () => {
return (
<React.Fragment>
<footer className=”relative pt-20 pb-12 bg-slate-800″>
<div className=”container 2xl:max-w-[87.5rem] px-4 mx-auto”>
<div className=”relative z-10 grid grid-cols-12 gap-5 xl:grid-cols-12″>
<div className=”col-span-12 md:col-span-6 lg:col-span-4 xl:col-span-3″>
<h5 className=”mb-4 font-medium tracking-wider text-slate-50″>Dashboards</h5>
<ul className=”flex flex-col gap-3 text-15″>
<li>
<a href=”#!” className=”relative inline-block transition-all duration-200 ease-linear text-slate-400 hover:text-slate-300 before:absolute before:border-b before:border-slate-500 before:inset-x-0 before:bottom-0 before:w-0 hover:before:w-full before:transition-all before:duration-300 before:ease-linear”>Analytics</a>
</li>
<li>
<a href=”#!” className=”relative inline-block transition-all duration-200 ease-linear text-slate-400 hover:text-slate-300 before:absolute before:border-b before:border-slate-500 before:inset-x-0 before:bottom-0 before:w-0 hover:before:w-full before:transition-all before:duration-300 before:ease-linear”>CRM</a>
</li>
</ul>
</div>
<div className=”col-span-12 md:col-span-6 lg:col-span-4 xl:col-span-3″>
<h5 className=”mb-4 font-medium tracking-wider text-slate-50″>Apps Pages</h5>
<ul className=”flex flex-col gap-3 text-15″>
<li>
<a href=”#!” className=”relative inline-block transition-all duration-200 ease-linear text-slate-400 hover:text-slate-300 before:absolute before:border-b before:border-slate-500 before:inset-x-0 before:bottom-0 before:w-0 hover:before:w-full before:transition-all before:duration-300 before:ease-linear”>Ecommerce Apps</a>
</li>
<li>
<a href=”#!” className=”relative inline-block transition-all duration-200 ease-linear text-slate-400 hover:text-slate-300 before:absolute before:border-b before:border-slate-500 before:inset-x-0 before:bottom-0 before:w-0 hover:before:w-full before:transition-all before:duration-300 before:ease-linear”>Invoices</a>
</li>

</ul>
</div>
<div className=”col-span-12 md:col-span-6 lg:col-span-4 xl:col-span-2″>
<h5 className=”mb-4 font-medium tracking-wider text-slate-50″>Resources</h5>
<ul className=”flex flex-col gap-3 text-15″>
<li>
<a href=”#!” className=”relative inline-block transition-all duration-200 ease-linear text-slate-400 hover:text-slate-300 before:absolute before:border-b before:border-slate-500 before:inset-x-0 before:bottom-0 before:w-0 hover:before:w-full before:transition-all before:duration-300 before:ease-linear”>All Resources</a>
</li>
<li>
<a href=”#!” className=”relative inline-block transition-all duration-200 ease-linear text-slate-400 hover:text-slate-300 before:absolute before:border-b before:border-slate-500 before:inset-x-0 before:bottom-0 before:w-0 hover:before:w-full before:transition-all before:duration-300 before:ease-linear”>Blog</a>
</li>
</ul>
</div>
<div className=”col-span-12 md:col-span-6 lg:col-span-12 xl:col-span-4″>
<div className=”flex”>
<div className=”flex-1″>
<p className=”mb-1 text-slate-500 text-15″>Support Email</p>
<h5 className=”text-lg !font-normal text-slate-200″>support@xxxx.com</h5>

</div>

<div className=”flex-1″>
<p className=”mb-1 text-slate-500 text-15″>Contact Us</p>
<h5 className=”text-lg !font-normal text-slate-200″>+(012) 1111 222 3434</h5>

</div>
</div>

</div>
</div>

<div className=”py-5 mt-20 border-y border-slate-700″>
<div className=”relative z-10 grid grid-cols-1 gap-5 md:grid-cols-12″>

<div className=”md:col-span-3 md:col-start-10″>
<ul className=”flex items-center gap-3 md:justify-end”>
<li>
<a href=”#!” className=”flex items-center justify-center size-10 transition-all duration-200 ease-linear border rounded-full text-slate-400 border-slate-700 hover:text-custom-500″>
<Facebook className=”size-4″></Facebook></a>
</li>
<li>
<a href=”#!” className=”flex items-center justify-center size-10 transition-all duration-200 ease-linear border rounded-full text-slate-400 border-slate-700 hover:text-custom-500″>
<Linkedin className=”size-4″></Linkedin></a>
</li>
<li>
<a href=”#!” className=”flex items-center justify-center size-10 transition-all duration-200 ease-linear border rounded-full text-slate-400 border-slate-700 hover:text-custom-500″>
<Instagram className=”size-4″></Instagram></a>
</li>
<li>
<a href=”#!” className=”flex items-center justify-center size-10 transition-all duration-200 ease-linear border rounded-full text-slate-400 border-slate-700 hover:text-custom-500″>
<Twitter className=”size-4″></Twitter></a>
</li>
<li>
<a href=”#!” className=”flex items-center justify-center size-10 transition-all duration-200 ease-linear border rounded-full text-slate-400 border-slate-700 hover:text-custom-500″>
<Youtube className=”size-4″></Youtube></a>
</li>
</ul>
</div>
</div>
</div>

<div className=”mt-12 text-center text-slate-400 text-16″>
<p>
{new Date().getFullYear()} © ramadhan. Design & Develop by
</p>
</div>
</div>
</footer>
</React.Fragment>
);
}

export default Footer;

Please follow and like us:
Pin Share