Vissza a webes elemekhez
Fejlécek

Tipográfiai hullám

Élő előnézet – a komponens teljes méretben.

Élő előnézet
HTML · CSS · JS
HTML
<section class="hero-typewave">

    <div class="typewave-light"></div>
    <div class="typewave-light typewave-light-two"></div>

    <div class="typewave-grid"></div>

    <div class="typewave-content">

        <div class="typewave-kicker">
            <span></span>
            <em class="typewave-typing"></em>
            <i></i>
            <span></span>
        </div>

        <h1 class="typewave-title">
            <span class="type-line">Alakítsd</span>
            <span class="type-line type-line-accent">át.</span>
            <span class="type-line">A világod.</span>
        </h1>

        <p class="typewave-description">
            Merész ötletek. Erős vizuális világ.
            Digitális élmények, amelyekre emlékeznek.
        </p>

        <a href="#" class="typewave-button">
            Felfedezem
            <span>→</span>
        </a>

    </div>

    <div class="typewave-wave">
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>

    <div class="typewave-meta">
        <span>CREATIVE DIRECTION</span>
        <span>06 / 2026</span>
    </div>

</section>
CSS
.hero-typewave {
    position: relative;
    width: 100%;
    min-height: 760px;
    overflow: hidden;
    isolation: isolate;

    display: flex;
    align-items: center;
    justify-content: center;

    background:
        radial-gradient(
            circle at 50% 50%,
            rgba(99, 111, 101, .18),
            transparent 35%
        ),
        #111412;

    color: #f3f0e8;

    font-family: Arial, sans-serif;
}


/* =========================
   HÁTTÉRFÉNYEK
========================= */

.typewave-light {
    position: absolute;

    width: 600px;
    height: 600px;

    left: 50%;
    top: 50%;

    transform: translate(-50%, -50%);

    border-radius: 50%;

    background:
        radial-gradient(
            circle,
            rgba(201, 181, 139, .13),
            rgba(201, 181, 139, .04) 30%,
            transparent 70%
        );

    filter: blur(25px);

    animation: typewaveGlow 8s ease-in-out infinite;

    z-index: -3;
}


.typewave-light-two {
    width: 400px;
    height: 400px;

    left: 75%;
    top: 25%;

    background:
        radial-gradient(
            circle,
            rgba(110, 137, 124, .15),
            transparent 70%
        );

    animation-duration: 11s;
    animation-delay: -3s;
}


/* =========================
   FINOM RÁCS
========================= */

.typewave-grid {
    position: absolute;
    inset: 0;

    opacity: .14;

    background-image:
        linear-gradient(
            rgba(255,255,255,.035) 1px,
            transparent 1px
        ),
        linear-gradient(
            90deg,
            rgba(255,255,255,.035) 1px,
            transparent 1px
        );

    background-size: 80px 80px;

    mask-image:
        radial-gradient(
            ellipse at center,
            black 20%,
            transparent 75%
        );

    z-index: -2;
}


/* =========================
   TARTALOM
========================= */

.typewave-content {
    position: relative;

    width: min(1000px, 90%);

    text-align: center;

    z-index: 5;
}


/* =========================
   KICKER
========================= */

.typewave-kicker {
    display: flex;

    align-items: center;
    justify-content: center;

    gap: 12px;

    margin-bottom: 30px;

    color: #b9aa8d;

    font-size: 10px;

    letter-spacing: 5px;

    text-transform: uppercase;

    opacity: 0;

    animation:
        typewaveFade .8s ease .2s forwards;
}


.typewave-kicker span {
    width: 35px;
    height: 1px;

    background: rgba(200,180,140,.45);
}


.typewave-kicker i {
    width: 4px;
    height: 4px;

    border-radius: 50%;

    background: #d3ba89;

    box-shadow:
        0 0 12px rgba(211,186,137,.8);
}


.typewave-kicker em {
    min-width: 160px;

    font-style: normal;
}


/* =========================
   FŐCÍM
========================= */

.typewave-title {
    margin: 0;

    font-family:
        Georgia,
        "Times New Roman",
        serif;

    font-size:
        clamp(65px, 10vw, 145px);

    line-height: .83;

    font-weight: 400;

    letter-spacing: -7px;

    text-transform: none;
}


.type-line {
    display: block;

    overflow: hidden;

    opacity: 0;

    transform:
        translateY(110%);

    animation:
        typeLineIn
        1s
        cubic-bezier(.16,1,.3,1)
        forwards;
}


.type-line:nth-child(1) {
    animation-delay: .35s;
}


.type-line:nth-child(2) {
    animation-delay: .55s;
}


