DEV Community

Cover image for Build a complete landing page in 30 minutes with pure CSS (no Tailwind, no frameworks)
nJ
nJ

Posted on

Build a complete landing page in 30 minutes with pure CSS (no Tailwind, no frameworks)

Frameworks are great. But sometimes you just want to build a landing page fast — no npm install, no config, no build pipeline. Just HTML and CSS.

In this tutorial I'll show you how to build a complete, responsive landing page in about 20 minutes using njX UI — a pure CSS library you include with one <link> tag.

Here's what we'll build:

💡 Replace with your final result CodePen.

A complete page with:

  • Navigation bar
  • Hero section with gradient text and CTA buttons
  • Features grid (6 cards)
  • Stats section
  • CTA banner
  • Footer

Let's go.


Step 0: Setup (2 minutes)

Create an index.html file. Add njX UI via CDN — that's the only dependency:

<!DOCTYPE html>
<html data-theme="dark">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>My Landing Page</title>

  <!-- njX UI — one line, everything included -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/njx-ui/css/style.min.css">
</head>
<body>

  <!-- we'll build here -->

</body>
</html>
Enter fullscreen mode Exit fullscreen mode

That's it for setup. Open the file in your browser — you'll notice the background is already dark and the font is set. The library applies base styles automatically.

Want a light theme? Change data-theme="dark" to data-theme="light". Or try "blue", "purple", "pink" — there are 9 themes total.


Step 1: Navigation (3 minutes)

<nav class="navbar navbar-sticky">
  <div class="navbar-brand">
    <a href="#" class="navbar-logo">MyProduct</a>
  </div>
  <div class="navbar-menu">
    <a class="navbar-link" href="#features">Features</a>
    <a class="navbar-link" href="#pricing">Pricing</a>
    <a class="navbar-link" href="#docs">Docs</a>
  </div>
  <div class="navbar-actions">
    <a class="btn btn-ghost btn-sm" href="#">Sign in</a>
    <a class="btn btn-primary btn-sm" href="#">Get Started</a>
  </div>
</nav>
Enter fullscreen mode Exit fullscreen mode

navbar-sticky keeps it pinned to the top as you scroll. The navbar collapses gracefully on mobile.


Step 2: Hero section (5 minutes)

This is the most important section — it's what visitors see first.

<section class="section" style="padding-top: 100px; padding-bottom: 80px; text-align: center;">
  <div class="container">

    <!-- Small label above the title -->
    <span class="tag tag-primary">✦ Now in public beta</span>

    <!-- Main headline -->
    <h1 class="text-5xl font-black mt-6" style="line-height: 1.1; letter-spacing: -1px;">
      Build faster with<br>
      <span class="text-gradient-primary">less code</span>
    </h1>

    <!-- Subheadline -->
    <p class="text-lg text-muted mt-6" style="max-width: 480px; margin-left: auto; margin-right: auto; line-height: 1.7;">
      The CSS toolkit for developers who want to ship landing pages
      in hours, not days. Zero config, zero dependencies.
    </p>

    <!-- CTA buttons -->
    <div class="flex gap-3 mt-8" style="justify-content: center; flex-wrap: wrap;">
      <a href="#" class="btn btn-primary btn-lg">🚀 Start for free</a>
      <a href="#" class="btn btn-outline btn-lg">View on GitHub →</a>
    </div>

    <!-- Social proof strip -->
    <div class="flex gap-6 mt-10" style="justify-content: center; flex-wrap: wrap;">
      <span class="text-muted" style="font-size: 13px;">★★★★★ <strong class="text-main">4.9</strong> on Product Hunt</span>
      <span class="text-muted" style="font-size: 13px;">📦 <strong class="text-main">2,400+</strong> npm downloads</span>
      <span class="text-muted" style="font-size: 13px;"><strong class="text-main">340</strong> GitHub stars</span>
    </div>

  </div>
</section>
Enter fullscreen mode Exit fullscreen mode

