From 345c0837b1425d4767deaf753710f4629ab37325 Mon Sep 17 00:00:00 2001 From: Grace Kind Date: Mon, 17 Aug 2026 19:15:08 -0500 Subject: [PATCH] Update video styles --- package.json | 2 +- src/css/style.css | 16 ++++++++--- src/js/templates/postEmbed.template.js | 10 +++++-- .../templates/postEmbed.template.test.js | 28 ++++++++++++------- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 7cf82a92..074f26e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "impro", - "version": "0.19.9", + "version": "0.19.10", "type": "module", "scripts": { "start": "rm -rf \"${BUILD_DIR:-build}\" && NODE_ENV=development eleventy --serve", diff --git a/src/css/style.css b/src/css/style.css index d56d80b0..984c7676 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -2675,7 +2675,14 @@ animated-button { border: var(--hair) solid var(--post-border-color); border-radius: var(--video-border-radius); overflow: hidden; - transform: translateZ(0); /* Prevents video jiggle on iPadOS scroll */ +} + +/* Reserve the media height without CSS aspect-ratio, which can flicker while + * scrolling video elements in WebKit. Percentage padding is based on width. */ +.post-video::before { + content: ""; + display: block; + padding-top: var(--post-video-height, 100%); } .post-video > .alt-indicator { @@ -2731,7 +2738,8 @@ animated-button { } .post-video streaming-video { - display: block; + position: absolute; + inset: 0; width: 100%; height: 100%; } @@ -2741,11 +2749,11 @@ animated-button { width: 100%; height: 100%; object-fit: cover; - transform: translateZ(0); /* Prevents video jiggle on iPadOS scroll */ } .post-video img { - display: block; + position: absolute; + inset: 0; width: 100%; height: 100%; object-fit: cover; diff --git a/src/js/templates/postEmbed.template.js b/src/js/templates/postEmbed.template.js index dab254f0..7a9f3777 100644 --- a/src/js/templates/postEmbed.template.js +++ b/src/js/templates/postEmbed.template.js @@ -276,6 +276,12 @@ function getPostMediaAspectRatio(media) { return Math.max(ratio, MIN_POST_MEDIA_ASPECT_RATIO); } +function postVideoSizingStyle(aspectRatio) { + const ratio = + Number.isFinite(aspectRatio) && aspectRatio > 0 ? aspectRatio : 1; + return `--post-video-height: ${100 / ratio}%;`; +} + function imageContainerTemplate({ image, lazyLoad, doCalculateAspectRatio }) { return html`
{ e.stopPropagation(); e.preventDefault(); @@ -401,7 +407,7 @@ function openAltTextDialog(altText) { function gifPlayerTemplate({ type = "video", uri, alt, aspectRatio = null }) { return html`
${type === "video" ? html` { return container.querySelector(".post-video"); } - it("renders the aspect ratio inline on .post-video", () => { + it("reserves height from the video aspect ratio", () => { const el = renderVideo({ width: 16, height: 9 }); assert(el !== null); - assert.deepEqual(el.style.aspectRatio, String(16 / 9)); + assert.deepEqual( + el.style.getPropertyValue("--post-video-height"), + "56.25%", + ); + assert.deepEqual(el.style.aspectRatio, ""); }); it("caps tall videos at a 1:2 ratio", () => { const el = renderVideo({ width: 1, height: 4 }); - assert.deepEqual(el.style.aspectRatio, String(1 / 2)); + assert.deepEqual(el.style.getPropertyValue("--post-video-height"), "200%"); }); it("passes through wide videos without clamping", () => { const el = renderVideo({ width: 5, height: 1 }); - assert.deepEqual(el.style.aspectRatio, "5"); + assert.deepEqual(el.style.getPropertyValue("--post-video-height"), "20%"); }); - it("omits aspect-ratio when missing", () => { + it("reserves a square when the aspect ratio is missing", () => { const el = renderVideo(undefined); - assert.deepEqual(el.style.aspectRatio, ""); + assert.deepEqual(el.style.getPropertyValue("--post-video-height"), "100%"); }); - it("omits aspect-ratio when invalid", () => { + it("reserves a square when the aspect ratio is invalid", () => { const el = renderVideo({ width: 0, height: 0 }); - assert.deepEqual(el.style.aspectRatio, ""); + assert.deepEqual(el.style.getPropertyValue("--post-video-height"), "100%"); }); it("renders a video with controls and no looping by default", () => { @@ -304,9 +308,13 @@ describe("postEmbedTemplate - gif presentation video", () => { ); }); - it("renders the aspect ratio inline on .post-video", () => { + it("reserves height from the gif aspect ratio", () => { const el = renderGifVideo({ aspectRatio: { width: 16, height: 9 } }); - assert.deepEqual(el.style.aspectRatio, String(16 / 9)); + assert.deepEqual( + el.style.getPropertyValue("--post-video-height"), + "56.25%", + ); + assert.deepEqual(el.style.aspectRatio, ""); }); it("shows the ALT badge when alt text is present", () => { -- 2.51.2