[FIX] website: ensure lazy loaded images are loaded on zoomed Chrome
Before this commit, some images were never appearing on Chrome, especially when using the 90% zoom. Steps to reproduce (on a 1920x1080 screen and using Chrome): 1. Edit the homepage 2. Add a "Cover" block and setup a 50% min-height on it 3. Add 2 "Columns" blocks below the "Cover" block 4. Set the width of the first "Columns" snippet's first image to the recommended size (690px) 5. Save 6. As a public user, set the browser zoom to 90% and go to the page (you may need to reload the page again so images are in cache) => The first image of the second "Columns" block never appears. opw-2731507 closes odoo/odoo#91075 X-original-commit: e9ef21b6cd5ae58322fa9102f9f34f06835f0485 Signed-off-by: Romain Derie (rde) <rde@odoo.com> Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
@@ -13,6 +13,7 @@ const dom = require('web.dom');
|
||||
var mixins = require('web.mixins');
|
||||
var publicWidget = require('web.public.widget');
|
||||
var utils = require('web.utils');
|
||||
const wUtils = require('website.utils');
|
||||
|
||||
var qweb = core.qweb;
|
||||
|
||||
@@ -1353,6 +1354,73 @@ registry.WebsiteAnimate = publicWidget.Widget.extend({
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* The websites, by default, use image lazy loading via the loading="lazy"
|
||||
* attribute on <img> elements. However, this does not work great on all
|
||||
* browsers. This widget fixes the behaviors with as less code as possible.
|
||||
*/
|
||||
registry.ImagesLazyLoading = publicWidget.Widget.extend({
|
||||
selector: '#wrapwrap',
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start() {
|
||||
// For each image on the page, force a 1px min-height so that Chrome
|
||||
// understands the image exists on different zoom sizes of the browser.
|
||||
// Indeed, without this, on a 90% zoom, some images were never loaded.
|
||||
// Once the image has been loaded, the 1px min-height is removed.
|
||||
// Note: another possible solution without JS would be this CSS rule:
|
||||
// ```
|
||||
// [loading="lazy"] {
|
||||
// min-height: 1px;
|
||||
// }
|
||||
// ```
|
||||
// This would solve the problem the same way with a CSS rule with a
|
||||
// very small priority (any class setting a min-height would still have
|
||||
// priority). However, the min-height would always be forced even once
|
||||
// the image is loaded, which could mess with some layouts relying on
|
||||
// the image intrinsic min-height.
|
||||
const imgEls = this.$target[0].querySelectorAll('img[loading="lazy"]');
|
||||
for (const imgEl of imgEls) {
|
||||
// Write initial min-height on the dataset, so that it can also
|
||||
// be properly restored on widget destroy.
|
||||
imgEl.dataset.lazyLoadingInitialMinHeight = imgEl.style.minHeight;
|
||||
imgEl.style.minHeight = '1px';
|
||||
wUtils.onceAllImagesLoaded($(imgEl)).then(() => {
|
||||
if (this.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
this._restoreImage(imgEl);
|
||||
});
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
destroy() {
|
||||
this._super(...arguments);
|
||||
const imgEls = this.$target[0].querySelectorAll('img[data-lazy-loading-initial-min-height]');
|
||||
for (const imgEl of imgEls) {
|
||||
this._restoreImage(imgEl);
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {HTMLImageElement} imgEl
|
||||
*/
|
||||
_restoreImage(imgEl) {
|
||||
imgEl.style.minHeight = imgEl.dataset.lazyLoadingInitialMinHeight;
|
||||
delete imgEl.dataset.lazyLoadingInitialMinHeight;
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
Widget: publicWidget.Widget,
|
||||
Animation: Animation,
|
||||
|
||||
Reference in New Issue
Block a user