What's happening here:

  • text-gradient-primary gives the colored gradient text — it automatically uses the active theme color
  • btn btn-primary btn-lg — a large themed button, no extra CSS needed
  • All spacing uses utility classes (mt-6, gap-3) from the library

Step 3: Features grid (5 minutes)

Six feature cards in a responsive grid:

<section class="section" id="features">
  <div class="container">

    <div style="text-align: center; margin-bottom: 48px;">
      <span class="tag">Features</span>
      <h2 class="text-3xl font-bold mt-4">Everything you need</h2>
      <p class="text-muted mt-3" style="max-width: 460px; margin-left: auto; margin-right: auto;">
        Built for speed. Designed for developers who ship.
      </p>
    </div>

    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px;">

      <div class="card hover-lift">
        <div class="card-body">
          <div class="text-2xl mb-3"></div>
          <h3 class="font-bold mb-2">Zero Dependencies</h3>
          <p class="text-muted text-sm">Pure CSS with optional vanilla JS. No npm install, no build step required.</p>
        </div>
      </div>

      <div class="card hover-lift">
        <div class="card-body">
          <div class="text-2xl mb-3">🎨</div>
          <h3 class="font-bold mb-2">9 Built-in Themes</h3>
          <p class="text-muted text-sm">Switch between dark, light, and 7 color themes with one HTML attribute.</p>
        </div>
      </div>

      <div class="card hover-lift">
        <div class="card-body">
          <div class="text-2xl mb-3">📦</div>
          <h3 class="font-bold mb-2">~40KB Minified</h3>
          <p class="text-muted text-sm">25+ components smaller than a single hero image. Fast by default.</p>
        </div>
      </div>

      <div class="card hover-lift">
        <div class="card-body">
          <div class="text-2xl mb-3">🎛️</div>
          <h3 class="font-bold mb-2">CSS Variable API</h3>
          <p class="text-muted text-sm">Every color, font, and radius is a token. Reskin everything in 10 lines.</p>
        </div>
      </div>

      <div class="card hover-lift">
        <div class="card-body">
          <div class="text-2xl mb-3">🔤</div>
          <h3 class="font-bold mb-2">12 Font Presets</h3>
          <p class="text-muted text-sm">Inter, Poppins, Space Grotesk and more. Switch fonts in one line.</p>
        </div>
      </div>

      <div class="card hover-lift">
        <div class="card-body">
          <div class="text-2xl mb-3">📐</div>
          <h3 class="font-bold mb-2">Works Everywhere</h3>
          <p class="text-muted text-sm">HTML, React, Vue, Svelte — if it renders HTML, njX UI works.</p>
        </div>
      </div>

    </div>
  </div>
</section>
Enter fullscreen mode Exit fullscreen mode

hover-lift is a hover effect class from the library — it smoothly lifts the card on hover with a shadow. No extra CSS.


Step 4: Stats section (2 minutes)

Numbers build trust. This takes 2 minutes:

<section class="section">
  <div class="container">
    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 24px; text-align: center;">

      <div>
        <div class="text-4xl font-black text-gradient-primary">25+</div>
        <div class="text-muted text-sm mt-2">Components</div>
      </div>

      <div>
        <div class="text-4xl font-black text-gradient-primary">9</div>
        <div class="text-muted text-sm mt-2">Color themes</div>
      </div>

      <div>
        <div class="text-4xl font-black text-gradient-primary">~40KB</div>
        <div class="text-muted text-sm mt-2">Minified size</div>
      </div>

      <div>
        <div class="text-4xl font-black text-gradient-primary">0</div>
        <div class="text-muted text-sm mt-2">Dependencies</div>
      </div>

    </div>
  </div>
</section>
Enter fullscreen mode Exit fullscreen mode

Step 5: CTA banner (2 minutes)

A final push before the footer:

