Cara Membuat Galeri Foto Fullscreen Slideshow di Blogger
Di halaman artikel saya hanya menampilkan cover album. Ketika album dibuka, viewer mengambil foto dari data-src lalu menampilkannya memenuhi layar. Kontrol slideshow dibuat tetap sederhana: previous, next, play/pause, fullscreen, counter, caption dan thumbnail.
Engine galeri dibuat langsung dengan HTML, CSS dan JavaScript biasa tanpa library galeri eksternal. Dengan cara ini struktur kode lebih mudah dibaca, selector bisa dibuat khusus, dan perilaku viewer lebih mudah disesuaikan dengan template Blogger.
Sumber referensi teknis : MDN KeyboardEvent | MDN Touch Events
Live Preview Galeri Foto Premium
Saya buat preview-nya langsung aktif di artikel. Klik salah satu album di bawah untuk membuka slideshow fullscreen. Foto bisa digeser dari tombol kiri/kanan, thumbnail, keyboard atau swipe. Tombol play menjalankan slideshow otomatis, sedangkan tombol expand memakai Fullscreen API jika didukung browser.













Konsep Galeri Fullscreen
Tidak lagi membawa library galeri eksternal hanya untuk membuka foto.
Album dan foto cukup ditambah dari markup sederhana.
Layout album satu kolom dan viewer mengikuti ukuran layar.
Cover album tetap dimuat seperti gambar biasa, sedangkan foto di dalam album disimpan pada data-src. Foto tersebut baru diberikan ke viewer ketika album dibuka sehingga halaman artikel tidak perlu menampilkan seluruh koleksi foto sekaligus.
Cara Kerja Engine Galeri
Fitur yang Saya Masukkan
Saya juga memakai selector khusus .cfGalleryStage dan .cfGalleryInfo agar viewer tidak bentrok dengan style global figure atau figcaption dari template.
Thumbnail saya letakkan di bagian bawah viewer agar foto bisa dipilih langsung tanpa harus menekan tombol berkali-kali. Saat foto berganti, gambar lama memudar sambil sedikit mengecil, lalu gambar baru masuk dengan efek zoom dan opacity sebelum kembali ke ukuran normal.
Satu artikel bisa memiliki beberapa kategori galeri.
Viewer memenuhi layar dan dapat masuk ke Fullscreen API browser.
Tombol play menjalankan pergantian foto otomatis setiap beberapa detik.
Panah kiri/kanan, Space, tombol F dan Escape bisa digunakan.
Geser kiri atau kanan untuk berpindah foto.
Foto lama memudar dan mengecil, lalu foto baru masuk dengan efek zoom.
1. Pasang Struktur HTML Galeri
Saya menaruh struktur ini di posisi artikel tempat galeri ingin muncul. Setiap tombol album memakai data-album, sedangkan kumpulan foto memakai data-album-data dengan ID yang sama.
<div class="cfGalleryGrid">
<button class="cfGalleryAlbum" type="button" data-album="a1">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFGOtgWnfQlTqDvk4E0yVGC61hUtxrEWu0VsPy9wwi9GJyZfRuPUoHnNj8QlJr_o9kBEA8dDgh1DyTusK3YB7_2uBPone5yanoaHByVZgOQWJ-_dOXqb4B68SaaCgPtjvSABXQNpJ8TOM/s800/pemandangan01.jpg" alt="Travel Europe" loading="lazy" />
<span class="cfGalleryShade">
</span>
<span class="cfGalleryAlbumMeta">
<i class="fa-solid fa-images">
</i>
<b>Travel Europe</b>
<small>4 foto</small>
</span>
</button>
<button class="cfGalleryAlbum" type="button" data-album="a2">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh13pXdYhb6QHj1cz6noJwM_U5zbWwcZomIk2uBW_RvRtfO-baRdnS-SuuxQzTsz6GhtN0VZmX721vbmurPpjh9reKbQLjC6eo_o70B-2_ssArG4xwHx5umPRXkAlJzuTbEgdIGY52Gs14/s800/japan-village01.jpg" alt="Japan Village" loading="lazy" />
<span class="cfGalleryShade">
</span>
<span class="cfGalleryAlbumMeta">
<i class="fa-solid fa-images">
</i>
<b>Japan Village</b>
<small>5 foto</small>
</span>
</button>
<button class="cfGalleryAlbum" type="button" data-album="a3">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4ieUmTdfcoKCutRIG9oec6NgvEa3BkeIZLQIpY8tN2UCxu7A_P3iKlj56BUZEP6LpKiR2yQ6ScbuNBdGcZ2AiLDP70sYcEIXRTMMCTC0T3NVXTDTKS2js_saSPCvr6fHMjO7eqpdn7lw/s800/indonesia01.jpg" alt="Destination Indonesia" loading="lazy" />
<span class="cfGalleryShade">
</span>
<span class="cfGalleryAlbumMeta">
<i class="fa-solid fa-images">
</i>
<b>Destination Indonesia</b>
<small>4 foto</small>
</span>
</button>
</div>
<div class="cfGalleryData" hidden>
<div data-album-data="a1" data-title="Travel Europe">
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFGOtgWnfQlTqDvk4E0yVGC61hUtxrEWu0VsPy9wwi9GJyZfRuPUoHnNj8QlJr_o9kBEA8dDgh1DyTusK3YB7_2uBPone5yanoaHByVZgOQWJ-_dOXqb4B68SaaCgPtjvSABXQNpJ8TOM/s800/pemandangan01.jpg" alt="Travel Europe 1" />
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9eWBIy0rPLaJS4Yo-kH21cCVqjKmmGEAJ_5iDqcjK3tVq8At1s3zd8bIL-IwJ5Mg31kjBBTTufDGUyZMbn9KUdq08vFAEmPa3N3ix5sYHfdyMFThhiI7pnEdwbjysZiV_rG7Lw9QVolI/s800/pemandangan02.jpg" alt="Travel Europe 2" />
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCUQnBAKua2xqmvMqlPJNeGUdQUn6jMpDuQycgB0x33-nt_mZ6ADFWH_yRzKZEyuu8EpY3m90JsB67ilWyuEeBxx20Q1w6h1MJRqq8wCSkKSQBhIX1_Wsef-vVHNw_B-w9FeQflXhTmD8/s800/pemandangan03.jpg" alt="Travel Europe 3" />
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgncMZ2Py6YEHZMvEmvpp_RFURioV-FmIL8IR_FjVT3b-ijNIewqtbxJ4Z1hyphenhyphen_iZuxdZwgJ6Qc0xoknFLDWdK9V4mT3SpafrkJX4WShJrqq0_BnHrSQF-i7StNUsOaTFzq9bMthKFAE-dU/s800/pemandangan04.jpg" alt="Travel Europe 4" />
</div>
<div data-album-data="a2" data-title="Japan Village">
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh13pXdYhb6QHj1cz6noJwM_U5zbWwcZomIk2uBW_RvRtfO-baRdnS-SuuxQzTsz6GhtN0VZmX721vbmurPpjh9reKbQLjC6eo_o70B-2_ssArG4xwHx5umPRXkAlJzuTbEgdIGY52Gs14/s800/japan-village01.jpg" alt="Japan Village 1" />
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO1yJxlwX09_Td0EZ_wbLbd0O0aASl3raBN_tUZn9L64kKHqfR6L972Q6q67sRZjK4ZTDt76U2sGZXRgFQadCHw6ia1phnppqMYCBz5Epmw_2kSLreD2T0Q0Z4Os7Ngp2_ed5hWrgJlh4/s800/japan-village02.jpg" alt="Japan Village 2" />
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid8SQbpyCIhyphenhyphenjurDcyHbeZn7P1AVgU6-eQH2GpuLPXYSe9gWs7ESlisxuqJMucas0HBZ8OnP6OVFrUSz6RWrxnzLXjPgvpblk_c3cQqKGdUIqbCmS_qz12oQpDcX3b-LW1LbrvtfuccsM/s800/japan-village03.jpg" alt="Japan Village 3" />
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA1fhWZnYfatDuBU4leLAF0pnHlDCQPizF2yaE7udcAbPV1Ksc9nr7inNhqy2TxcrIZ2TcDlhI62bMa74AiRtC_jfdw8PqdKnPAovj0DkZSOzh2gHeA3fvLekr8go5hlSfJVG2F5-O4A8/s800/japan-village04.jpg" alt="Japan Village 4" />
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY-CIJqoGubip4W6H3-4EALY6lV3hKPllYx5T-lNx0jliGNSFredrN5UMUaf3bbfp5GuUKkAnSZbbFYZKG6HRJZijwO76dmSegf-vTpSnx-sSukZein_nmu8_2YKDHEjSHZdsrKmev8oE/s800/japan-village05.jpg" alt="Japan Village 5" />
</div>
<div data-album-data="a3" data-title="Destination Indonesia">
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4ieUmTdfcoKCutRIG9oec6NgvEa3BkeIZLQIpY8tN2UCxu7A_P3iKlj56BUZEP6LpKiR2yQ6ScbuNBdGcZ2AiLDP70sYcEIXRTMMCTC0T3NVXTDTKS2js_saSPCvr6fHMjO7eqpdn7lw/s800/indonesia01.jpg" alt="Destination Indonesia 1" />
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinOTx89y9KIfYLZztW9NInTi94REDEJsn15K-K1F9z1bMYUE7iCQziJ1Zq1sHDgMGaiNCduFZkhxR-fP1NPvk7W51U9BzG49UuHFdhYP7gqHF2X0EaFCmL5bF0OrKN3x3XNmX__96w68Y/s800/indonesia02.jpg" alt="Destination Indonesia 2" />
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgssfG_asmw8p6l-UiFEMNeYpwMy9qgBBc2XwATzcg8A2i9EmLs4NC2PX77Y4MCMhef8_rFYxuzbUs2MMQrPxZbNT79MsVSjJaONTFIztMZBpW0e03iR6fy5y5iGu6b9tErHLATK_pT7EM/s800/indonesia03.jpg" alt="Destination Indonesia 3" />
<img data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0qoArdXaGi32wWfI04Lc5yQmPWy425uhnvI2EF46_YAkubzH33yji8zVuk8jETR74Y69FrT7zFndLf6FKTEOrnK847icE39FnHmPc3_TxYITZE7Cy6YImpfBRr2lofZY-pq5n38J0a3g/s800/indonesia04.jpg" alt="Destination Indonesia 4" />
</div>
</div>
<div class="cfGalleryLightbox" hidden aria-hidden="true">
<div class="cfGalleryBackdrop" data-close>
</div>
<div class="cfGalleryViewer" role="dialog" aria-modal="true" aria-label="Photo gallery slideshow">
<div class="cfGalleryTopbar">
<button class="cfGalleryTool cfGalleryPlay" type="button" aria-label="Putar slideshow" title="Play slideshow"><i class="fa-solid fa-play"></i></button>
<button class="cfGalleryTool cfGalleryFullscreen" type="button" aria-label="Fullscreen" title="Fullscreen"><i class="fa-solid fa-expand"></i></button>
</div>
<button class="cfGalleryClose" type="button" aria-label="Tutup"><i class="fa-solid fa-xmark"></i></button>
<button class="cfGalleryNav cfGalleryPrev" type="button" aria-label="Sebelumnya"><i class="fa-solid fa-chevron-left"></i></button>
<div class="cfGalleryStage"><img class="cfGalleryImage" alt="" /><div class="cfGalleryInfo"><span class="cfGalleryCaption"></span><small class="cfGalleryCounter"></small></div><div class="cfGalleryThumbs" aria-label="Thumbnail foto"></div><div class="cfGalleryProgress" aria-hidden="true"><span></span></div></div>
<button class="cfGalleryNav cfGalleryNext" type="button" aria-label="Berikutnya"><i class="fa-solid fa-chevron-right"></i></button>
</div>
</div>
</div>
2. Pasang CSS
CSS berikut mengatur kartu album, overlay, lightbox, tombol navigasi, caption, dan mode mobile. Untuk artikel CodeFlare saya tetap menaruh CSS di bagian bawah.
.cfGalleryWarning{padding:15px}
.cfGalleryHero{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:18px 0}
.cfGalleryHero>div{padding:12px;border:1px solid rgba(0,131,218,.18);border-radius:7px;background:rgba(0,131,218,.025)}
.cfGalleryHero i{display:block;margin-bottom:7px;color:#0083da;font-size:19px}
.cfGalleryHero strong{display:block;font-size:15px}
.cfGalleryHero p{margin:4px 0 0;font-size:15px;line-height:1.5}
.cfGalleryApp{position:relative;margin:18px 0}
.cfGalleryGrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
.cfGalleryAlbum{position:relative;overflow:hidden;min-height:220px;padding:0;border:0;border-radius:9px;background:#0b1720;cursor:pointer;text-align:left}
.cfGalleryAlbum img{display:block;width:100%;height:100%;min-height:220px;object-fit:cover;transition:transform .35s ease}
.cfGalleryAlbum:hover img{transform:scale(1.06);opacity:.92}
.cfGalleryShade{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,.02) 35%,rgba(3,12,18,.9) 100%)}
.cfGalleryAlbumMeta{position:absolute;left:13px;right:13px;bottom:12px;z-index:2;color:#fff}
.cfGalleryAlbumMeta i{display:inline-flex;margin-right:6px;color:#8cd7ff}
.cfGalleryAlbumMeta b{font-size:15px}
.cfGalleryAlbumMeta small{display:block;margin-top:3px;font-size:12px;color:rgba(255,255,255,.72)}
.cfGalleryLightbox[hidden]{display:none}
.cfGalleryLightbox{position:fixed;inset:0;z-index:999999;display:grid;place-items:center;padding:18px}
.cfGalleryBackdrop{position:absolute;inset:0;background:rgba(2,9,14,.9);backdrop-filter:blur(8px)}
.cfGalleryViewer{position:relative;z-index:2;width:min(100%,980px);height:min(86vh,760px);display:grid;place-items:center}
.cfGalleryViewer::before,.cfGalleryViewer::after{content:"";position:absolute;top:0;bottom:0;width:84px;z-index:3;pointer-events:none}
.cfGalleryViewer::before{left:0;background:linear-gradient(90deg,rgba(2,9,14,.62),rgba(2,9,14,0))}
.cfGalleryViewer::after{right:0;background:linear-gradient(270deg,rgba(2,9,14,.74),rgba(2,9,14,0))}
.cfGalleryStage{display:flex;position:relative;width:100%;height:100%;align-items:center;justify-content:center}
.cfGalleryImage{display:block;max-width:100%;max-height:calc(86vh - 118px);object-fit:contain;border-radius:6px;box-shadow:0 22px 60px rgba(0,0,0,.35)}
.cfGalleryImage{opacity:1;transform:translateX(0) scale(1);transition:opacity .34s ease,transform .42s cubic-bezier(.2,.75,.25,1);will-change:opacity,transform}
.cfGalleryImage.is-leaving{opacity:0;transform:translateX(var(--cfGalleryMove,18px)) scale(.94)}
.cfGalleryImage.is-entering{opacity:0;transform:translateX(calc(var(--cfGalleryMove,18px)*-1)) scale(1.07)}
.cfGalleryInfo{position:absolute;left:50%;bottom:62px;z-index:5;display:flex;gap:10px;align-items:center;max-width:calc(100% - 110px);padding:8px 11px;border-radius:6px;background:rgba(4,18,28,.72);color:#fff;transform:translateX(-50%);backdrop-filter:blur(6px)}
.cfGalleryThumbs{position:absolute;left:50%;bottom:6px;z-index:5;display:flex;gap:6px;width:max-content;max-width:calc(100% - 100px);padding:6px;overflow-x:auto;transform:translateX(-50%);border:1px solid rgba(255,255,255,.12);border-radius:7px;background:rgba(4,18,28,.66);backdrop-filter:blur(6px);scrollbar-width:thin}
.cfGalleryThumb{flex:0 0 auto;width:56px;height:40px;padding:0;overflow:hidden;border:1px solid transparent;border-radius:5px;background:#07131c;cursor:pointer;opacity:.62;transition:opacity .2s ease,transform .2s ease,border-color .2s ease}
.cfGalleryThumb img{display:block;width:100%;height:100%;object-fit:cover}
.cfGalleryThumb:hover{opacity:1;transform:translateY(-2px) scale(1.06)}
.cfGalleryThumb.is-active{opacity:1;border-color:#8cd7ff;box-shadow:0 0 0 1px rgba(0,131,218,.25)}
.cfGalleryCaption{font-size:15px;font-weight:700}
.cfGalleryCounter{font-size:12px;color:rgba(255,255,255,.72);white-space:nowrap}
.cfGalleryClose,.cfGalleryNav{position:absolute;z-index:6;display:flex;align-items:center;justify-content:center;padding:0;border:1px solid rgba(255,255,255,.18);background:rgba(4,18,28,.42);color:#fff;cursor:pointer;backdrop-filter:blur(5px);transition:background .25s ease,border-color .25s ease,box-shadow .25s ease,transform .25s ease,opacity .25s ease;opacity:.96}
.cfGalleryClose{top:0;right:0;width:42px;height:42px;border-radius:7px}
.cfGalleryNav{top:50%;width:44px;height:52px;transform:translateY(-50%)}
.cfGalleryPrev{left:0;border-radius:7px 0 0 7px}
.cfGalleryNext{right:0;border-radius:0 7px 7px 0}
.cfGalleryClose:hover{background:rgba(0,131,218,.92);border-color:rgba(255,255,255,.6);box-shadow:0 10px 24px rgba(0,131,218,.24);transform:scale(1.05)}
.cfGalleryNav:hover{background:rgba(0,131,218,.92);border-color:rgba(255,255,255,.6);box-shadow:0 10px 24px rgba(0,131,218,.24);transform:translateY(-50%) scale(1.05)}
.cfGalleryClose i,.cfGalleryNav i{color:#fff;font-size:16px;text-shadow:0 1px 6px rgba(0,0,0,.22)}
.cfGalleryLock{overflow:hidden}
.cfGalleryFlow{display:grid;grid-template-columns:1fr 28px 1fr 28px 1fr;gap:7px;align-items:center;margin:18px 0}
.cfGalleryFlow>div{padding:11px;text-align:center;border:1px solid rgba(0,131,218,.18);border-radius:7px;background:rgba(0,131,218,.025)}
.cfGalleryFlow>div i{display:block;margin-bottom:6px;color:#0083da;font-size:18px}
.cfGalleryFlow strong,.cfGalleryFlow span{display:block;font-size:15px}
.cfGalleryFlow span{margin-top:2px;opacity:.7}
.cfGalleryFlow>i{text-align:center;color:#0083da}
.cfGallerySteps{display:grid;gap:8px;margin:17px 0}
.cfGallerySteps>div{display:grid;grid-template-columns:38px minmax(0,1fr);gap:10px;align-items:center;padding:10px 12px;border-left:3px solid #0083da;background:rgba(0,131,218,.035)}
.cfGallerySteps b{display:flex;width:32px;height:30px;align-items:center;justify-content:center;border-radius:4px;background:#0083da;color:#fff;font-size:12px}
.cfGallerySteps strong,.cfGallerySteps small{display:block;font-size:15px}
.cfGallerySteps small{margin-top:2px;line-height:1.4;opacity:.7}
.cfGalleryFeature{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin:17px 0}
.cfGalleryFeature>div{padding:11px;border:1px solid rgba(0,131,218,.18);border-radius:6px;background:rgba(0,131,218,.025)}
.cfGalleryFeature i{display:block;margin-bottom:6px;color:#0083da;font-size:18px}
.cfGalleryFeature strong{display:block;font-size:15px}
.cfGalleryFeature p{margin:4px 0 0;font-size:15px;line-height:1.5}
.cfGalleryClosing{display:grid;grid-template-columns:42px minmax(0,1fr);gap:11px;align-items:center;margin:24px 0;padding:14px;border:1px solid rgba(0,131,218,.18);border-radius:7px;background:linear-gradient(120deg,rgba(0,131,218,.06),rgba(105,78,180,.035))}
.cfGalleryClosing>i{display:flex;width:40px;height:40px;align-items:center;justify-content:center;border-radius:5px;background:#0083da;color:#fff}
.cfGalleryClosing small,.cfGalleryClosing strong{display:block}
.cfGalleryClosing small{font-size:12px;letter-spacing:.55px;opacity:.65}
.cfGalleryClosing strong{font-size:16px;margin:2px 0 3px}
.cfGalleryClosing p{margin:0;font-size:15px;line-height:1.5}
@media(max-width:760px){.cfGalleryGrid{grid-template-columns:1fr}
.cfGalleryAlbum{min-height:240px}
.cfGalleryAlbum img{min-height:240px}
.cfGalleryFlow{grid-template-columns:1fr}
.cfGalleryFlow>i{transform:rotate(90deg)}
.cfGalleryHero{grid-template-columns:1fr}
}
@media(max-width:560px){.cfGalleryFeature{grid-template-columns:1fr}
.cfGalleryLightbox{padding:8px}
.cfGalleryViewer{height:92vh}
.cfGalleryImage{max-height:calc(92vh - 122px)}
.cfGalleryNav{width:38px;height:48px}
.cfGalleryInfo{bottom:58px;max-width:calc(100% - 80px)}
.cfGalleryThumbs{max-width:calc(100% - 34px)}
.cfGalleryThumb{width:50px;height:36px}
}
@media(prefers-reduced-motion:reduce){.cfGalleryAlbum img,.cfGalleryImage,.cfGalleryThumb{transition:none}
}
.cfGalleryLightbox{padding:0;background:#02070b}
.cfGalleryBackdrop{background:rgba(2,7,11,.97);backdrop-filter:none}
.cfGalleryViewer{width:100vw;height:100vh;max-width:none;max-height:none;overflow:hidden}
.cfGalleryViewer::before,.cfGalleryViewer::after{width:110px}
.cfGalleryStage{box-sizing:border-box;width:100%;height:100%;padding:58px 72px 126px}
.cfGalleryImage{max-width:100%;max-height:100%;border-radius:4px;box-shadow:0 26px 90px rgba(0,0,0,.48)}
.cfGalleryImage{opacity:1;transform:scale(1);transition:opacity .42s ease,transform .58s cubic-bezier(.2,.75,.2,1);will-change:opacity,transform}
.cfGalleryImage.is-leaving{opacity:0;transform:scale(.9)}
.cfGalleryImage.is-entering{opacity:0;transform:scale(1.1)}
.cfGalleryTopbar{position:absolute;top:12px;left:50%;z-index:8;display:flex;gap:7px;transform:translateX(-50%)}
.cfGalleryTool{display:flex;width:42px;height:42px;align-items:center;justify-content:center;padding:0;border:1px solid rgba(255,255,255,.18);border-radius:7px;background:rgba(4,18,28,.52);color:#fff;cursor:pointer;backdrop-filter:blur(7px);transition:transform .22s ease,background .22s ease,border-color .22s ease}
.cfGalleryTool:hover{transform:translateY(-2px);background:rgba(0,131,218,.92);border-color:rgba(255,255,255,.58)}
.cfGalleryTool i{font-size:15px;color:#fff}
.cfGalleryClose{top:12px;right:12px}
.cfGalleryPrev{left:0}.cfGalleryNext{right:0}
.cfGalleryInfo{bottom:72px}
.cfGalleryThumbs{bottom:18px;max-width:calc(100% - 150px)}
.cfGalleryProgress{position:absolute;left:0;right:0;bottom:0;z-index:7;height:3px;background:rgba(255,255,255,.12);overflow:hidden}
.cfGalleryProgress span{display:block;width:0;height:100%;background:#25a9ee}
.cfGalleryProgress span.is-running{animation:cfGallerySlideProgress 4s linear forwards}
@keyframes cfGallerySlideProgress{from{width:0}to{width:100%}}
.cfGalleryLightbox:fullscreen{background:#02070b}.cfGalleryLightbox:fullscreen .cfGalleryViewer{width:100vw;height:100vh}
@media(max-width:560px){.cfGalleryStage{padding:56px 42px 112px}.cfGalleryViewer::before,.cfGalleryViewer::after{width:58px}.cfGalleryInfo{bottom:62px}.cfGalleryThumbs{bottom:14px;max-width:calc(100% - 28px)}.cfGalleryTopbar{top:8px}.cfGalleryClose{top:8px;right:8px}}
@media(prefers-reduced-motion:reduce){.cfGalleryImage,.cfGalleryTool,.cfGalleryProgress span{transition:none;animation:none}}
3. Pasang JavaScript
JavaScript ini tidak membutuhkan jQuery. Satu engine juga bisa menangani lebih dari satu galeri selama masing-masing memakai atribut data-cf-gallery.
"use strict";
document.querySelectorAll("[data-cf-gallery]").forEach(function(app){
if(app.dataset.ready)return;
app.dataset.ready="1";
var box=app.querySelector(".cfGalleryLightbox");
var photo=app.querySelector(".cfGalleryImage");
var cap=app.querySelector(".cfGalleryCaption");
var counter=app.querySelector(".cfGalleryCounter");
var thumbs=app.querySelector(".cfGalleryThumbs");
var playBtn=app.querySelector(".cfGalleryPlay");
var fullBtn=app.querySelector(".cfGalleryFullscreen");
var progress=app.querySelector(".cfGalleryProgress span");
var items=[],index=0,startX=0,animating=false,playing=false,animTimer=0,slideTimer=0;
var slideDelay=4000;
function getAlbum(id){
var d=app.querySelector('[data-album-data="'+id+'"]');
if(!d)return[];
var title=d.getAttribute("data-title")||"Gallery";
return [].slice.call(d.querySelectorAll("img")).map(function(im,i){
return{src:im.getAttribute("data-src")||im.src,alt:im.alt||title+" "+(i+1),title:title};
});
}
function updateThumbs(){
if(!thumbs)return;
[].forEach.call(thumbs.children,function(btn,i){btn.classList.toggle("is-active",i===index)});
var active=thumbs.children[index];
if(active){
var left=active.offsetLeft-(thumbs.clientWidth-active.offsetWidth)/2;
thumbs.scrollTo({left:Math.max(0,left),behavior:"smooth"});
}
}
function render(){
if(!items.length)return;
var x=items[index];
photo.src=x.src;photo.alt=x.alt;cap.textContent=x.title;counter.textContent=(index+1)+" / "+items.length;
updateThumbs();
}
function buildThumbs(){
if(!thumbs)return;
thumbs.innerHTML="";
items.forEach(function(item,i){
var btn=document.createElement("button");
btn.type="button";btn.className="cfGalleryThumb";btn.setAttribute("aria-label","Buka foto "+(i+1));
var im=document.createElement("img");
im.src=item.src;im.alt=item.alt;im.loading="lazy";btn.appendChild(im);
btn.addEventListener("click",function(){if(i===index||animating)return;changeTo(i,i>index?1:-1)});
thumbs.appendChild(btn);
});
}
function restartProgress(){
if(!progress)return;
progress.classList.remove("is-running");
void progress.offsetWidth;
if(playing)progress.classList.add("is-running");
}
function scheduleAuto(){
clearTimeout(slideTimer);
restartProgress();
if(!playing)return;
slideTimer=setTimeout(function(){changeTo(index+1,1,true)},slideDelay);
}
function setPlayState(state){
playing=state;
var icon=playBtn.querySelector("i");
icon.className=playing?"fa-solid fa-pause":"fa-solid fa-play";
playBtn.setAttribute("aria-label",playing?"Jeda slideshow":"Putar slideshow");
playBtn.title=playing?"Pause slideshow":"Play slideshow";
scheduleAuto();
}
function changeTo(next,direction,fromAuto){
if(!items.length||animating)return;
animating=true;clearTimeout(animTimer);clearTimeout(slideTimer);
if(progress)progress.classList.remove("is-running");
photo.classList.add("is-leaving");
animTimer=setTimeout(function(){
index=(next+items.length)%items.length;
var x=items[index];
photo.classList.remove("is-leaving");photo.classList.add("is-entering");
photo.src=x.src;photo.alt=x.alt;cap.textContent=x.title;counter.textContent=(index+1)+" / "+items.length;
updateThumbs();
requestAnimationFrame(function(){requestAnimationFrame(function(){
photo.classList.remove("is-entering");
animTimer=setTimeout(function(){animating=false;if(playing)scheduleAuto()},560);
})});
},260);
}
function move(step){changeTo(index+step,step)}
function toggleFullscreen(){
if(!document.fullscreenEnabled)return;
if(document.fullscreenElement){document.exitFullscreen()}
else if(box.requestFullscreen){box.requestFullscreen()}
}
function updateFullscreenIcon(){
var icon=fullBtn.querySelector("i");
var active=document.fullscreenElement===box;
icon.className=active?"fa-solid fa-compress":"fa-solid fa-expand";
fullBtn.setAttribute("aria-label",active?"Keluar fullscreen":"Fullscreen");
fullBtn.title=active?"Exit fullscreen":"Fullscreen";
}
function open(id){
items=getAlbum(id);if(!items.length)return;
index=0;animating=false;buildThumbs();render();
box.hidden=false;box.setAttribute("aria-hidden","false");
document.documentElement.classList.add("cfGalleryLock");
setPlayState(false);app.querySelector(".cfGalleryClose").focus();
}
function close(){
setPlayState(false);box.hidden=true;box.setAttribute("aria-hidden","true");
photo.removeAttribute("src");photo.classList.remove("is-leaving","is-entering");
clearTimeout(animTimer);clearTimeout(slideTimer);animating=false;
document.documentElement.classList.remove("cfGalleryLock");
if(document.fullscreenElement===box&&document.exitFullscreen)document.exitFullscreen();
}
app.querySelectorAll(".cfGalleryAlbum").forEach(function(btn){
btn.addEventListener("click",function(){open(btn.getAttribute("data-album"))});
});
app.querySelector(".cfGalleryPrev").addEventListener("click",function(){move(-1)});
app.querySelector(".cfGalleryNext").addEventListener("click",function(){move(1)});
app.querySelector(".cfGalleryClose").addEventListener("click",close);
app.querySelector("[data-close]").addEventListener("click",close);
playBtn.addEventListener("click",function(){setPlayState(!playing)});
if(!document.fullscreenEnabled){fullBtn.hidden=true}
else{
fullBtn.addEventListener("click",toggleFullscreen);
document.addEventListener("fullscreenchange",updateFullscreenIcon);
}
box.addEventListener("touchstart",function(e){startX=e.changedTouches[0].clientX},{passive:true});
box.addEventListener("touchend",function(e){
var dx=e.changedTouches[0].clientX-startX;
if(Math.abs(dx)>45)move(dx<0?1:-1);
},{passive:true});
document.addEventListener("keydown",function(e){
if(box.hidden)return;
if(e.key==="Escape"&&!document.fullscreenElement)close();
else if(e.key==="ArrowLeft")move(-1);
else if(e.key==="ArrowRight")move(1);
else if(e.key===" "){e.preventDefault();setPlayState(!playing)}
else if(e.key.toLowerCase()==="f")toggleFullscreen();
});
});
})();</script>
Cara Mengganti Foto dan Nama Album
<img src="..."> di tombol album.data-title.<img data-src="..."> di album yang diinginkan.data-album dan data-album-data harus sama.Ukuran Gambar yang Saya Pakai
Untuk contoh ini saya menaikkan URL gambar lama dari ukuran thumbnail s64 ke s800. Untuk album artikel biasa, ukuran sekitar 800px sudah cukup nyaman sebagai titik awal. Kalau foto memang perlu dilihat sangat detail, URL bisa dinaikkan lagi, tetapi ukuran file juga ikut bertambah.
Kalau JavaScript Mati
Cover album tetap terlihat karena bagian kartu memakai HTML biasa. Yang tidak bekerja hanya pembukaan lightbox. Karena itu saya memilih struktur yang tidak membuat seluruh bagian artikel hilang hanya karena satu script gagal dijalankan.
Galeri Lama Tetap Punya Ide Bagus, Engine-nya yang Saya Modernisasi
Ide awal mengelompokkan foto ke dalam beberapa album masih saya pertahankan karena memang cocok untuk artikel travel, dokumentasi acara, tutorial bergambar, portofolio fotografi, sampai katalog visual. Yang saya buang adalah ketergantungan pada kode plugin yang terlalu besar untuk kebutuhan seperti ini.
Saya lebih suka galeri yang mudah dimodifikasi daripada efek yang keren tetapi membuat kode artikel susah dirawat.

No comments
💬 Share Your Thoughts & Join the Hall of Fame!
Punya pendapat atau tips tentang artikel ini? Tuliskan komentar kamu sekarang! 🚀
💎 Komentar yang bermanfaat, relevan, dan positif berkesempatan tampil di CodeFlare Hall of Fame dan masuk ke Top Commentators Widget.
👉 Comment now. Share your ideas. Get noticed on codeflare.net