How to One-Page Website Design (Single-Page Site) with Smooth Scrolling Navigation

Want a sleek one-page WordPress site with buttery-smooth scrolling navigation?

Want a modern one-page WordPress site that looks and feels like the pros — smooth scrolling to sections, sticky menu that highlights where you are, no page reloads, mobile hamburger that just works — and ranks well in Google too?

You know the sites I’m talking about. The ones like devxhub.com or those clean SaaS landing pages where everything flows on one long scroll. Hero at the top grabs attention, then services, testimonials, contact — menu clicks take you there buttery smooth. People love them because they’re fast, app-like, and keep visitors engaged without bouncing to new pages.

The problem? Most tutorials are outdated, bloated with paid plugins, or leave you with jumpy scrolling and header overlap issues. In 2026, you don’t need that headache. You can build this exact setup 100% free using tools that load lightning-fast and play nice with SEO.

That’s why I put together this guide. Whether you go the Elementor route (drag-and-drop easy) or Kadence (insane speed and performance), you’ll get:

  • Real smooth scrolling with easing — no instant jumps
  • Active menu highlighting as you scroll (shows users exactly where they are)
  • Sticky header offset so sections don’t hide under the nav
  • Mobile-ready hamburger menu that scrolls perfectly
  • Bonus tricks like one-section-at-a-time “app feel” and that thin mobile-style scrollbar everyone wants now
  • All with free plugins/themes — no upsells, no bloat killing your load times

And yes, this setup helps your SEO too. One-page sites can rank great when done right — focused content, fast performance, clear internal anchors, and easy crawling. Google loves pages that keep people on-site longer, and this layout does exactly that.

By the end, you’ll have a professional one-pager that converts like crazy for agencies, freelancers, SaaS, portfolios — whatever you’re building.

Ready to ditch multi-page headaches and build something modern? Let’s dive in. Pick the method that fits you best and get it live today. 🚀

(Scroll down for the full step-by-step — Elementor first, then Kadence, plus the extras.)

Hero → Services → Testimonials → Contact… all on one long scrollable page. Menu clicks smoothly scroll to sections (no page reloads). Sticky header. Active menu highlighting. Mobile hamburger. Zero bloat.
This is the modern SaaS/agency/portfolio layout everyone copies in 2026. And yes — you can build it 100% FREE.
Here are the best free methods right now (Elementor way + Kadence way + bonus tricks). Pick one and launch in under an hour.

Method 1: Easiest & Most Reliable → Elementor (Free) + Helpers

Why this wins for most people Elementor handles smooth scroll natively now (since ~2023 updates). Add one tiny plugin for perfect sticky-header offset + active highlighting.

Free stack you need
Elementor (free page builder)
Astra, Kadence or Hello Elementor (lightweight theme)
Optional: Page Scroll to ID (free) → fixes jumpy scroll + header overlap

Step-by-step setup (2026 updated)
Install plugins/themes Plugins → Add New: Elementor + (optional) Page Scroll to ID. Theme: Hello Elementor or Astra/Kadence.

Set homepage Pages → Add New → “Home”. Settings → Reading: Static page → select “Home”.

