Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add low quality image placeholders #19

Open
adamsilverstein opened this issue Nov 29, 2021 · 23 comments · May be fixed by #282
Open

Add low quality image placeholders #19

adamsilverstein opened this issue Nov 29, 2021 · 23 comments · May be fixed by #282
Assignees
Labels
[Focus] Images [Type] Feature

Comments

@adamsilverstein
Copy link
Member

@adamsilverstein adamsilverstein commented Nov 29, 2021

The LQIP approach, popularized by Medium, uses a very small placeholder image to enable a quicker initial page load. The idea is the placeholder gives the user a sense of the image shapes and color while consuming minimal bytes. The hires image then replaces the placeholder later in the page load cycle.

The approach may help with perceived performance, although in general more bytes will be consumed overall - the extra image, plus the JavaScript to make the placeholder work. This approach deserves more research and might remain plugin territory.

previously: adamsilverstein/modern-images-wp#19

@adamsilverstein adamsilverstein added [Type] Feature [Focus] Images labels Nov 29, 2021
@adamsilverstein adamsilverstein added this to Triage in [Focus] Images Nov 29, 2021
@mitogh
Copy link
Member

@mitogh mitogh commented Jan 7, 2022

One thing to consider can be the Blurhash algorithm:

Where the hash for the image can be stored as part of the meta of the image.

@westonruter
Copy link
Member

@westonruter westonruter commented Jan 10, 2022

The Node.js AMP Optimizer has support for blurry image placeholders. Here's the implementation: https://github.com/ampproject/amp-toolbox/blob/main/packages/optimizer/lib/transformers/AddBlurryImagePlaceholders.js

@dainemawer
Copy link
Contributor

@dainemawer dainemawer commented Jan 20, 2022

The LQIP is quite a common pattern across the web now. I've worked on a few projects using https://github.com/aFarkas/lazysizes which also implements this paradigm.

One way of handling the low quality image, in order to save a server request is to encode it:
data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==

This means that theres no request to the placeholder image and the browser can carry on its business without worrying about connectivity or download issues. Im sure that may increase the byte size of the final HTML resource, but if sites are using gzip or brotli I think this could be trivial.

@spacedmonkey
Copy link
Member

@spacedmonkey spacedmonkey commented Jan 20, 2022

I have implemented blurhash for the web stories plugin. I really liked it. I would be willing to work on this as a feature plugin.

@adamsilverstein
Copy link
Member Author

@adamsilverstein adamsilverstein commented Jan 31, 2022

I have implemented blurhash for the web stories plugin. I really liked it. I would be willing to work on this as a feature plugin.

That looks promising, can the blurhash approach use the base64 version of the placeholder mentioned above?

@dainemawer
Copy link
Contributor

@dainemawer dainemawer commented Feb 1, 2022

Did a bit of research on this @adamsilverstein - looks like its faster to run with blurhash as opposed to implementing a base64 image - so maybe we just run with blurhash ?

@mitogh
Copy link
Member

@mitogh mitogh commented Feb 1, 2022

Adding some additional ideas here in case we want to explore different alternatives:

  • Create a smaller image 1x1
  • Create a smaller image 10x10
  • Store and save the predominant image color as part of the meta and use that as background to fill the container as the image loads.

@eugene-manuilov
Copy link
Contributor

@eugene-manuilov eugene-manuilov commented Feb 1, 2022

One thing that we should remember is that images are indexed by search engines and one of the techniques to drive traffic to the site. If we replace images with placeholders, then this may cause images not being indexed by search engines and thus negatively affect the organic traffic for some sites.

@eugene-manuilov
Copy link
Contributor

@eugene-manuilov eugene-manuilov commented Feb 1, 2022

JPEG has progressive compression that allows to achieve similar results: https://medium.com/hd-pro/jpeg-formats-progressive-vs-baseline-73b3938c2339#e3aa

Not sure how feasible it is to implement in our plugin.

@adamsilverstein
Copy link
Member Author

@adamsilverstein adamsilverstein commented Feb 1, 2022

JPEG has progressive compression that allows to achieve similar results: medium.com/hd-pro/jpeg-formats-progressive-vs-baseline-73b3938c2339#e3aa

Possibly we could take advantage of this with custom Image classes, we need to look into support in libgd and imagick. This wouldn't help with WebP images.

@adamsilverstein
Copy link
Member Author

@adamsilverstein adamsilverstein commented Feb 1, 2022

One thing that we should remember is that images are indexed by search engines and one of the techniques to drive traffic to the site. If we replace images with placeholders, then this may cause images not being indexed by search engines and thus negatively affect the organic traffic for some sites.

Good point that bears more investigation. Can the image(s) be listed in a meta tag to avoid that (ie og:image)?

My other concern about this change overall is how it might negatively impact the largest contentful paint measurement, how much of a hit will that take for this "perceived" performance boost, and is that acceptable?

@pbearne
Copy link

@pbearne pbearne commented Feb 4, 2022

