Placeholder is sized by width only, so a thumbnail with a different aspect ratio is drawn at the wrong height
PhotoSwipe version: 5.4.4 Browser: Chrome (also reproducible in incognito, so not an extension)
Summary
Placeholder.setDisplayedSize() scales the image placeholder by width and lets
its height follow the thumbnail's own aspect ratio. When the thumbnail's aspect
ratio differs from the full image's — common in gallery generators that crop
thumbnails to a fixed size — the placeholder is drawn taller or shorter than the
image it stands in for.
The user-visible result is a distracting flicker on open: for a fraction of a second a blurred band of the photo extends past where the image actually ends, and then snaps to the correct size once the full image paints. It reads as a rendering glitch rather than as a progressive-loading effect, and it is most noticeable on the very interaction that should feel smoothest — clicking a thumbnail to open the lightbox.
Cause
In src/js/slide/placeholder.js:
setDisplayedSize(width, height) {
if (this.element.tagName === 'IMG') {
// Use transform scale() to modify img placeholder size
// (instead of changing width/height directly).
// This helps with performance, specifically in iOS15 Safari.
setWidthHeight(this.element, 250, 'auto');
this.element.style.transformOrigin = '0 0';
this.element.style.transform = toTransformString(0, 0, width / 250);
} else {
setWidthHeight(this.element, width, height);
}
}For the IMG branch the rendered height is 250 / thumbnailAspectRatio, scaled
by width / 250 — so the final height is width / thumbnailAspectRatio. The
height argument is ignored. The div branch just below uses both dimensions
and is correct.
Steps to reproduce
- Build a gallery whose thumbnails are cropped to a fixed size — e.g. 280x210 (4:3) — while the photos have other aspect ratios.
- Give the anchor correct
data-pswp-width/data-pswp-heightfor the full image (e.g. 1152x768, 3:2) and setmsrcto the cropped thumbnail. - Open that slide.
Expected: the placeholder occupies exactly the box the full image will.
Actual: the placeholder is width / (4/3) tall instead of width / (3/2),
i.e. ~12% too tall. It overhangs the bottom of the image and then jumps to the
right size when the full image paints — a brief but distracting flicker on every
open. With the dynamic caption plugin (type: 'below') the overhang lands on top
of the caption text, which makes it look especially broken. It affects the first
slide opened, the only one that gets an image placeholder
(content.js: this.data.msrc && this.slide.isFirstSlide ? this.data.msrc : false).
Suggested fix
Honour the height argument in the IMG branch — either by scaling the two
axes independently, or by setting explicit width/height on the element and
letting object-fit: cover crop the thumbnail into the correct box. The latter
keeps a single transform for the iOS 15 performance reason noted in the
comment, while making a mismatched thumbnail fill the right rectangle rather
than dictating its shape.
Workaround
Suppress the image placeholder so PhotoSwipe uses the correctly sized div:
lightbox.addFilter('placeholderSrc', () => false);This costs the blurred preview, but nothing is ever drawn at the wrong shape.
Source: dimsemenov/PhotoSwipe