Build sections in Elementor Edit with Elementor. Drag Sections for Hero, Services, How We Work, Portfolio, Testimonials, Contact. For each: Advanced → CSS ID → hero / services / portfolio / contact (lowercase, no spaces, no #).

Create menu with anchor links Appearance → Menus → Primary Menu. Add Custom Links: URL: #hero → Text: Home URL: #services → Text: Services etc. Assign to Primary/Header location.

Enable smooth scroll & fix header overlap Elementor usually does smooth scroll automatically. Test it. If jumpy or content hides under sticky header: Activate Page Scroll to ID. Settings → Page Scroll to ID: Offset: 80–120px (match your header height)
Speed: 800ms

It auto-highlights active menu items too in most cases.

Sticky header Astra/Kadence Customizer → Header → Sticky. Or Elementor Theme Builder header → sticky.

Polish Mobile: Hamburger auto-works. Add Back to Top: Elementor button → #hero link, or WPFront Scroll Top plugin. Test desktop + mobile. Done.

This replicates devxhub.com perfectly — free, fast, reliable.

Method 2: Kadence Theme + Blocks (Super Lightweight, SaaS Speed)

Kadence is blazing fast (<100ms TTFB possible). Native smooth scroll + sticky header. Add tiny code for pro active highlighting.

Free tools:
– Kadence Theme
– Kadence Blocks
– Code Snippets (for active menu magic)

Step-by-step (pixel-perfect SaaS style)

1. Install & activate
Kadence Theme + Kadence Blocks + Code Snippets.
Customize → General → Performance: Enable Scroll to ID.

2. Homepage setup
Pages → Add New → “Home”.
Reading settings: Static homepage.
Page settings: Full Width, Unboxed, Disable title/header spacing if wanted.

3. Build sections with anchors
Gutenberg/Kadence editor.
Add Row Layout / Section blocks.
Advanced → HTML Anchor: hero / features / pricing / contact.
Use Design Library → search “SaaS” for quick starters.

4. Menu setup
Menus → Primary Menu.
Custom Links: #hero / #features etc.
Customize → Header → Primary Navigation: Assign menu, center align, brand colors, sticky ON.

5. Active highlighting + perfect offset (must-have code)
Code Snippets → Add New.

PHP snippet (offset for sticky header):

add_filter('kadence_scroll_to_id_additional_offset', function($offset){
$offset = 120; // adjust to your header height
$admin_bar = is_admin_bar_showing() ? 32 : 0;
return $offset + $admin_bar;
});

JS snippet (active menu on scroll — paste as HTML/JS in footer):

<script>
function highlightAnchorLinks() {
  const menu = document.getElementById('primary-menu');
  if (!menu) return;
  const links = menu.querySelectorAll('a[href^="#"], a[href^="/#"]');
  const observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
      if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
        const id = entry.target.id;
        menu.querySelectorAll('.current-menu-item').forEach(el => el.classList.remove('current-menu-item'));
        const item = menu.querySelector(`a[href$="#${id}"]`)?.parentNode;
        if (item) item.classList.add('current-menu-item');
      }
    });
  }, {threshold: 0.5});

  links.forEach(link => {
    const id = link.getAttribute('href').replace(/^.*#/, '');
    const section = document.getElementById(id);
    if (section) observer.observe(section);
  });
}
document.addEventListener('DOMContentLoaded', highlightAnchorLinks);
</script>

6. Test & tweak Clear cache. Scroll/click. Smooth. Active items highlight. Customize → Additional CSS for .current-menu-item { color: yourbrand !important; font-weight: 700; }

Bonus 1: Fake “Single Section Visible” Like Mobile App (One Section at a Time)

Want only one section visible (hide others) — super clean, app-like feel.

1. Add class dynamic-section to every section (Advanced → CSS Classes).
2. Additional CSS:

.dynamic-section { display: none; opacity: 0; transition: opacity 0.4s ease; }
#landing, #home { display: block; opacity: 1; }
.dynamic-section.show { opacity: 1; }

JS via Code Snippets (front-end):

document.addEventListener("DOMContentLoaded", () => {
  const sections = document.querySelectorAll(".dynamic-section");
  const links = document.querySelectorAll('a[href^="#"]');

  function showSection(id) {
    sections.forEach(s => { s.classList.remove("show"); s.style.display = "none"; });
    const target = document.getElementById(id);
    if (target) {
      target.style.display = "block";
      setTimeout(() => target.classList.add("show"), 10);
      target.scrollIntoView({behavior: "smooth"});
    }
  }

  links.forEach(link => {
    link.addEventListener("click", e => {
      if (link.getAttribute("href").startsWith("#")) {
        e.preventDefault();
        const id = link.getAttribute("href").substring(1);
        showSection(id);
        links.forEach(l => l.classList.remove("active"));
        link.classList.add("active");
        history.pushState(null, null, `#${id}`);
      }
    });
  });

  const hash = window.location.hash.substring(1);
  showSection(hash || "landing");

  window.addEventListener("popstate", () => {
    showSection(window.location.hash.substring(1) || "landing");
  });
});

