On page load, .flex-viewport should be set to the actual height of the first image.
When clicking a thumbnail, the height of .flex-viewport should change to the height of the new image.
On page load, .flex-viewport height is set to the same value as its width, based on the WooCommerce configuration for single product image width.
When clicking thumbnails 2 to n-1, the height of .flex-viewport doesn't change.
When clicking on thumbnail n, .flex-viewport height is finally set to the actual image height.
When clicking back to another image, the actual height is used.
For some reason, Lazy Load doesn't set the width and height attributes of the image to its actual dimensions, but uses the WC setting instead for both. Only when all images have been loaded, the gallery code uses actual image dimensions to adapt .flex-viewport.
Grab the actual image size, the WooCommerce setting for image width and the setting for cropping. Then, calculate the height from all of them, maintaining correct aspect ratio.
Provide a way to trigger immediate loading of all the gallery images on page load.
Exclude WooCommerce gallery images from lazy loading, or at least provide an option to do this.
The use of correct image heights seems like the most complete solution to me.
FYI, setting images to "height: -webkit-fill-available;" fixes this, but is non-standard. Solution #1 above is still better, but any inline styling imposed via JS should be reset when the actual image loads, in order to maintain reponsiveness.
Oddly, adding the class "skip-lazy" to images does not solve this problem, so either I'm adding it incorrectly, or this method isn't working. Image files are still loaded by jQuery. See https://dev2.get-business-online.com/sentani/product/susana-burgundy-formal-dress/, for example.
This is on latest Jetpack and WooCommerce.
When the page loads, the main image is shown square, but after a while, its bottom is revealed. This is obviously done by a script, but I don't know how to find out which. Basically, this script changes the height of ".flex-viewport", but not the height of anything else. This script also runs on window resize.
Whenever this script has run, the height of the viewport can be copied around to the images in the gallery.
Alternatively (sorry, I'm not a front end developer), can Flex styling be applied so as to stretch everything in the gallery to the height of the viewport?
Looking at this again, it seems like an issue with timing, where the WooCommerce script runs before the Jetpack script, so that the WC script doesn't "see" an image yet.
A possible solution for this would be to load product images in the background, for example, before they are viewed, perhaps even just the next one. Another solution is to push the Jetpack script to run before the WC one and await the image.
One more thing I saw was the use of "padding-top" and absolute placement to fix the aspect ratio of elements. Unfortunately, I'm not good enough with CSS to get the WC gallery elements to stay that way, and if we're already going in the direction of scripting, this may not be necessary.
The aspect ratio, BTW, can be determined from the WooCommerce settings, but won't work for "uncropped" (damn).
Anyone owning this and/or thinking of a solution yet?
There is a filter in WooCommerce that can force images to have a specific height and to be cropped. So I've used it to ensure that all images will be loaded at the same height. Then, I set "body .flex-viewport" to "height: auto !important;" Works OK for me.
The filter code I've used:
add_filter( 'woocommerce_get_image_size_single', 'custom_product_image_size' );
function custom_product_image_size( $size ) {
return array(
'width' => 600,
'height' => 900,
'crop' => 1,
);
}
This may not work for sites with a variety of product image heights, but it works when images are uniform, or can be uniformly cropped.
I'm not sure why this didn't work for me before, but it's working now:
body .flex-viewport {
height: auto !important;
}
The invisible image blocks are still square, but the viewport stays open to the full height of the visible image. When images are switched, it also remains at the same height, inherited from the lazy-loaded new image.
It's important to note that my images are all the same height. Not sure what happens when they're not, but it can't be worse than the default up-down motion...
After some more research of various situations, I'm back to "it's a matter of timing". If the image is loaded by the time the WC script sets the height of the viewport, the appearance is as it would be without lazy loading. Since the image isn't loaded in time, the viewport is set based on the square placeholder image.
So either the timing can be fixed, or the placeholder image's "width" and "height" CSS attributes can be set using the respective IMG tag's attributes.
As a workaround, I'm trying to use the jetpack_lazy_images_new_attributes filter to add a style tag to placeholders, but I'm not sure how to figure out which WooCommerce thumbnail size to use. Another problem is that inline styling overrides the theme and can cause all sorts of issues, unless we can separate the placeholder from the real images.
Can this please be fixed?
This was marked "high priority" on March 7. Any plans to fix it?
Basically, without Lazy Images, the WooCommerce flex-viewport is as tall as the highest actual images. With Lazy Images, it's as high as the square placeholders, dropping to the correct height after all the images have been loaded.
See https://www.plastic2go.com.au/products/plastic-crates/600x400/folding-vented-iso-crate/c2gp6416fv/ (the other page was on a test site and is no longer there).
@ebinnion Do you think you could take a look? This may be related to another issue you were looking at, #10046.
It may also be related to #9896 or #9345.
Thank you!
I likely won't be able to dig into this for a bit. Based on a comment by @galbaras above, I have a hunch that the placeholder PR that I worked on last week might help: #10086
That being said, it's still rough and will need some work before it goes in. At the moment, it's not top of my list. I'll need to pick it up between other projects.
I have a similar issue with Lazy Load on WooCommerce on product pages. I turned off the lazy load feature.
The main image would start to load and then gallery images load to stop the main image from fully appearing. The result is an image of the proper width and about 35 pixels high, a sliver of what the image is supposed to. Clicking on the magnifying brings out a properly sized image and after that, everything loads correctly.
This happens only on the product pages. Pages, catalog pages are fine, no issues.
For the moment I have removed the lazy feature from the site, so I can't show it to you. It is an active site and they do want sell merchandise,
If it helps, the site is www.shopcousinearl.com.
I can confirm the issue from @davidtleblanc on product pages too.
As a temporary workaround this will let you use lazy loading in every page of the website except the products one:
function is_lazyload_activated() {
$condition = is_product();
if ( $condition ) return false;
return true;
}
add_filter( 'lazyload_is_enabled', 'is_lazyload_activated', 10, 3 );
@paulotruta
Thanks for the reply and temporary workaround.
I need to put this in my functions.php file, correct? Sorry for asking, but I am not a coder and I don't want to put this somewhere where it causes a problem.
@paulotruta
Thanks for the reply and temporary workaround.
I need to put this in my functions.php file, correct? Sorry for asking, but I am not a coder and I don't want to put this somewhere where it causes a problem.
Yes, please do so. Should work. But if not please reply here.
No worries ;)
@paulotruta
Seems to be working fine. Thanks for the help.
Got an idea (from @nosilver4u) to use a properly-sized SVG, instead of the square GIF. Seems to work a treat and forces the browser to do the same thing with the placeholder it would do with the real image.
Hi @galbaras – Do you generate the SVG in advance or on the fly? If you have some example code, I'd be interested in seeing it so that we can consider improving the implementation.
The code in question is here: https://github.com/nosilver4u/ewww-image-optimizer/blob/master/classes/class-ewwwio-lazy-load.php#L176
It does seem to require setting the height/width attributes on the image, so those need to be known (or gathered from the image filename). Without the height/width attributes, the SVGs just scale to the parent container size. Could be another way to make that happen, but that's what I've come up with so far.
@galbaras
As you say, it will be solved by using the jetpack_lazy_images_new_attributes and SVG.
We need two hook steps, because wp_get_attachment_image_attributes doesn't have the height and width parameters.
add_filter( 'wp_get_attachment_image_attributes',function ($attributes, $attachment, $size){
if ( $attachment ) {
$src = image_downsize( $attachment->ID, $size );
if ( $src ) {
$attributes['srcwidth'] = $src[1];
$attributes['srcheight'] = $src[2];
}
}
return $attributes;
},10, 3 );
add_filter( 'jetpack_lazy_images_new_attributes',function ($attributes){
if ( !empty( $attributes['srcwidth'] ) && !empty( $attributes['srcheight'] )){
$attributes['srcset'] = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ".$attributes['srcwidth']." ".$attributes['srcheight']." '%3E%3C/svg%3E";
}
return $attributes;
} );
@oginomizuho Thank you for this. I've switched to another plugin for lazy loading, so can't test this anymore, but hopefully, it will help other people.
For now, I'm closing this issue.
Most helpful comment
The code in question is here: https://github.com/nosilver4u/ewww-image-optimizer/blob/master/classes/class-ewwwio-lazy-load.php#L176
It does seem to require setting the height/width attributes on the image, so those need to be known (or gathered from the image filename). Without the height/width attributes, the SVGs just scale to the parent container size. Could be another way to make that happen, but that's what I've come up with so far.