.type-line:nth-child(3) {
    animation-delay: .75s;
}


.type-line-accent {
    color: #d3ba89;

    font-style: italic;

    padding-right: 20px;

    position: relative;
}


/* =========================
   FÉNYCSÍK A CÍMEN
========================= */

.type-line-accent::after {
    content: "";

    position: absolute;

    left: -20%;
    top: 50%;

    width: 140%;
    height: 2px;

    background:
        linear-gradient(
            90deg,
            transparent,
            rgba(255,255,255,.9),
            #d3ba89,
            transparent
        );

    box-shadow:
        0 0 18px rgba(211,186,137,.7);

    transform:
        translateX(-100%)
        rotate(-4deg);

    opacity: 0;

    animation:
        titleSweep
        1.3s
        ease
        1.15s
        forwards;
}


/* =========================
   LEÍRÁS
========================= */

.typewave-description {
    max-width: 520px;

    margin:
        42px auto
        0;

    color: #9c9f9b;

    font-size: 14px;

    line-height: 1.9;

    opacity: 0;

    transform: translateY(20px);

    animation:
        typewaveFadeUp
        .9s
        ease
        1.25s
        forwards;
}


/* =========================
   GOMB
========================= */

.typewave-button {
    display: inline-flex;

    align-items: center;

    gap: 25px;

    margin-top: 32px;

    padding:
        15px
        22px;

    border:
        1px solid
        rgba(211,186,137,.45);

    color: #eee9df;

    text-decoration: none;

    text-transform: uppercase;

    letter-spacing: 3px;

    font-size: 10px;

    opacity: 0;

    animation:
        typewaveFadeUp
        .8s
        ease
        1.5s
        forwards;

    transition:
        background .35s ease,
        border-color .35s ease,
        transform .35s ease,
        box-shadow .35s ease;
}


.typewave-button span {
    font-size: 18px;

    transition:
        transform .35s ease;
}


.typewave-button:hover {
    background:
        rgba(211,186,137,.09);

    border-color:
        rgba(211,186,137,.85);

    transform:
        translateY(-4px);

    box-shadow:
        0 15px 45px rgba(0,0,0,.3);
}


.typewave-button:hover span {
    transform:
        translateX(6px);
}


/* =========================
   HULLÁM
========================= */

.typewave-wave {
    position: absolute;

    left: -5%;
    right: -5%;
    bottom: -180px;

    height: 300px;

    display: flex;

    align-items: center;

    justify-content: center;

    gap: 8px;

    opacity: .3;

    transform:
        rotate(-3deg);

    z-index: 1;
}


.typewave-wave span {
    display: block;

    width: 2px;

    height: 80px;

    background:
        linear-gradient(
            to bottom,
            transparent,
            #d0b47f,
            transparent
        );

    box-shadow:
        0 0 12px rgba(208,180,127,.4);

    animation:
        waveMove
        2.8s
        ease-in-out
        infinite;
}


.typewave-wave span:nth-child(1) {
    height: 50px;
    animation-delay: -.2s;
}


.typewave-wave span:nth-child(2) {
    height: 90px;
    animation-delay: -.4s;
}


.typewave-wave span:nth-child(3) {
    height: 140px;
    animation-delay: -.6s;
}


.typewave-wave span:nth-child(4) {
    height: 180px;
    animation-delay: -.8s;
}


.typewave-wave span:nth-child(5) {
    height: 140px;
    animation-delay: -1s;
}


.typewave-wave span:nth-child(6) {
    height: 90px;
    animation-delay: -1.2s;
}


.typewave-wave span:nth-child(7) {
    height: 50px;
    animation-delay: -1.4s;
}


/* =========================
   ALSÓ META
========================= */

.typewave-meta {
    position: absolute;

    left: 30px;
    right: 30px;
    bottom: 25px;

    display: flex;

    justify-content: space-between;

    color: #5e625e;

    font-size: 8px;

    letter-spacing: 3px;

    z-index: 5;
}


/* =========================
   ANIMÁCIÓK
========================= */

@keyframes typeLineIn {

    0% {
        opacity: 0;
        transform:
            translateY(110%);
        filter: blur(8px);
    }

    100% {
        opacity: 1;
        transform:
            translateY(0);
        filter: blur(0);
    }

}


@keyframes titleSweep {

    0% {
        opacity: 0;
        transform:
            translateX(-100%)
            rotate(-4deg);
    }

    15% {
        opacity: 1;
    }

    100% {
        opacity: 0;
        transform:
            translateX(100%)
            rotate(-4deg);
    }

}