Bonus 2: Mobile-Like Thin Scrollbar (2026 Favorite)

Add to Additional CSS:

html {
  scrollbar-width: thin;
  scrollbar-color: #888 transparent;
}
::-webkit-scrollbar { width: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #888; border-radius: 10px; }
::-webkit-scrollbar-thumb:hover { background: #555; }

Test on real phones — iOS/Android often overlay/hide anyway. Perfect for clean SaaS look.

Pick Elementor if you want drag-drop speed. Pick Kadence if you want insane performance. Both free. Both nail the devxhub.com vibe.

Save this. Share it. Build something awesome today.

Here are some extra, battle-tested tricks to level up your one-page WordPress site even more — the kind of small wins that make visitors go “damn, this feels premium” and help you stand out from the average setup. These work perfectly with both the Elementor and Kadence methods I already gave you.

I’ve used every single one of these on client sites in 2025–2026. Pick the ones that match your goals.

1. Sticky “Progress Bar” at the Top (Reading Progress Indicator)

Shows visitors how far they’ve scrolled — great for long one-pagers. Makes the page feel more interactive.
Quick Kadence way (no plugin): Appearance → Customize → Additional CSS:

/* Progress bar */
#reading-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 0%;
  height: 4px;
  background: #0066ff; /* your brand color */
  z-index: 9999;
  transition: width 0.2s ease;
}

Code Snippets → Add New (JS, run on front-end):

<script>
window.addEventListener('scroll', () => {
  const winScroll = document.body.scrollTop || document.documentElement.scrollTop;
  const height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
  const scrolled = (winScroll / height) * 100;
  document.getElementById('reading-progress').style.width = scrolled + '%';
});
</script>

Then add this HTML somewhere high (e.g., Kadence header hook or Elementor custom HTML widget at top of page):

<div id="reading-progress"></div>

Boom — thin colored bar fills as you scroll. Looks super modern.

2. Animate Sections on Scroll (Fade / Slide In)

Sections appear as you scroll down — huge engagement boost.

Free & easy with Kadence Blocks or Elementor:
– In Kadence: Select Row/Section → Advanced → Animation → Entrance Animation (Fade In Up, Slide In Right, etc.). Set Trigger to “Scroll Into View”.
– In Elementor: Section → Advanced → Motion Effects → Entrance Animation → Fade In Up. Viewport: 10–20%.

Pro tip: Delay each section by 100–200ms more than the one above it for a nice cascade effect.

3. Parallax Background on Hero (Subtle, Not Cheesy)

Gives depth without killing mobile performance.

– Kadence way:
Row Layout → Background → Background Type: Image → Parallax: Enable → Speed: 0.3–0.5 (low = subtle).

– Elementor way:
Section → Style → Background → Background Type: Classic → Image → Attachment: Fixed (or use Motion Effects → Background Motion → Parallax).

Mobile fix: Add media query to disable on phones if it feels weird:

@media (max-width: 767px) {
  .your-hero-section { background-attachment: scroll !important; }
}

4. “Scroll to Next Section” Arrow / Button

Floating arrow at bottom of each section that scrolls to the next one. Classic SaaS move.

– Elementor: Add Button widget at bottom of section → Link: #next-section-id → Icon: Arrow Down → Position: Center.

– Kadence: Add Button block → Link to next anchor → Icon: Arrow down.

Make it float & pulse: Additional CSS:

.scroll-next {
  position: absolute;
  bottom: 30px;
  left: 50%;
  transform: translateX(-50%);
  animation: pulse 2s infinite;
}
@keyframes pulse {
  0% { transform: translate(-50%, 0); }
  50% { transform: translate(-50%, 10px); }
  100% { transform: translate(-50%, 0); }
}

Add class “scroll-next” to your button.

5. Hide Header on Scroll Down, Show on Scroll Up

Super clean — header disappears when reading, reappears when going back up.
Code Snippets → JS (front-end):

<script>
let lastScrollTop = 0;
const header = document.querySelector('header.site-header'); // adjust selector if needed

window.addEventListener('scroll', () => {
  let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
  if (scrollTop > lastScrollTop && scrollTop > 200) {
    header.style.transform = 'translateY(-100%)';
    header.style.transition = 'transform 0.3s ease';
  } else {
    header.style.transform = 'translateY(0)';
  }
  lastScrollTop = scrollTop <= 0 ? 0 : scrollTop;
});
</script>

Add this CSS so it doesn’t fight sticky:

header.site-header { transition: transform 0.3s ease; }

6. Smooth Scroll Speed Control (Custom Easing)

Make scroll feel luxurious.
Additional CSS (works everywhere):

html {
  scroll-behavior: smooth;
  scroll-padding-top: 100px; /* your header height + buffer */
}

For fancier easing, Code Snippets JS:

<script>
// Override default smooth scroll
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
  anchor.addEventListener('click', function(e) {
    e.preventDefault();
    const target = document.querySelector(this.getAttribute('href'));
    if (target) {
      target.scrollIntoView({
        behavior: 'smooth',
        block: 'start'
      });
    }
  });
});
</script>

