WEBLEB
Accueil
Éditeur
Connexion
Pro
Français
English
Français
Español
Português
Deutsch
Italiano
हिंदी
HTML
CSS
JS
*, *::after, *::before { margin: 0; padding: 0; box-sizing: border-box; } :root { --active-color: hsl(204 100 53); --bg-color: #e1e3e5; --icon-default: hsl(203 5 75); --icon-accent: hsl(203 15 98); --navigation-color: hsl(203 5 25 / 0.3); } body { min-block-size: 100vh; display: flex; justify-content: center; align-items: center; background-color: var(--bg-color); } .image-slider { display: flex; flex-flow: column; width: clamp(360px, 96vw, 830px); aspect-ratio: 16 / 9; min-height: 300px; overflow: hidden; border-radius: 8px; container-type: inline-size; contain: content; background-color: #0006; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 2px, rgba(0, 0, 0, 0.3) 0px 2px 4px, rgba(0, 0, 0, 0.25) 0px 4px 8px, rgba(0, 0, 0, 0.2) 0px 8px 16px, rgba(0, 0, 0, 0.15) 0px 16px 32px; } .slider__content { flex-grow: 1; display: flex; justify-content: space-between; } .slider-control--button { border: 0; background: 0; outline: 0; cursor: pointer; place-content: center; padding-inline: 3vw; z-index: 1; display: grid; } .icon { height: 2rem; width: 2rem; fill: var(--icon-default); border-radius: 50%; } .slider-control--button:where(:hover) { background-image: linear-gradient( to var(--position), #0000 0%, #0002, 80%, #0006 100% ); .icon { fill: var(--icon-accent); background: #0001; } } .slider-control--button:active { outline: 0.2em solid hsl(204 100 53); outline-offset: -0.5em; } .prev-button { --position: left; } .next-button { --position: right; } .image-display { position: fixed; inset: 0; } .slider-navigation { z-index: 10; display: grid; grid-auto-flow: column; grid-template-columns: repeat(6, 1fr); grid-auto-columns: 100%; gap: 1.25rem; padding: 1rem; place-content: center; background-color: var(--navigation-color); backdrop-filter: blur(6px); } .nav-button { display: grid; width: 100%; height: 100%; border-radius: 0.5em; overflow: hidden; align-items: center; justify-content: center; border: 0; aspect-ratio: 16 / 9; transition: filter 150ms linear, scale 266ms ease; } .thumbnail { display: block; max-width: 100%; width: 100%; object-fit: cover; height: 100%; } .nav-button[aria-selected="true"] { scale: 1.1; } .nav-button[aria-selected="true"], .nav-button:focus-visible { outline: 0.2em solid var(--active-color); outline-offset: 0.2em; } .nav-button[aria-selected="false"] { filter: opacity(0.7); } .nav-button[aria-selected="false"]:where(:hover, :focus-visible) { filter: opacity(1); } @container (max-width: 660px) { .nav-button:not(:has(img)) { background-color: rgb(241, 235, 232); } .slider-navigation { display: flex; justify-content: center; padding-block: 1.5em; } .nav-button { inline-size: 0.625rem; aspect-ratio: 1; border-radius: 50%; } .nav-button > .thumbnail { display: none; } .nav-button[aria-selected="true"] { background-color: black; scale: 1.5; } }
class Slider { constructor(slider) { this.slider = slider; this.display = slider.querySelector(".image-display"); this.navButtons = Array.from(slider.querySelectorAll(".nav-button")); this.prevButton = slider.querySelector(".prev-button"); this.nextButton = slider.querySelector(".next-button"); this.sliderNavigation = slider.querySelector(".slider-navigation"); this.currentSlideIndex = 0; this.preloadedImages = {}; this.initialize(); } initialize() { this.setupSlider(); this.preloadImages(); this.eventListeners(); } setupSlider() { this.showSlide(this.currentSlideIndex); } showSlide(index) { this.currentSlideIndex = index; const navButtonImg = this.navButtons[ this.currentSlideIndex ].querySelector("img"); if (navButtonImg) { const imgClone = navButtonImg.cloneNode(); this.display.replaceChildren(imgClone); } this.updateNavButtons(); } updateNavButtons() { this.navButtons.forEach((button, buttonIndex) => { const isSelected = buttonIndex === this.currentSlideIndex; button.setAttribute("aria-selected", isSelected); if (isSelected) button.focus(); }); } preloadImages() { this.navButtons.forEach((button) => { const imgElement = button.querySelector("img"); if (imgElement) { const imgSrc = imgElement.src; if (!this.preloadedImages[imgSrc]) { this.preloadedImages[imgSrc] = new Image(); this.preloadedImages[imgSrc].src = imgSrc; } } }); } eventListeners() { document.addEventListener("keydown", (event) => { this.handleAction(event.key); }); this.sliderNavigation.addEventListener("click", (event) => { const targetButton = event.target.closest(".nav-button"); const index = targetButton ? this.navButtons.indexOf(targetButton) : -1; if (index !== -1) { this.showSlide(index); } }); this.prevButton.addEventListener("click", () => this.handleAction("prev") ); this.nextButton.addEventListener("click", () => this.handleAction("next") ); } handleAction(action) { if (action === "Home") { this.currentSlideIndex = 0; } else if (action === "End") { this.currentSlideIndex = this.navButtons.length - 1; } else if (action === "ArrowRight" || action === "next") { this.currentSlideIndex = (this.currentSlideIndex + 1) % this.navButtons.length; } else if (action === "ArrowLeft" || action === "prev") { this.currentSlideIndex = (this.currentSlideIndex - 1 + this.navButtons.length) % this.navButtons.length; } this.showSlide(this.currentSlideIndex); } } const ImageSlider = new Slider(document.querySelector(".image-slider"));
Validating your code, please wait...
HTML
CSS
JS
*, *::after, *::before { margin: 0; padding: 0; box-sizing: border-box; } :root { --active-color: hsl(204 100 53); --bg-color: #e1e3e5; --icon-default: hsl(203 5 75); --icon-accent: hsl(203 15 98); --navigation-color: hsl(203 5 25 / 0.3); } body { min-block-size: 100vh; display: flex; justify-content: center; align-items: center; background-color: var(--bg-color); } .image-slider { display: flex; flex-flow: column; width: clamp(360px, 96vw, 830px); aspect-ratio: 16 / 9; min-height: 300px; overflow: hidden; border-radius: 8px; container-type: inline-size; contain: content; background-color: #0006; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 2px, rgba(0, 0, 0, 0.3) 0px 2px 4px, rgba(0, 0, 0, 0.25) 0px 4px 8px, rgba(0, 0, 0, 0.2) 0px 8px 16px, rgba(0, 0, 0, 0.15) 0px 16px 32px; } .slider__content { flex-grow: 1; display: flex; justify-content: space-between; } .slider-control--button { border: 0; background: 0; outline: 0; cursor: pointer; place-content: center; padding-inline: 3vw; z-index: 1; display: grid; } .icon { height: 2rem; width: 2rem; fill: var(--icon-default); border-radius: 50%; } .slider-control--button:where(:hover) { background-image: linear-gradient( to var(--position), #0000 0%, #0002, 80%, #0006 100% ); .icon { fill: var(--icon-accent); background: #0001; } } .slider-control--button:active { outline: 0.2em solid hsl(204 100 53); outline-offset: -0.5em; } .prev-button { --position: left; } .next-button { --position: right; } .image-display { position: fixed; inset: 0; } .slider-navigation { z-index: 10; display: grid; grid-auto-flow: column; grid-template-columns: repeat(6, 1fr); grid-auto-columns: 100%; gap: 1.25rem; padding: 1rem; place-content: center; background-color: var(--navigation-color); backdrop-filter: blur(6px); } .nav-button { display: grid; width: 100%; height: 100%; border-radius: 0.5em; overflow: hidden; align-items: center; justify-content: center; border: 0; aspect-ratio: 16 / 9; transition: filter 150ms linear, scale 266ms ease; } .thumbnail { display: block; max-width: 100%; width: 100%; object-fit: cover; height: 100%; } .nav-button[aria-selected="true"] { scale: 1.1; } .nav-button[aria-selected="true"], .nav-button:focus-visible { outline: 0.2em solid var(--active-color); outline-offset: 0.2em; } .nav-button[aria-selected="false"] { filter: opacity(0.7); } .nav-button[aria-selected="false"]:where(:hover, :focus-visible) { filter: opacity(1); } @container (max-width: 660px) { .nav-button:not(:has(img)) { background-color: rgb(241, 235, 232); } .slider-navigation { display: flex; justify-content: center; padding-block: 1.5em; } .nav-button { inline-size: 0.625rem; aspect-ratio: 1; border-radius: 50%; } .nav-button > .thumbnail { display: none; } .nav-button[aria-selected="true"] { background-color: black; scale: 1.5; } }
class Slider { constructor(slider) { this.slider = slider; this.display = slider.querySelector(".image-display"); this.navButtons = Array.from(slider.querySelectorAll(".nav-button")); this.prevButton = slider.querySelector(".prev-button"); this.nextButton = slider.querySelector(".next-button"); this.sliderNavigation = slider.querySelector(".slider-navigation"); this.currentSlideIndex = 0; this.preloadedImages = {}; this.initialize(); } initialize() { this.setupSlider(); this.preloadImages(); this.eventListeners(); } setupSlider() { this.showSlide(this.currentSlideIndex); } showSlide(index) { this.currentSlideIndex = index; const navButtonImg = this.navButtons[ this.currentSlideIndex ].querySelector("img"); if (navButtonImg) { const imgClone = navButtonImg.cloneNode(); this.display.replaceChildren(imgClone); } this.updateNavButtons(); } updateNavButtons() { this.navButtons.forEach((button, buttonIndex) => { const isSelected = buttonIndex === this.currentSlideIndex; button.setAttribute("aria-selected", isSelected); if (isSelected) button.focus(); }); } preloadImages() { this.navButtons.forEach((button) => { const imgElement = button.querySelector("img"); if (imgElement) { const imgSrc = imgElement.src; if (!this.preloadedImages[imgSrc]) { this.preloadedImages[imgSrc] = new Image(); this.preloadedImages[imgSrc].src = imgSrc; } } }); } eventListeners() { document.addEventListener("keydown", (event) => { this.handleAction(event.key); }); this.sliderNavigation.addEventListener("click", (event) => { const targetButton = event.target.closest(".nav-button"); const index = targetButton ? this.navButtons.indexOf(targetButton) : -1; if (index !== -1) { this.showSlide(index); } }); this.prevButton.addEventListener("click", () => this.handleAction("prev") ); this.nextButton.addEventListener("click", () => this.handleAction("next") ); } handleAction(action) { if (action === "Home") { this.currentSlideIndex = 0; } else if (action === "End") { this.currentSlideIndex = this.navButtons.length - 1; } else if (action === "ArrowRight" || action === "next") { this.currentSlideIndex = (this.currentSlideIndex + 1) % this.navButtons.length; } else if (action === "ArrowLeft" || action === "prev") { this.currentSlideIndex = (this.currentSlideIndex - 1 + this.navButtons.length) % this.navButtons.length; } this.showSlide(this.currentSlideIndex); } } const ImageSlider = new Slider(document.querySelector(".image-slider"));