From 8507a3eb1649cc486271ccd6527ecc61e75e58ed Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Sat, 31 Oct 2020 00:25:05 +0100 Subject: [PATCH] prevent jumps when image loads by adding a spacer --- .../web/ui/css/themes/element/theme.css | 29 +++++++++++++----- src/platform/web/ui/css/timeline.css | 6 ++-- .../web/ui/session/room/timeline/ImageView.js | 30 +++++++++---------- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/platform/web/ui/css/themes/element/theme.css b/src/platform/web/ui/css/themes/element/theme.css index c6f4a620..3e42fc9c 100644 --- a/src/platform/web/ui/css/themes/element/theme.css +++ b/src/platform/web/ui/css/themes/element/theme.css @@ -494,6 +494,8 @@ ul.Timeline > li.messageStatus .message-container > p { .message-container { padding: 1px 10px 0px 10px; margin: 5px 10px 0 10px; + /* so the .picture can grow horizontally and its spacer can grow vertically */ + width: 100%; } .message-container .profile { @@ -505,6 +507,10 @@ ul.Timeline > li.messageStatus .message-container > p { --avatar-size: 25px; } +.TextMessageView { + width: 100%; +} + .TextMessageView.continuation .message-container { margin-top: 0; margin-bottom: 0; @@ -534,22 +540,28 @@ ul.Timeline > li.messageStatus .message-container > p { } -.message-container a.picture { +.message-container .picture { display: grid; text-decoration: none; overflow: hidden; margin-top: 4px; border-radius: 4px; + width: 100%; } -.message-container a.picture > img { - grid-row: 1 / 2; - grid-column: 1 / 2; +/* .spacer grows with an inline padding-top to the size of the image, +so the timeline doesn't jump when the image loads */ +.message-container .picture > * { + grid-row: 1; + grid-column: 1; } -.message-container a.picture > time { - grid-row: 1 / 2; - grid-column: 1 / 2; +.message-container .picture > img { + width: 100%; + height: auto; +} + +.message-container .picture > time { align-self: end; justify-self: end; color: #2e2f32; @@ -559,6 +571,9 @@ ul.Timeline > li.messageStatus .message-container > p { background-color: rgba(255, 255, 255, 0.75); border-radius: 4px; } +.message-container .picture > .spacer { + width: 100%; +} .TextMessageView.pending .message-container { color: #ccc; diff --git a/src/platform/web/ui/css/timeline.css b/src/platform/web/ui/css/timeline.css index 5a45f56b..ee9ffdbb 100644 --- a/src/platform/web/ui/css/timeline.css +++ b/src/platform/web/ui/css/timeline.css @@ -37,14 +37,12 @@ limitations under the License. margin: 5px 0; } -.message-container a.picture { +.message-container .picture { display: block; } -.message-container a.picture > img { +.message-container .picture > img { display: block; - width: 100%; - height: auto; } .TextMessageView { diff --git a/src/platform/web/ui/session/room/timeline/ImageView.js b/src/platform/web/ui/session/room/timeline/ImageView.js index b16ea834..00669a55 100644 --- a/src/platform/web/ui/session/room/timeline/ImageView.js +++ b/src/platform/web/ui/session/room/timeline/ImageView.js @@ -19,20 +19,20 @@ import {renderMessage} from "./common.js"; export class ImageView extends TemplateView { render(t, vm) { - return renderMessage(t, vm, - t.div([ - t.a({href: vm.lightboxUrl, className: "picture"}, [ - t.img({ - src: vm => vm.thumbnailUrl, - loading: "lazy", - alt: vm => vm.label, - title: vm => vm.label, - style: vm => `max-width: ${vm.thumbnailWidth}px; max-height: ${vm.thumbnailHeight}px;` - }), - t.time(vm.date + " " + vm.time) - ]), - t.if(vm => vm.error, t.createTemplate((t, vm) => t.p({className: "error"}, vm.error))) - ]) - ); + const heightRatioPercent = (vm.thumbnailHeight / vm.thumbnailWidth) * 100; + return renderMessage(t, vm, [ + t.a({href: vm.lightboxUrl, className: "picture", style: `max-width: ${vm.thumbnailWidth}px`}, [ + t.div({className: "spacer", style: `padding-top: ${heightRatioPercent}%;`}), + t.img({ + loading: "lazy", + src: vm => vm.thumbnailUrl, + alt: vm => vm.label, + title: vm => vm.label, + style: `max-width: ${vm.thumbnailWidth}px; max-height: ${vm.thumbnailHeight}px;` + }), + t.time(vm.date + " " + vm.time), + ]), + t.if(vm => vm.error, t.createTemplate((t, vm) => t.p({className: "error"}, vm.error))) + ]); } }