7. Section-Specific Cursor / Hover Effects

Subtle fun: change cursor when hovering over certain sections.
CSS:

#services, #portfolio {
  cursor: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><circle cx="16" cy="16" r="8" fill="%230066ff" opacity="0.6"/></svg>'), auto;
}

Or just:

#hero:hover { cursor: crosshair; }

Adding Confetti on CTA Click (WordPress Edition – 2026 Style)

This is one of those micro-interactions that boosts conversions like crazy on SaaS/agency sites. User clicks “Get Started” or “Submit” → boom, colorful explosion celebrates the action. Feels premium and fun.

The easiest, lightest way uses the canvas-confetti library (super popular, tiny file size, no dependencies). Works great with Elementor, Kadence, Gutenberg — anywhere you can add custom JS.

Option 1: Quick & Dirty (No Plugin – Recommended for Speed)

1. Add the library via CDN (paste this in your footer or header – I like Code Snippets plugin for this):
Code Snippets → Add New → Run Everywhere or Footer:

<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.3/dist/confetti.browser.min.js"></script>

(This is the current version as of 2026 – always check jsDelivr for latest.)

2. Trigger it on your CTA button click.

Find your button’s ID or class (e.g., in Elementor: Advanced → CSS ID = “my-cta” or class “.cta-button”).

Add this JS via Code Snippets (front-end only):

<script>
document.addEventListener('DOMContentLoaded', function() {
  // Replace '#my-cta' with your button's selector
  document.querySelector('#my-cta').addEventListener('click', function(e) {
    // Optional: prevent default if it's a form submit or link
    // e.preventDefault(); // uncomment if needed

    confetti({
      particleCount: 150,       // how many pieces
      spread: 70,               // wider = more dramatic
      origin: { y: 0.6 },       // start from middle-ish (0=top, 1=bottom)
      colors: ['#0066ff', '#00cc99', '#ff3366', '#ffcc00'], // your brand colors
      ticks: 200,               // how long they last
      gravity: 0.5,             // slower fall = prettier
      scalar: 1.2               // bigger pieces
    });

    // Optional: second burst for extra pop
    setTimeout(() => {
      confetti({
        particleCount: 100,
        angle: 120,
        spread: 60,
        origin: { x: 1, y: 0.6 }
      });
    }, 200);
  });
});
</script>

Customize: Play with particleCount (50–300), spread (45–100), colors array to match your brand.
3. Test it: Click your CTA → colorful burst! Works on mobile too.

Similar Posts