Nazmul Hub | Enterprise Header

Wave Motion Slider (CSS Wave)

Wave Motion Slider (CSS Wave)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Nazmul // Wave Motion Slider</title>
    <style>
        :root {
            --primary: #ffffff;
            --accent: #ff3e00;
            --bg: #0a0a0a;
            --font-main: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
            --transition-speed: 0.8s;
            --wave-stagger: 0.025s;
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            background-color: var(--bg);
            color: var(--primary);
            font-family: var(--font-main);
            overflow: hidden;
            height: 100vh;
        }

        /* --- Layout --- */
        .app-container {
            position: relative;
            width: 100%;
            height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .navbar {
            position: absolute;
            top: 0;
            width: 100%;
            padding: 40px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            z-index: 100;
            mix-blend-mode: difference;
        }

        .logo {
            font-size: 1.2rem;
            font-weight: 900;
            letter-spacing: 5px;
            text-transform: uppercase;
        }

        .nav-links {
            display: flex;
            gap: 40px;
            list-style: none;
            font-size: 0.8rem;
            text-transform: uppercase;
            letter-spacing: 2px;
        }

        /* --- Slider Logic --- */
        .slider {
            position: relative;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        .slide {
            position: absolute;
            inset: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            opacity: 0;
            pointer-events: none;
            transition: opacity 0.5s ease;
        }

        .slide.active {
            opacity: 1;
            pointer-events: all;
        }

        /* --- Content Styling --- */
        .slide-content {
            position: relative;
            z-index: 10;
            text-align: center;
            max-width: 800px;
        }

        .slide-number {
            font-size: 1rem;
            display: block;
            margin-bottom: 20px;
            overflow: hidden;
        }

        .slide-number span {
            display: block;
            transform: translateY(100%);
            transition: transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
        }

        .active .slide-number span {
            transform: translateY(0);
        }

        .slide-title {
            font-size: clamp(3rem, 10vw, 8rem);
            font-weight: 800;
            line-height: 0.9;
            text-transform: uppercase;
            margin-bottom: 30px;
            overflow: hidden;
        }

        .slide-title span {
            display: block;
            transform: translateY(110%);
        }

        .active .slide-title span {
            transform: translateY(0);
        }

        /* --- The Wave Transition Engine --- */
        .wave-container {
            position: absolute;
            inset: 0;
            display: flex;
            z-index: 5;
            pointer-events: none;
        }

        .wave-slat {
            flex: 1;
            height: 100%;
            background-color: var(--accent);
            transform: scaleY(0);
            transform-origin: bottom;
        }

        .wave-slat.animate-up {
            animation: waveUp var(--transition-speed) cubic-bezier(0.76, 0, 0.24, 1) forwards;
            animation-delay: calc(var(--i) * var(--wave-stagger));
        }

        .wave-slat.animate-down {
            animation: waveDown var(--transition-speed) cubic-bezier(0.76, 0, 0.24, 1) forwards;
            animation-delay: calc(var(--i) * var(--wave-stagger));
            transform-origin: top;
            transform: scaleY(1);
        }

        @keyframes waveUp {
            0% { transform: scaleY(0); }
            100% { transform: scaleY(1); }
        }

        @keyframes waveDown {
            0% { transform: scaleY(1); }
            100% { transform: scaleY(0); }
        }

        /* --- Backgrounds --- */
        .slide-bg {
            position: absolute;
            inset: 0;
            background-size: cover;
            background-position: center;
            filter: brightness(0.4) grayscale(0.5);
            transform: scale(1.1);
            transition: transform 1.5s cubic-bezier(0.16, 1, 0.3, 1);
        }

        .active .slide-bg {
            transform: scale(1);
        }

        /* --- Controls --- */
        .controls {
            position: absolute;
            bottom: 60px;
            right: 60px;
            display: flex;
            gap: 20px;
            z-index: 100;
        }

        .btn {
            background: none;
            border: 1px solid rgba(255,255,255,0.3);
            color: white;
            width: 60px;
            height: 60px;
            border-radius: 50%;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;
            position: relative;
            overflow: hidden;
        }

        .btn:hover {
            border-color: var(--accent);
            background: var(--accent);
        }

        .btn svg {
            width: 20px;
            height: 20px;
            fill: currentColor;
        }

        /* --- Custom Progress Indicator --- */
        .progress-wrap {
            position: absolute;
            bottom: 60px;
            left: 60px;
            z-index: 100;
            display: flex;
            align-items: center;
            gap: 20px;
        }

        .line-outer {
            width: 200px;
            height: 2px;
            background: rgba(255,255,255,0.1);
            position: relative;
        }

        .line-inner {
            position: absolute;
            left: 0;
            top: 0;
            height: 100%;
            width: 0%;
            background: var(--accent);
            transition: width 0.5s ease;
        }

    </style>
</head>
<body>

    <nav class="navbar">
        <div class="logo">Nazmul Hub</div>
        <ul class="nav-links">
            <li>Projects</li>
            <li>Studio</li>
            <li>Contact</li>
        </ul>
    </nav>

    <div class="app-container">
        <!-- The Wave Effect Layer -->
        <div id="wave-engine" class="wave-container"></div>

        <div class="slider" id="main-slider">
            <!-- Slide 1 -->
            <div class="slide active" data-index="0" data-color="#ff3e00">
                <div class="slide-bg" style="background-image: url('https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&q=80&w=2070');"></div>
                <div class="slide-content">
                    <span class="slide-number"><span>01 / 03</span></span>
                    <h1 class="slide-title"><span>Vertical<br>Horizon</span></h1>
                </div>
            </div>

            <!-- Slide 2 -->
            <div class="slide" data-index="1" data-color="#0066ff">
                <div class="slide-bg" style="background-image: url('https://images.unsplash.com/photo-1503387762-592dee58c460?auto=format&fit=crop&q=80&w=2070');"></div>
                <div class="slide-content">
                    <span class="slide-number"><span>02 / 03</span></span>
                    <h1 class="slide-title"><span>Brutalist<br>Echo</span></h1>
                </div>
            </div>

            <!-- Slide 3 -->
            <div class="slide" data-index="2" data-color="#00ff95">
                <div class="slide-bg" style="background-image: url('https://images.unsplash.com/photo-1494438639946-1ebd1d20bf85?auto=format&fit=crop&q=80&w=2067');"></div>
                <div class="slide-content">
                    <span class="slide-number"><span>03 / 03</span></span>
                    <h1 class="slide-title"><span>Nordic<br>Void</span></h1>
                </div>
            </div>
        </div>

        <div class="progress-wrap">
            <span id="current-idx">01</span>
            <div class="line-outer"><div class="line-inner" id="progress-bar"></div></div>
            <span>03</span>
        </div>

        <div class="controls">
            <button class="btn" id="prev-btn">
                <svg viewBox="0 0 24 24"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg>
            </button>
            <button class="btn" id="next-btn">
                <svg viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
            </button>
        </div>
    </div>

    <script>
        class WaveSlider {
            constructor() {
                this.slider = document.getElementById('main-slider');
                this.slides = document.querySelectorAll('.slide');
                this.waveEngine = document.getElementById('wave-engine');
                this.nextBtn = document.getElementById('next-btn');
                this.prevBtn = document.getElementById('prev-btn');
                this.progressBar = document.getElementById('progress-bar');
                this.currentIdxEl = document.getElementById('current-idx');
                
                this.currentIndex = 0;
                this.isAnimating = false;
                this.slatCount = 40; // Number of vertical wave elements

                this.init();
            }

            init() {
                // Create the wave slats
                for (let i = 0; i < this.slatCount; i++) {
                    const slat = document.createElement('div');
                    slat.classList.add('wave-slat');
                    slat.style.setProperty('--i', i);
                    this.waveEngine.appendChild(slat);
                }

                this.updateUI();

                this.nextBtn.addEventListener('click', () => this.changeSlide(1));
                this.prevBtn.addEventListener('click', () => this.changeSlide(-1));
                
                // Keyboard support
                window.addEventListener('keydown', (e) => {
                    if (e.key === 'ArrowRight') this.changeSlide(1);
                    if (e.key === 'ArrowLeft') this.changeSlide(-1);
                });
            }

            updateUI() {
                const progress = ((this.currentIndex + 1) / this.slides.length) * 100;
                this.progressBar.style.width = `${progress}%`;
                this.currentIdxEl.innerText = `0${this.currentIndex + 1}`;
                
                // Update accent color based on slide data
                const color = this.slides[this.currentIndex].dataset.color;
                document.documentElement.style.setProperty('--accent', color);
            }

            async changeSlide(direction) {
                if (this.isAnimating) return;
                this.isAnimating = true;

                const nextIndex = (this.currentIndex + direction + this.slides.length) % this.slides.length;
                const slats = document.querySelectorAll('.wave-slat');

                // Phase 1: Wave Covers Viewport
                slats.forEach(slat => {
                    slat.classList.remove('animate-down');
                    slat.classList.add('animate-up');
                    slat.style.transformOrigin = 'bottom';
                });

                // Wait for the middle of the wave to peak
                await new Promise(resolve => setTimeout(resolve, 800));

                // Phase 2: Switch Slide Content
                this.slides[this.currentIndex].classList.remove('active');
                this.currentIndex = nextIndex;
                this.slides[this.currentIndex].classList.add('active');
                this.updateUI();

                // Phase 3: Wave Recedes
                slats.forEach(slat => {
                    slat.classList.remove('animate-up');
                    slat.classList.add('animate-down');
                    slat.style.transformOrigin = 'top';
                });

                // Finalize
                setTimeout(() => {
                    this.isAnimating = false;
                }, 800 + (this.slatCount * 25)); // Buffer for stagger
            }
        }

        // Initialize production engine
        document.addEventListener('DOMContentLoaded', () => {
            new WaveSlider();
        });
    </script>
</body>
</html>

My Services

II offer complete digital solutions that help brands grow online —
from designing modern websites to creating powerful marketing campaigns. Every project is built with passion, creativity, and precision.