Galériák és képek
Lebegő képkártyák, mélységi hatással
Élő előnézet – a komponens teljes méretben.
Élő előnézet
HTML · CSS · JS
<section class="we-float-gallery" data-float-gallery>
<header class="we-float-gallery__header">
<span class="we-float-gallery__eyebrow">KÉPEK · TÖRTÉNETEK · ÉLMÉNYEK</span>
<h2>Más nézőpontból<span>.</span></h2>
<p>Minden táj egy új világ. Lépj közelebb, és fedezd fel!</p>
</header>
<div class="we-float-gallery__scene" data-float-scene>
<div class="we-float-gallery__glow"></div>
<div class="we-float-gallery__orbit we-float-gallery__orbit--one"></div>
<div class="we-float-gallery__orbit we-float-gallery__orbit--two"></div>
<button class="we-float-gallery__card we-float-gallery__card--one"
type="button"
data-float-photo
data-title="A hegyek nyugalma"
data-description="Ahol a csend messzebbre ér, mint a tekintet."
aria-label="A hegyek nyugalma – kép megnyitása">
<img src="https://images.unsplash.com/photo-1470770841072-f978cf4d019e?auto=format&fit=crop&w=1000&q=85"
alt="Hegyek és tó"
loading="lazy">
<span class="we-float-gallery__card-label">
<small>01 / TERMÉSZET</small>
<strong>A hegyek nyugalma</strong>
</span>
</button>
<button class="we-float-gallery__card we-float-gallery__card--two"
type="button"
data-float-photo
data-title="Zöld menedék"
data-description="Egy ösvény, amely elvezet a mindennapoktól."
aria-label="Zöld menedék – kép megnyitása">
<img src="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?auto=format&fit=crop&w=800&q=85"
alt="Napfényes erdő"
loading="lazy">
<span class="we-float-gallery__card-label">
<small>02 / ERDŐ</small>
<strong>Zöld menedék</strong>
</span>
</button>
<button class="we-float-gallery__card we-float-gallery__card--three"
type="button"
data-float-photo
data-title="Aranyóra"
data-description="Az a néhány perc, amikor a táj aranyba öltözik."
aria-label="Aranyóra – kép megnyitása">
<img src="https://images.unsplash.com/photo-1470252649378-9c29740c9fa8?auto=format&fit=crop&w=800&q=85"
alt="Aranyló fények a táj felett"
loading="lazy">
<span class="we-float-gallery__card-label">
<small>03 / FÉNYEK</small>
<strong>Aranyóra</strong>
</span>
</button>
<button class="we-float-gallery__card we-float-gallery__card--four"
type="button"
data-float-photo
data-title="A végtelen kék"
data-description="Hullámok, fények és a szabadság érzése."
aria-label="A végtelen kék – kép megnyitása">
<img src="https://images.unsplash.com/photo-1518837695005-2083093ee35b?auto=format&fit=crop&w=800&q=85"
alt="Tenger hullámai"
loading="lazy">
<span class="we-float-gallery__card-label">
<small>04 / TENGER</small>
<strong>A végtelen kék</strong>
</span>
</button>
<span class="we-float-gallery__index" aria-hidden="true">01 — 04</span>
<span class="we-float-gallery__hint">MOZDÍTSD AZ EGERET</span>
</div>
<footer class="we-float-gallery__footer">
<span>FELFEDEZÉSRE VÁRÓ VILÁGOK</span>
<span class="we-float-gallery__footer-line"></span>
<span>KATTINTS EGY KÉPRE</span>
</footer>
</section>
.we-float-gallery {
--float-bg: #101713;
--float-text: #f4f0e6;
--float-muted: #aab6aa;
--float-gold: #c9aa70;
position: relative;
width: 100%;
padding: clamp(32px, 5vw, 64px) 20px 30px;
overflow: hidden;
box-sizing: border-box;
color: var(--float-text);
background:
radial-gradient(ellipse at 50% 52%, #24382c 0%, transparent 55%),
var(--float-bg);
font-family: Georgia, "Times New Roman", serif;
}
.we-float-gallery *,
.we-float-gallery *::before,
.we-float-gallery *::after {
box-sizing: border-box;
}
.we-float-gallery__header {
position: relative;
z-index: 2;
max-width: 760px;
margin: 0 auto;
text-align: center;
}
.we-float-gallery__eyebrow {
color: var(--float-gold);
font-family: Arial, sans-serif;
font-size: 10px;
font-weight: 700;
letter-spacing: .24em;
}
.we-float-gallery__header h2 {
margin: 15px 0 12px;
font-size: clamp(32px, 5vw, 54px);
font-weight: 400;
line-height: 1.1;
letter-spacing: -.035em;
}
.we-float-gallery__header h2 span {
color: var(--float-gold);
}
.we-float-gallery__header p {
margin: 0;
color: var(--float-muted);
font-family: Arial, sans-serif;
font-size: 14px;
line-height: 1.7;
}
.we-float-gallery__scene {
position: relative;
width: 100%;
max-width: 1000px;
height: clamp(430px, 57vw, 620px);
margin: 10px auto 0;
perspective: 1200px;
transform-style: preserve-3d;
isolation: isolate;
}
.we-float-gallery__glow {
position: absolute;
top: 18%;
left: 25%;
width: 50%;
height: 65%;
border-radius: 50%;
background: rgb(150 174 125 / 12%);
filter: blur(65px);
pointer-events: none;
}
.we-float-gallery__orbit {
position: absolute;
top: 50%;
left: 50%;
border: 1px solid rgb(201 170 112 / 12%);
border-radius: 50%;
transform: translate(-50%, -50%) rotate(-18deg);
pointer-events: none;
}
.we-float-gallery__orbit--one {
width: 78%;
height: 66%;
}
.we-float-gallery__orbit--two {
width: 60%;
height: 86%;
transform: translate(-50%, -50%) rotate(24deg);
}
.we-float-gallery__card {
position: absolute;
display: block;
width: 34%;
height: 55%;
padding: 0;
overflow: hidden;
border: 1px solid rgb(255 255 255 / 20%);
border-radius: 3px;
background: #28362d;
color: #fff;
text-align: left;
cursor: pointer;
transform-style: preserve-3d;
box-shadow:
0 24px 60px rgb(0 0 0 / 30%),
0 2px 5px rgb(0 0 0 / 15%);
transition:
left 650ms cubic-bezier(.2, .7, .2, 1),
top 650ms cubic-bezier(.2, .7, .2, 1),
transform 650ms cubic-bezier(.2, .7, .2, 1),
box-shadow 350ms ease;
will-change: transform;
}
.we-float-gallery__card img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 800ms cubic-bezier(.2, .7, .2, 1);
}
.we-float-gallery__card::after {
position: absolute;
inset: 0;
content: "";
background: linear-gradient(
180deg,
transparent 40%,
rgb(8 15 10 / 80%) 100%
);
pointer-events: none;
}
.we-float-gallery__card:hover {
z-index: 10 !important;
box-shadow:
0 35px 80px rgb(0 0 0 / 48%),
0 0 0 1px rgb(201 170 112 / 65%);
}
.we-float-gallery__card:hover img {
transform: scale(1.07);
}
.we-float-gallery__card:focus-visible {
outline: 2px solid var(--float-gold);
outline-offset: 5px;
z-index: 11 !important;
}
.we-float-gallery__card-label {
position: absolute;
z-index: 2;
right: 15px;
bottom: 16px;
left: 15px;
display: flex;
flex-direction: column;
gap: 7px;
pointer-events: none;
}
.we-float-gallery__card-label small {
color: #e7cb93;
font-family: Arial, sans-serif;
font-size: 9px;
font-weight: 700;
letter-spacing: .17em;
}
.we-float-gallery__card-label strong {
font-size: clamp(15px, 1.8vw, 22px);
font-weight: 400;
line-height: 1.2;
}
.we-float-gallery__card--one {
top: 17%;
left: 14%;
z-index: 4;
transform: rotate(-8deg) translateZ(65px);
}
.we-float-gallery__card--two {
top: 9%;
left: 47%;
z-index: 3;
transform: rotate(7deg) translateZ(15px);
}
.we-float-gallery__card--three {
top: 40%;
left: 37%;
z-index: 5;
transform: rotate(-3deg) translateZ(105px);
}
.we-float-gallery__card--four {
top: 29%;
left: 63%;
z-index: 2;
transform: rotate(9deg) translateZ(-25px);
}
.we-float-gallery__index {
position: absolute;
right: 2%;
bottom: 8%;
color: rgb(201 170 112 / 60%);
font-family: Arial, sans-serif;
font-size: 12px;
letter-spacing: .18em;
}
.we-float-gallery__hint {
position: absolute;
bottom: 8%;
left: 2%;
color: var(--float-muted);
font-family: Arial, sans-serif;
font-size: 9px;
letter-spacing: .2em;
}
.we-float-gallery__footer {
display: flex;
align-items: center;
gap: 16px;
max-width: 1000px;
margin: 0 auto;
color: var(--float-muted);
font-family: Arial, sans-serif;
font-size: 9px;
letter-spacing: .12em;
}
.we-float-gallery__footer-line {
flex: 1;
height: 1px;
background: rgb(201 170 112 / 35%);
}
/* Nagyított képnézet */
.we-float-gallery__viewer {
position: fixed;
z-index: 99999;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 30px;
background: rgb(5 9 7 / 95%);
opacity: 0;
visibility: hidden;
pointer-events: none;
transition: opacity 250ms ease, visibility 250ms ease;
}
.we-float-gallery__viewer.is-open {
opacity: 1;
visibility: visible;
pointer-events: auto;
}
.we-float-gallery__viewer-inner {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: min(100%, 1100px);
height: 100%;
}
.we-float-gallery__viewer-image {
display: block;
max-width: 100%;
max-height: 82vh;
object-fit: contain;
box-shadow: 0 25px 80px rgb(0 0 0 / 40%);
}
.we-float-gallery__viewer-close,
.we-float-gallery__viewer-arrow {
position: absolute;
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
width: 46px;
height: 46px;
border: 1px solid rgb(255 255 255 / 30%);
border-radius: 50%;
background: rgb(15 22 17 / 65%);
color: #fff;
font-size: 25px;
cursor: pointer;
transition: background 180ms ease, color 180ms ease;
}
.we-float-gallery__viewer-close:hover,
.we-float-gallery__viewer-arrow:hover {
background: var(--float-gold);
color: #101713;
}
.we-float-gallery__viewer-close {
top: 20px;
right: 20px;
}
.we-float-gallery__viewer-arrow {
top: 50%;
transform: translateY(-50%);
}
.we-float-gallery__viewer-prev {
left: 12px;
}
.we-float-gallery__viewer-next {
right: 12px;
}
.we-float-gallery__viewer-info {
position: absolute;
right: 0;
bottom: 0;
left: 0;
display: flex;
justify-content: space-between;
gap: 15px;
padding: 18px 5px;
color: var(--float-muted);
font-family: Arial, sans-serif;
font-size: 12px;
}
.we-float-gallery__viewer-title {
color: var(--float-text);
font-family: Georgia, "Times New Roman", serif;
font-size: 22px;
}
@media (max-width: 650px) {
.we-float-gallery {
padding-right: 12px;
padding-left: 12px;
}
.we-float-gallery__scene {
height: 450px;
margin-top: 5px;
}
.we-float-gallery__card {
width: 43%;
height: 47%;
}
.we-float-gallery__card--one {
top: 12%;
left: 5%;
}
.we-float-gallery__card--two {
top: 8%;
left: 49%;
}
.we-float-gallery__card--three {
top: 42%;
left: 20%;
}
.we-float-gallery__card--four {
top: 37%;
left: 54%;
}
.we-float-gallery__card-label {
right: 9px;
bottom: 10px;
left: 9px;
gap: 5px;
}
.we-float-gallery__card-label small {
font-size: 8px;
}
.we-float-gallery__card-label strong {
font-size: 15px;
}
.we-float-gallery__hint {
bottom: 1%;
left: 3%;
font-size: 8px;
}
.we-float-gallery__index {
right: 3%;
bottom: 1%;
font-size: 10px;
}
.we-float-gallery__footer {
gap: 8px;
font-size: 8px;
}
.we-float-gallery__viewer {
padding: 12px;
}
.we-float-gallery__viewer-image {
max-height: 72vh;
}
.we-float-gallery__viewer-close {
top: 10px;
right: 10px;
}
.we-float-gallery__viewer-arrow {
top: auto;
bottom: 55px;
width: 40px;
height: 40px;
}
.we-float-gallery__viewer-prev {
left: 5px;
}
.we-float-gallery__viewer-next {
right: 5px;
}
}
@media (prefers-reduced-motion: reduce) {
.we-float-gallery__card,
.we-float-gallery__card img,
.we-float-gallery__viewer {
transition-duration: .01ms !important;
}
}
document.querySelectorAll("[data-float-gallery]").forEach((gallery) => {
if (gallery.dataset.floatInitialized === "true") {
return;
}
const scene = gallery.querySelector("[data-float-scene]");
const cards = Array.from(
gallery.querySelectorAll("[data-float-photo]")
);
if (!scene || cards.length === 0) {
console.warn("Lebegő galéria: hiányzó HTML-elemek.", gallery);
return;
}
gallery.dataset.floatInitialized = "true";
const reduceMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
).matches;
// Finom mélységi mozgás egérrel.
if (!reduceMotion) {
scene.addEventListener("pointermove", (event) => {
if (event.pointerType === "touch") {
return;
}
const rect = scene.getBoundingClientRect();
const x = (event.clientX - rect.left) / rect.width;
const y = (event.clientY - rect.top) / rect.height;
const rotateY = (x - 0.5) * 7;
const rotateX = (0.5 - y) * 5;
scene.style.transform =
`rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
});
scene.addEventListener("pointerleave", () => {
scene.style.transform = "rotateX(0deg) rotateY(0deg)";
});
cards.forEach((card, index) => {
card.addEventListener("pointermove", (event) => {
if (event.pointerType === "touch") {
return;
}
const rect = card.getBoundingClientRect();
const x = (event.clientX - rect.left) / rect.width;
const y = (event.clientY - rect.top) / rect.height;
const tiltY = (x - 0.5) * 5;
const tiltX = (0.5 - y) * 5;
card.style.setProperty("--float-tilt-x", `${tiltX}deg`);
card.style.setProperty("--float-tilt-y", `${tiltY}deg`);
});
card.addEventListener("pointerleave", () => {
card.style.removeProperty("--float-tilt-x");
card.style.removeProperty("--float-tilt-y");
});
});
}
// Képnézegető létrehozása.
const viewer = document.createElement("div");
viewer.className = "we-float-gallery__viewer";
viewer.setAttribute("role", "dialog");
viewer.setAttribute("aria-modal", "true");
viewer.setAttribute("aria-label", "Képnagyító");
viewer.innerHTML = `
<button type="button"
class="we-float-gallery__viewer-close"
aria-label="Bezárás">×</button>
<div class="we-float-gallery__viewer-inner">
<button type="button"
class="we-float-gallery__viewer-arrow we-float-gallery__viewer-prev"
aria-label="Előző kép">‹</button>
<img class="we-float-gallery__viewer-image" src="" alt="">
<button type="button"
class="we-float-gallery__viewer-arrow we-float-gallery__viewer-next"
aria-label="Következő kép">›</button>
<div class="we-float-gallery__viewer-info">
<span class="we-float-gallery__viewer-title"></span>
<span class="we-float-gallery__viewer-count"></span>
</div>
</div>
`;
document.body.appendChild(viewer);
const image = viewer.querySelector(
".we-float-gallery__viewer-image"
);
const title = viewer.querySelector(
".we-float-gallery__viewer-title"
);
const count = viewer.querySelector(
".we-float-gallery__viewer-count"
);
const closeButton = viewer.querySelector(
".we-float-gallery__viewer-close"
);
const prevButton = viewer.querySelector(
".we-float-gallery__viewer-prev"
);
const nextButton = viewer.querySelector(
".we-float-gallery__viewer-next"
);
let currentIndex = 0;
let previousFocus = null;
function showImage(index) {
currentIndex = (index + cards.length) % cards.length;
const card = cards[currentIndex];
const img = card.querySelector("img");
image.src = img.currentSrc || img.src;
image.alt = img.alt;
title.textContent = card.dataset.title || img.alt;
count.textContent =
String(currentIndex + 1).padStart(2, "0") +
" / " +
String(cards.length).padStart(2, "0");
}
function openViewer(index) {
previousFocus = document.activeElement;
showImage(index);
viewer.classList.add("is-open");
document.body.style.overflow = "hidden";
closeButton.focus();
}
function closeViewer() {
viewer.classList.remove("is-open");
document.body.style.overflow = "";
if (previousFocus && typeof previousFocus.focus === "function") {
previousFocus.focus();
}
}
cards.forEach((card, index) => {
card.addEventListener("click", () => openViewer(index));
});
closeButton.addEventListener("click", closeViewer);
prevButton.addEventListener("click", () => {
showImage(currentIndex - 1);
});
nextButton.addEventListener("click", () => {
showImage(currentIndex + 1);
});
viewer.addEventListener("click", (event) => {
if (event.target === viewer) {
closeViewer();
}
});
document.addEventListener("keydown", (event) => {
if (!viewer.classList.contains("is-open")) {
return;
}
if (event.key === "Escape") {
event.preventDefault();
closeViewer();
} else if (event.key === "ArrowLeft") {
event.preventDefault();
showImage(currentIndex - 1);
} else if (event.key === "ArrowRight") {
event.preventDefault();
showImage(currentIndex + 1);
}
});
});