fix(photoswipe): keyboard arrow animation via CSS keyframes

Previous approach (CSS transition + reflow trick) is unreliable in
Firefox. New approach: PhotoSwipe emits 'change' synchronously before
painting; we add a direction-aware CSS keyframe animation to the
incoming slide element, with animation-fill-mode:both so there is no
flash before the animation starts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
This commit is contained in:
2026-06-21 21:36:48 +02:00
parent 415d95ed47
commit 9f503c011d
4 changed files with 79 additions and 18 deletions
+22 -6
View File
@@ -515,15 +515,31 @@ const lightbox = new PhotoSwipeLightbox({
pswpModule: () => import('https://cdn.jsdelivr.net/npm/photoswipe@5/dist/photoswipe.esm.min.js')
});
lightbox.on('afterOpen', function () {
var container = lightbox.pswp.element.querySelector('.pswp__container');
var pswp = lightbox.pswp;
var keyDir = 0;
var clearTimer = null;
function onKey(e) {
if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;
container.style.transition = 'transform 0.35s cubic-bezier(0.4, 0, 0.22, 1)';
container.getBoundingClientRect(); // force reflow so browser commits current position as "from"
setTimeout(function () { container.style.transition = ''; }, 400);
if (e.key === 'ArrowRight') keyDir = 1;
else if (e.key === 'ArrowLeft') keyDir = -1;
else keyDir = 0;
}
document.addEventListener('keydown', onKey, true);
lightbox.pswp.on('close', function () { document.removeEventListener('keydown', onKey, true); });
pswp.on('change', function () {
if (!keyDir) return;
var dir = keyDir;
keyDir = 0;
var el = pswp.currSlide && pswp.currSlide.el;
if (!el) return;
el.classList.remove('pswp-key-from-left', 'pswp-key-from-right');
el.offsetWidth; // restart animation if navigating rapidly
el.classList.add(dir > 0 ? 'pswp-key-from-right' : 'pswp-key-from-left');
clearTimeout(clearTimer);
clearTimer = setTimeout(function () { el.classList.remove('pswp-key-from-left', 'pswp-key-from-right'); }, 400);
});
pswp.on('close', function () {
document.removeEventListener('keydown', onKey, true);
clearTimeout(clearTimer);
});
});
lightbox.init();