@keyframes typewaveGlow {

    0%, 100% {
        transform:
            translate(-50%, -50%)
            scale(.9);
        opacity: .6;
    }

    50% {
        transform:
            translate(-50%, -50%)
            scale(1.15);
        opacity: 1;
    }

}


@keyframes typewaveFade {

    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }

}


@keyframes typewaveFadeUp {

    from {
        opacity: 0;
        transform:
            translateY(20px);
    }

    to {
        opacity: 1;
        transform:
            translateY(0);
    }

}


@keyframes waveMove {

    0%, 100% {
        transform:
            scaleY(.55);
    }

    50% {
        transform:
            scaleY(1.45);
    }

}


/* =========================
   TABLET
========================= */

@media (max-width: 800px) {

    .hero-typewave {
        min-height: 700px;
    }

    .typewave-title {
        font-size:
            clamp(55px, 11vw, 100px);

        letter-spacing: -4px;
    }

}


/* =========================
   MOBIL
========================= */

@media (max-width: 600px) {

    .hero-typewave {
        min-height: 650px;
    }

    .typewave-title {
        font-size:
            clamp(48px, 15vw, 75px);

        letter-spacing: -3px;
    }

    .typewave-description {
        max-width: 320px;

        font-size: 13px;

        margin-top: 32px;
    }

    .typewave-kicker {
        letter-spacing: 3px;
    }

    .typewave-kicker span {
        width: 20px;
    }

    .typewave-meta {
        left: 15px;
        right: 15px;
    }

    .typewave-wave {
        bottom: -130px;
    }

}


@media (prefers-reduced-motion: reduce) {

    .typewave-light,
    .typewave-light-two,
    .type-line,
    .type-line-accent::after,
    .typewave-description,
    .typewave-button,
    .typewave-wave span {
        animation: none !important;
    }

    .type-line,
    .typewave-description,
    .typewave-button,
    .typewave-kicker {
        opacity: 1;
        transform: none;
    }

}
JavaScript
document.addEventListener("DOMContentLoaded", () => {

    const hero =
        document.querySelector(".hero-typewave");

    if (!hero) return;


    /* =========================
       GÉPELŐS SZÖVEG
    ========================= */

    const typing =
        hero.querySelector(".typewave-typing");

    const words = [
        "Creative thinking",
        "Bold ideas",
        "Digital stories",
        "New possibilities"
    ];

    let wordIndex = 0;
    let charIndex = 0;
    let deleting = false;


    function typingLoop() {

        if (!typing) return;

        const word =
            words[wordIndex];


        if (!deleting) {

            charIndex++;

            typing.textContent =
                word.substring(
                    0,
                    charIndex
                );


            if (
                charIndex >=
                word.length
            ) {

                deleting = true;

                setTimeout(
                    typingLoop,
                    1700
                );

                return;
            }


            setTimeout(
                typingLoop,
                75
            );

        } else {

            charIndex--;

            typing.textContent =
                word.substring(
                    0,
                    charIndex
                );


            if (charIndex <= 0) {

                deleting = false;

                wordIndex =
                    (wordIndex + 1)
                    % words.length;

                setTimeout(
                    typingLoop,
                    450
                );

                return;
            }


            setTimeout(
                typingLoop,
                38
            );
        }

    }


    setTimeout(
        typingLoop,
        800
    );


    /* =========================
       EGÉRREAGÁLÁS
    ========================= */

    if (
        window.matchMedia(
            "(pointer: fine)"
        ).matches &&
        !window.matchMedia(
            "(prefers-reduced-motion: reduce)"
        ).matches
    ) {

        const content =
            hero.querySelector(
                ".typewave-content"
            );

        const light =
            hero.querySelector(
                ".typewave-light"
            );

        hero.addEventListener(
            "mousemove",
            (event) => {

                const rect =
                    hero.getBoundingClientRect();

                const x =
                    (
                        event.clientX -
                        rect.left
                    ) /
                    rect.width -
                    .5;

                const y =
                    (
                        event.clientY -
                        rect.top
                    ) /
                    rect.height -
                    .5;


                if (content) {

                    content.style.transform =
                        `translate(${x * 8}px, ${y * 6}px)`;
                }


                if (light) {

                    light.style.marginLeft =
                        `${x * 35}px`;

                    light.style.marginTop =
                        `${y * 30}px`;
                }

            }
        );


        hero.addEventListener(
            "mouseleave",
            () => {

                if (content) {
                    content.style.transform = "";
                }

                if (light) {
                    light.style.marginLeft = "";
                    light.style.marginTop = "";
                }

            }
        );

    }

});