<section class="section">
  <div class="container">
    <div class="card border-gradient-primary" style="text-align: center; padding: 52px 40px;">
      <h2 class="text-3xl font-bold mb-4">Ready to ship faster?</h2>
      <p class="text-muted mb-8" style="max-width: 400px; margin-left: auto; margin-right: auto;">
        Drop one link tag into your project and start building in minutes.
      </p>
      <div style="background: var(--bg-main); border: 1px solid color-mix(in srgb, var(--color-neutral-600) 25%, transparent); border-radius: 10px; padding: 10px 18px; display: inline-block; margin-bottom: 24px;">
        <code style="font-size: 13px; color: var(--color-primary);">
          &lt;link rel="stylesheet" href="cdn.jsdelivr.net/npm/njx-ui/css/style.min.css"&gt;
        </code>
      </div>
      <div class="flex gap-3" style="justify-content: center; flex-wrap: wrap;">
        <a href="#" class="btn btn-primary">Get Started Free</a>
        <a href="#" class="btn btn-ghost">★ Star on GitHub</a>
      </div>
    </div>
  </div>
</section>
Enter fullscreen mode Exit fullscreen mode

border-gradient-primary applies a gradient border that follows the active theme — a nice premium touch with zero custom CSS.


Step 6: Footer (1 minute)

<footer class="section" style="border-top: 1px solid color-mix(in srgb, var(--color-neutral-600) 18%, transparent); padding-top: 32px; padding-bottom: 32px;">
  <div class="container" style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 16px;">
    <span class="text-muted text-sm">© 2025 MyProduct. Built with njX UI.</span>
    <div class="flex gap-4">
      <a href="#" class="text-muted text-sm hover-primary">GitHub</a>
      <a href="#" class="text-muted text-sm hover-primary">npm</a>
      <a href="#" class="text-muted text-sm hover-primary">Docs</a>
    </div>
  </div>
</footer>
Enter fullscreen mode Exit fullscreen mode

Bonus: Add a theme switcher (optional, 5 minutes)

Want visitors to be able to switch the theme live? Add this anywhere on the page:

<!-- Theme pills in the navbar -->
<div style="display: flex; gap: 6px; align-items: center;">
  <div onclick="setTheme('dark')"   style="width:16px;height:16px;border-radius:50%;background:#4a4a56;cursor:pointer"></div>
  <div onclick="setTheme('blue')"   style="width:16px;height:16px;border-radius:50%;background:#3b82f6;cursor:pointer"></div>
  <div onclick="setTheme('purple')" style="width:16px;height:16px;border-radius:50%;background:#a855f7;cursor:pointer"></div>
  <div onclick="setTheme('pink')"   style="width:16px;height:16px;border-radius:50%;background:#ec4899;cursor:pointer"></div>
  <div onclick="setTheme('light')"  style="width:16px;height:16px;border-radius:50%;background:#e2e8f0;cursor:pointer"></div>
</div>

<script>
  function setTheme(t) {
    document.documentElement.setAttribute('data-theme', t);
    try { localStorage.setItem('njx-theme', t); } catch(e) {}
  }
  const saved = localStorage.getItem('njx-theme');
  if (saved) document.documentElement.setAttribute('data-theme', saved);
</script>
Enter fullscreen mode Exit fullscreen mode

That's literally the entire theme switcher. Click a dot → entire page recolors instantly using CSS custom properties. No page reload.


Final result

Here's the complete page we just built:

💡 Replace with your final landing page CodePen.

The whole thing is ~60 lines of HTML with zero custom CSS. Try changing data-theme="dark" to data-theme="purple" on the <html> tag — every color on the page updates at once.


What we used

Class What it does
data-theme="dark" Sets the active color theme
btn btn-primary btn-lg Large themed button
text-gradient-primary Gradient text in theme color
card hover-lift Card that lifts on hover
border-gradient-primary Gradient border card
text-muted Secondary text color
text-5xl font-black Typography utilities
container Centered max-width wrapper
section Section with standard padding

Going further

In the next post I'll show how the 9-theme system actually works under the hood — pure CSS custom properties, zero JavaScript for the styling itself.


Did this save you time? Drop a ❤️ or leave a comment — what would you build next?

Top comments (0)