One Page Scroll

HTML

<!DOCTYPE html>
<html lang="ru">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Scroll Sections</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div class="container">
      <section class="section" style="background: #333">Главная</section>
      <section class="section" style="background: #555">Услуги</section>
      <section class="section" style="background: #777">Портфолио</section>
      <section class="section" style="background: #999">Контакты</section>
    </div>

    <script src="script.js"></script>
  </body>
</html>

CSS

body,
html {
  margin: 0;
  padding: 0;
  overflow: hidden;
  font-family: sans-serif;
  scroll-behavior: smooth;
}

.container {
  height: 100vh;
  overflow: hidden;
}

.section {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 3rem;
  color: white;
}

JS

const sections = document.querySelectorAll(".section");
let current = 0;

function scrollToSection(index) {
  if (index < 0 || index >= sections.length) return;
  sections[index].scrollIntoView({ behavior: "smooth" });
  current = index;
}

let isScrolling = false;

window.addEventListener("wheel", (e) => {
  if (isScrolling) return;

  isScrolling = true;
  if (e.deltaY > 0) {
    scrollToSection(current + 1);
  } else {
    scrollToSection(current - 1);
  }

  setTimeout(() => {
    isScrolling = false;
  }, 800); // защита от быстрого скролла
});

React

import { useEffect } from "react";
import "./App.css";

const sections = ["Главная", "Обо мне", "Проекты", "Контакты"];

export default function App() {
  useEffect(() => {
    const handleWheel = (e) => {
      const direction = e.deltaY > 0 ? 1 : -1;
      const sections = document.querySelectorAll(".section");
      const current = Math.round(window.scrollY / window.innerHeight);
      const next = Math.min(
        Math.max(current + direction, 0),
        sections.length - 1,
      );
      window.scrollTo({
        top: next * window.innerHeight,
        behavior: "smooth",
      });
    };
    window.addEventListener("wheel", handleWheel, { passive: false });
    return () => window.removeEventListener("wheel", handleWheel);
  }, []);

  return (
    <div className="wrapper">
      {sections.map((title, i) => (
        <section
          key={i}
          className="section"
          style={{ backgroundColor: `hsl(${i * 80}, 70%, 20%)` }}
        >
          <h1>{title}</h1>
        </section>
      ))}
    </div>
  );
}