I have looked at this a bit and a bit of code that works
the approach I took was to add a background image to the img tag and removed the background on image load (for transparent images)
I created the image using blurhash and stored the hash as image meta and then created the base64 on the render
It might be better to store the base64 in DB to save having to recreate it each time but this would take more space
I hacked some proof on concept code here https://github.com/pbearne/blurhash/blob/main/blurhash.php

onload="this.style.removeProperty('background');" style="background-size: cover; background-image: url(data:image/png;base64,iVBORw0KGgoAA......ORK5C=)

I need to add a filter to the media.php in core

$filtered_image = apply_filters( 'wp_img_tag_add_adjust', $filtered_image, $context, $attachment_id );

What I like about adding the image server-side is that don't have to wait for JS to render it but the downside is more data on the wire and isn't removed if no-JS (but we could handle that with CSS maybe)

Would this approach work?

I suspect that we will need a new filter for any approach we take to allow us to add elements to the img tags similar to this comint
xwp/wordpress-develop@2efb39b

@eclarke1 eclarke1 added the Needs Discussion label Feb 7, 2022
@eclarke1 eclarke1 moved this from Backlog to To do in [Focus] Images Feb 7, 2022
@adamsilverstein
Copy link
Member Author

@adamsilverstein adamsilverstein commented Feb 9, 2022

@pbearne Very interesting, I was wondering about using the background - clever!

I need to add a filter to the media.php in core

Can you point specifically to where (or is there a ticket to add)? Could you try using wp_get_attachment_image filter for now? That might be sufficient for the plugin.

Have you tested how this approach affects performance metrics?

@adamsilverstein
Copy link
Member Author

@adamsilverstein adamsilverstein commented Feb 9, 2022

JPEG has progressive compression that allows to achieve similar results: medium.com/hd-pro/jpeg-formats-progressive-vs-baseline-73b3938c2339#e3aa

@eugene-manuilov Good point, this is a great feature of jpegs.

When researching I found that LCP doesn't take progressive images into account currently (see w3c/largest-contentful-paint#71) so I'm curious how any approach would affect both perceived and measured performance.

@pbearne
Copy link

@pbearne pbearne commented Feb 10, 2022

@adamsilverstein

Can you point specifically to where (or is there a ticket to add)? Could you try using wp_get_attachment_image filter for now? That might be sufficient for the plugin.

here is the filter I was looking at adding xwp/wordpress-develop@2efb39b
I will look at the wp_get_attachment_image filter and see if I can use that instead

Have you tested how this approach affects performance metrics?

We are looking at the metrics it does add to the content on the wire so it may well be better to use JS to convert the blurhash into the background image

@pbearne
Copy link

@pbearne pbearne commented Feb 10, 2022

@adamsilverstein I have a working(ish) plugin https://github.com/pbearne/blurhash

@Stevemoretz
Copy link

@Stevemoretz Stevemoretz commented Feb 20, 2022

@adamsilverstein I have a working(ish) plugin https://github.com/pbearne/blurhash

Was looking for this all over!

@pbearne
Copy link

@pbearne pbearne commented Mar 29, 2022

@pbearne pbearne linked a pull request Apr 5, 2022 that will close this issue
3 tasks
@pbearne
Copy link

@pbearne pbearne commented Apr 5, 2022

Screen.Recording.2022-04-05.at.13.10.43.mov

video of it working

@eclarke1 eclarke1 moved this from To do to In progress in [Focus] Images Apr 6, 2022
@adamsilverstein
Copy link
Member Author

@adamsilverstein adamsilverstein commented Apr 8, 2022

interesting related ticket shared by Joy in slack: w3c/largest-contentful-paint#68 (comment)

@adamsilverstein
Copy link
Member Author

@adamsilverstein adamsilverstein commented Apr 12, 2022

@pbearne - #282 is a core patch right? Have you been able to implement this in the performance lab plugin (and if so, what is the PR for that)?

@erikyo
Copy link

@erikyo erikyo commented Apr 12, 2022

original conversation on slack

As low-res image you can use the preview contained in the exif data of the jpg, a method to get that image is to use the function exif-thumbnail (php exif module needed).
To mention, it is possible for an image to not have a preview (not all have it, especially if they were stripped of metadata before being uploaded) so better to use it in combination with other methods.

@pbearne
Copy link

@pbearne pbearne commented Apr 14, 2022

this also allows us to color the drop shadow
box-shadow: var(--dominant-color) 0px 54px 55px;
or create a border
border: solid var(--dominant-color);

@felixarntz felixarntz added this to the First release after 1.0.0 milestone Apr 15, 2022
@eclarke1 eclarke1 added Needs Review and removed Needs Discussion labels Apr 19, 2022
@eclarke1 eclarke1 moved this from In progress to Review in [Focus] Images Apr 19, 2022
@eclarke1 eclarke1 removed the Needs Review label Apr 26, 2022
@eclarke1 eclarke1 moved this from Review to In progress in [Focus] Images Apr 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Focus] Images [Type] Feature
Projects
[Focus] Images
In progress
Development

Successfully merging a pull request may close this issue.