Vissza a webes elemekhez
Galériák és képek

Panoráma – Felfedezés nagyban

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

Élő előnézet
HTML · CSS · JS
HTML
<section class="panorama-galeria" aria-label="Panoráma képgaléria">

    <div class="panorama-fejlec">
        <span class="panorama-kisfelirat">VILÁGUNK RÉSZLETEI</span>
        <h2>Fedezd fel a <em>pillanatot.</em></h2>
        <p>Három hely, három hangulat, végtelen történet.</p>
    </div>

    <div class="panorama-panelek">

        <article class="panorama-panel aktiv" tabindex="0">
            <img
                src="https://images.unsplash.com/photo-1470770841072-f978cf4d019e?auto=format&fit=crop&w=1200&q=85"
                alt="Hegyekkel körülvett tó"
                class="panorama-foto"
            >
            <div class="panorama-arnyek"></div>

            <div class="panorama-tartalom">
                <span class="panorama-szam">01 / 03</span>
                <h3>A csend birodalma</h3>
                <p>Ahol a hegyek és a víz összeérnek.</p>
                <button class="panorama-nagyitas" type="button">
                    Kép megtekintése <span aria-hidden="true">↗</span>
                </button>
            </div>
        </article>

        <article class="panorama-panel" tabindex="0">
            <img
                src="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?auto=format&fit=crop&w=1200&q=85"
                alt="Napfényes, zöld erdő"
                class="panorama-foto"
            >
            <div class="panorama-arnyek"></div>

            <div class="panorama-tartalom">
                <span class="panorama-szam">02 / 03</span>
                <h3>Az erdő titkai</h3>
                <p>Fények, árnyékok és rejtett ösvények.</p>
                <button class="panorama-nagyitas" type="button">
                    Kép megtekintése <span aria-hidden="true">↗</span>
                </button>
            </div>
        </article>

        <article class="panorama-panel" tabindex="0">
            <img
                src="https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?auto=format&fit=crop&w=1200&q=85"
                alt="Magas hegycsúcsok a felhők között"
                class="panorama-foto"
            >
            <div class="panorama-arnyek"></div>

            <div class="panorama-tartalom">
                <span class="panorama-szam">03 / 03</span>
                <h3>A magaslatok világa</h3>
                <p>Új perspektíva minden egyes lépéssel.</p>
                <button class="panorama-nagyitas" type="button">
                    Kép megtekintése <span aria-hidden="true">↗</span>
                </button>
            </div>
        </article>

    </div>

    <div class="panorama-lablec">
        <span>MOZDULJ · FEDEZZ FEL · LÁSS MÁSKÉPP</span>
        <span class="panorama-jel">✳</span>
    </div>

    <div class="panorama-lightbox" aria-hidden="true">
        <button class="panorama-bezar" type="button"
                aria-label="Nagyított kép bezárása">×</button>
        <img src="" alt="" class="panorama-lightbox-kep">
        <p class="panorama-lightbox-cim"></p>
    </div>

</section>
CSS
.panorama-galeria {
    --panorama-arany: #d8bc83;
    --panorama-hatter: #101713;
    --panorama-feher: #f8f6ef;

    position: relative;
    isolation: isolate;
    box-sizing: border-box;
    width: 100%;
    padding: 70px 5%;
    overflow: hidden;
    background: var(--panorama-hatter);
    color: var(--panorama-feher);
    font-family: Arial, sans-serif;
}

.panorama-galeria *,
.panorama-galeria *::before,
.panorama-galeria *::after {
    box-sizing: border-box;
}

/* FEJLÉC */

.panorama-fejlec {
    max-width: 760px;
    margin: 0 auto 42px;
    text-align: center;
}

.panorama-kisfelirat {
    display: block;
    margin-bottom: 18px;
    color: var(--panorama-arany);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 4px;
}

.panorama-fejlec h2 {
    margin: 0 0 16px;
    color: var(--panorama-feher);
    font-family: Georgia, "Times New Roman", serif;
    font-size: clamp(32px, 4.5vw, 58px);
    font-weight: 400;
    line-height: 1.15;
}

.panorama-fejlec h2 em {
    color: var(--panorama-arany);
    font-weight: 400;
}

.panorama-fejlec > p {
    margin: 0;
    color: rgba(248, 246, 239, 0.65);
    font-size: 14px;
    line-height: 1.8;
}

/* KÉPPANELEK */

.panorama-panelek {
    display: flex;
    align-items: stretch;
    gap: 12px;
    width: 100%;
    min-height: 440px;
}

.panorama-panel {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    min-height: 440px;
    overflow: hidden;
    outline: none;
    background: #27332b;
    cursor: pointer;
    transition: flex 0.65s cubic-bezier(.2, .75, .25, 1);
}

.panorama-panel.aktiv,
.panorama-panel:hover,
.panorama-panel:focus-visible {
    flex: 2.4 1 0;
}

