unicef / iogt

BSD 2-Clause "Simplified" License
25 stars 34 forks source link

Support <picture> tag and multiple image formats for significant file size reductions #1060

Open cbunicef opened 2 years ago

cbunicef commented 2 years ago

Here is a format comparison: https://unicefiogt.iogt.site/documents/4/image_formats_comparison.html (downloads)

In the example <picture> (supported by 95% of users globally, although not Opera Mini which will fall back to the imc src="") is used to serve progressively more accepted image formats with larger file sizes. If the browser cannot use the first option, then it will continue to the next option, falling back to the last option:

<picture>
  <source type="image/avif" srcset="https://unicefiogt.iogt.site/documents/2/Banner2.width-320.avif">
  <source type="image/webp" srcset="https://unicefiogt.iogt.site/documents/1/Banner2.width-320.webp">
  <img src="https://unicefiogt.iogt.site/documents/3/Banner2.width-320.png">
</picture>

Firefox and Chrome will display the AVIF file, while Edge will display the WebP file.

With this approach we can use AVIF (68% of users), then fall back to webp (90% of users), and finally to PNG (virtually all users).

File sizes for this example image

Banner2 width-320

PNG 19KB WebP 12KB - 37% file size reduction, no visual change AVIF 4KB - 79% file size reduction, acceptable visual change

Here are the three images taken via screenshot and saved losslessly 2022-01-25 15_37_53-Mozilla Firefox

There is no noticeable difference between PNG and WebP. In PNG vs AVIF the difference in quality is noticeable in a side-by-side comparison, but doesn't harm the readability of the image in any way.

cbunicef commented 2 years ago

https://squoosh.app/editor is a good tool for experimenting with filetypes and encoding settings.

cbunicef commented 2 years ago

https://blog.logrocket.com/how-to-format-quality-images-using-avif-squoosh-and-go-avif/ claims that when using <picture> as above, browsers that don't support the tag will still fallback to the <img> tag.

cbunicef commented 1 year ago

Here is some use of the <picture> tag that may enable the browser itself to load the proper image size based on device resolution as in #1030

https://github.com/codingjoe/django-pictures

<!-- template.html -->
{% load pictures %}
{% picture profile.picture alt="Spiderman" loading="lazy" m=6 l=4 %}

The template above will render into:

<picture>
  <source type="image/webp"
          srcset="/media/testapp/profile/image/800w.webp 800w, /media/testapp/profile/image/100w.webp 100w, /media/testapp/profile/image/200w.webp 200w, /media/testapp/profile/image/300w.webp 300w, /media/testapp/profile/image/400w.webp 400w, /media/testapp/profile/image/500w.webp 500w, /media/testapp/profile/image/600w.webp 600w, /media/testapp/profile/image/700w.webp 700w"
          sizes="(min-width: 0px) and (max-width: 991px) 100vw, (min-width: 992px) and (max-width: 1199px) 33vw, 600px">
  <img src="/media/testapp/profile/image.jpg" alt="Spiderman" width="800" height="800" loading="lazy">
</picture>

@ChrisMarsh82 @istride @sheralim012 related to our convo today

cbunicef commented 1 year ago

Doing some testing on squoosh.app, I found:

  1. Sometimes using compression formats like AVIF results in a significant loss of visual quality
  2. Sometimes using these compression formats results in a larger filesize - this is more often the case in smaller images

As an ADMINISTRATOR I would like to be able to

In the Admin Panel this could be shown in site settings

Title USE ADVANCED IMAGE FORMATS - EXPERIMENTAL Help text "IoGT is able to use advanced image formats, like WebP or AVIF, to reduce the file size of images on your site. This means users will consume less of their data packages when browsing the site, and the content will take less space on their device if they download it. Not all devices support these advanced image formats - for those devices IoGT will use standard formats like PNG or JPG. In most cases advanced image formats will reduce image file size without having a negative impact on how images look, but if you have any problems with the quality of your images you can consider disabling them here."

Check boxes to allow WebP and AVIF

sheralim012 commented 1 year ago

Currently, we have these main breakpoints in the website

Viewport Width Layouts (Column) Image Width
>= 1400 3 360/180
< 1400 & >= 768 2 360/180
< 768 & >= 360 1 360/180
< 359 1 360/180

CC: @cbunicef

cbunicef commented 1 year ago

Happy to hear there is a simpler solution that we can already use. As discussed let's make this require a feature flag to enable while we are testing.

On the question of image width at viewport widths, we could try this and see how it looks:

Viewport Width Layouts (Column) Image Width
>= 1400 3 600/300
< 1400 & >= 768 2 460/230
< 768 & >= 360 (should this be 767?) 1 460/230
< 359 1 340/190

We actually have a interesting behavior in our responsive configuration where the largest image is shown between 660-768px viewport sizes. That image is shown larger than when the viewport is 1400px.

Here are the approximate image dimensions I see when viewing at different viewport sizes:

Viewport Width Approx Image Width
>= 1000 550, consistent (~55% of viewport at 1000)
999 to 768 scaling smaller as viewport reduces
768 425 (~55% of viewport)
767 & >= 660 570, consistent (~75% of viewport at 767)
559 to 360 scaling smaller as viewport reduces
360 270 (~75% of vp)
270 to 240 scaling smaller as viewport reduces
240 144 (60% of vp)

How should we handle this? Probably it would be much better to tie our viewport categories to our CSS breakpoints, but the actual dimensions of images as shown are more complicated.

istride commented 1 year ago

Have we considered how use of <picture> would affect offline mode?

Presumably, there would be more renditions for each source image and we wouldn't know which format or size would be required, so all renditions would have to be downloaded.

cbunicef commented 1 year ago

We will look into whether we can cache images based on the current viewport when downloading for offline mode.

Once this feature is ready for testing, we will remove #1060 which has been deployed to Sandbox, and then deploy this feature for testing. That way there won't be a conflict between the two features and no flags needed.

cbunicef commented 1 year ago

Viewport Width Layouts (Column) Image Width

= 1400 3 600/300 < 1400 & >= 768 2 460/230 < 768 & >= 360 (should this be 767?) 1 460/230 < 359 1 340/190

I had accidentally kept all the half-size image widths at 180, I edited so now they reflect half of the full size for each width.