.panorama-panel:focus-visible {
    outline: 2px solid var(--panorama-arany);
    outline-offset: -4px;
}

/* FOTÓK */

.panorama-foto {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    transform: scale(1.04);
    transition: transform 0.9s ease;
}

.panorama-panel:hover .panorama-foto,
.panorama-panel.aktiv .panorama-foto {
    transform: scale(1);
}

.panorama-arnyek {
    position: absolute;
    inset: 0;
    background:
        linear-gradient(
            180deg,
            rgba(8, 13, 10, 0.02) 20%,
            rgba(8, 13, 10, 0.3) 50%,
            rgba(8, 13, 10, 0.9) 100%
        );
    transition: background 0.5s ease;
}

/* PANEL SZÖVEGE */

.panorama-tartalom {
    position: absolute;
    right: 24px;
    bottom: 28px;
    left: 24px;
    z-index: 2;
}

.panorama-szam {
    display: block;
    margin-bottom: 14px;
    color: var(--panorama-arany);
    font-size: 11px;
    letter-spacing: 2px;
}

.panorama-tartalom h3 {
    margin: 0;
    color: #fff;
    font-family: Georgia, "Times New Roman", serif;
    font-size: clamp(20px, 2.2vw, 29px);
    font-weight: 400;
    line-height: 1.25;
    text-wrap: balance;
}

.panorama-tartalom > p {
    max-width: 300px;
    max-height: 0;
    margin: 0;
    overflow: hidden;
    color: rgba(255, 255, 255, 0.8);
    font-size: 13px;
    line-height: 1.7;
    opacity: 0;
    transition:
        max-height 0.4s ease,
        margin 0.4s ease,
        opacity 0.4s ease;
}

.panorama-panel.aktiv .panorama-tartalom > p,
.panorama-panel:hover .panorama-tartalom > p,
.panorama-panel:focus-visible .panorama-tartalom > p {
    max-height: 90px;
    margin-top: 12px;
    opacity: 1;
}

/* NAGYÍTÁS GOMB */

.panorama-nagyitas {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    max-width: 100%;
    margin-top: 17px;
    padding: 10px 0;
    border: 0;
    border-bottom: 1px solid var(--panorama-arany);
    background: transparent;
    color: #fff;
    font: inherit;
    font-size: 12px;
    letter-spacing: 0.5px;
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transition:
        opacity 0.35s ease,
        color 0.3s ease;
}

.panorama-nagyitas span {
    color: var(--panorama-arany);
    font-size: 17px;
}

.panorama-panel.aktiv .panorama-nagyitas,
.panorama-panel:hover .panorama-nagyitas,
.panorama-panel:focus-within .panorama-nagyitas {
    opacity: 1;
    pointer-events: auto;
}

.panorama-nagyitas:hover {
    color: var(--panorama-arany);
}

/* ALSÓ DÍSZÍTÉS */

.panorama-lablec {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    margin-top: 26px;
    color: rgba(248, 246, 239, 0.48);
    font-size: 10px;
    letter-spacing: 2px;
}

.panorama-jel {
    color: var(--panorama-arany);
    font-size: 23px;
}

/* TELJES KÉPERNYŐS NAGYÍTÁS */

.panorama-lightbox {
    position: fixed;
    inset: 0;
    z-index: 99999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 18px;
    padding: 55px 24px 30px;
    background: rgba(5, 8, 6, 0.96);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.3s ease, visibility 0.3s ease;
}

.panorama-lightbox.nyitva {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

.panorama-lightbox-kep {
    display: block;
    max-width: 100%;
    max-height: 78vh;
    object-fit: contain;
}

.panorama-lightbox-cim {
    margin: 0;
    color: var(--panorama-feher);
    font-family: Georgia, "Times New Roman", serif;
    font-size: 19px;
    text-align: center;
}

.panorama-bezar {
    position: absolute;
    top: 12px;
    right: 22px;
    display: grid;
    width: 44px;
    height: 44px;
    place-items: center;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    background: transparent;
    color: #fff;
    font-size: 32px;
    line-height: 1;
    cursor: pointer;
}

.panorama-bezar:hover {
    border-color: var(--panorama-arany);
    color: var(--panorama-arany);
}

/* TABLET */

@media (max-width: 850px) {
    .panorama-galeria {
        padding: 55px 4%;
    }

    .panorama-panelek {
        min-height: 390px;
        gap: 8px;
    }

    .panorama-panel {
        min-height: 390px;
    }

    .panorama-panel.aktiv,
    .panorama-panel:hover,
    .panorama-panel:focus-visible {
        flex: 2 1 0;
    }

    .panorama-tartalom {
        right: 15px;
        bottom: 22px;
        left: 15px;
    }

    .panorama-tartalom h3 {
        font-size: 22px;
    }
}

/* MOBIL */

@media (max-width: 600px) {
    .panorama-galeria {
        padding: 42px 18px;
    }

    .panorama-fejlec {
        margin-bottom: 28px;
    }

    .panorama-kisfelirat {
        font-size: 9px;
        letter-spacing: 3px;
    }

    .panorama-fejlec > p {
        font-size: 13px;
    }

    .panorama-panelek {
        flex-direction: column;
        gap: 10px;
        min-height: 0;
    }

    .panorama-panel,
    .panorama-panel.aktiv,
    .panorama-panel:hover,
    .panorama-panel:focus-visible {
        flex: none;
        width: 100%;
        min-height: 105px;
        height: 105px;
        transition: height 0.45s ease;
    }

    .panorama-panel.aktiv {
        height: 310px;
    }

    .panorama-panel.aktiv .panorama-tartalom > p {
        max-height: 90px;
        margin-top: 12px;
        opacity: 1;
    }

    .panorama-panel.aktiv .panorama-nagyitas {
        opacity: 1;
        pointer-events: auto;
    }

    .panorama-tartalom {
        right: 20px;
        bottom: 20px;
        left: 20px;
    }

    .panorama-tartalom h3 {
        font-size: 23px;
    }

    .panorama-panel:not(.aktiv) .panorama-tartalom > p,
    .panorama-panel:not(.aktiv) .panorama-nagyitas {
        display: none;
    }

    .panorama-lablec {
        font-size: 8px;
        letter-spacing: 1.3px;
    }

    .panorama-lightbox {
        padding: 60px 14px 25px;
    }

    .panorama-lightbox-kep {
        max-height: 75vh;
    }
}

/* MOZGÁSCSÖKKENTÉS */

@media (prefers-reduced-motion: reduce) {
    .panorama-galeria *,
    .panorama-galeria *::before,
    .panorama-galeria *::after {
        scroll-behavior: auto !important;
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}
JavaScript
document.querySelectorAll(".panorama-galeria").forEach((galeria) => {
    const panelek = [...galeria.querySelectorAll(".panorama-panel")];
    const lightbox = galeria.querySelector(".panorama-lightbox");
    const nagyKep = galeria.querySelector(".panorama-lightbox-kep");
    const kepCim = galeria.querySelector(".panorama-lightbox-cim");
    const bezarGomb = galeria.querySelector(".panorama-bezar");

    if (!panelek.length || !lightbox || !nagyKep || !bezarGomb) {
        return;
    }

    let elozoFokusz = null;

    function panelAktivalasa(panel) {
        panelek.forEach((elem) => {
            const aktiv = elem === panel;
            elem.classList.toggle("aktiv", aktiv);
            elem.setAttribute("aria-current", aktiv ? "true" : "false");
        });
    }

    function nagyitasMegnyitasa(panel) {
        const kep = panel.querySelector(".panorama-foto");
        const cim = panel.querySelector("h3");

        if (!kep) return;

        elozoFokusz = document.activeElement;

        nagyKep.src = kep.currentSrc || kep.src;
        nagyKep.alt = kep.alt || "";
        kepCim.textContent = cim ? cim.textContent : "";

        lightbox.classList.add("nyitva");
        lightbox.setAttribute("aria-hidden", "false");
        document.body.style.overflow = "hidden";

        bezarGomb.focus();
    }

    function nagyitasBezarasa() {
        lightbox.classList.remove("nyitva");
        lightbox.setAttribute("aria-hidden", "true");
        document.body.style.overflow = "";

        nagyKep.removeAttribute("src");
        nagyKep.alt = "";

        if (elozoFokusz && typeof elozoFokusz.focus === "function") {
            elozoFokusz.focus();
        }
    }

    panelek.forEach((panel) => {
        panel.addEventListener("click", (esemeny) => {
            const nagyitasGomb = esemeny.target.closest(
                ".panorama-nagyitas"
            );

            if (nagyitasGomb) {
                esemeny.stopPropagation();
                nagyitasMegnyitasa(panel);
                return;
            }

            panelAktivalasa(panel);
        });

        panel.addEventListener("keydown", (esemeny) => {
            if (
                esemeny.target !== panel ||
                (esemeny.key !== "Enter" && esemeny.key !== " ")
            ) {
                return;
            }

            esemeny.preventDefault();
            panelAktivalasa(panel);
        });
    });

    bezarGomb.addEventListener("click", nagyitasBezarasa);

    lightbox.addEventListener("click", (esemeny) => {
        if (esemeny.target === lightbox) {
            nagyitasBezarasa();
        }
    });

    document.addEventListener("keydown", (esemeny) => {
        if (!lightbox.classList.contains("nyitva")) return;

        if (esemeny.key === "Escape") {
            nagyitasBezarasa();
        }
    });

    // Asztali gépen az egérrel is váltható a kiemelt panel.
    panelek.forEach((panel) => {
        panel.addEventListener("mouseenter", () => {
            if (window.matchMedia("(hover: hover)").matches) {
                panelAktivalasa(panel);
            }
        });
    });
});