Skip to content

Instantly share code, notes, and snippets.

@jimdiroffii
Last active August 6, 2025 01:57
Show Gist options
  • Select an option

  • Save jimdiroffii/e9ee83d9fb906a43f8a8ff8026d8a929 to your computer and use it in GitHub Desktop.

Select an option

Save jimdiroffii/e9ee83d9fb906a43f8a8ff8026d8a929 to your computer and use it in GitHub Desktop.
How to enable JPG fallback for any AVIF image on your website
/* SOURCE: https://gregbenzphotography.com/photoshop/photoshop-now-natively-supports-avif-for-50-smaller-files-than-jpg/
REVISED with corrections and error handling.
*/
function replaceAvifImagesWithPicture() {
const logToConsole = true;
if (logToConsole) console.log("replaceAvifImagesWithPicture()");
// Select all <img> elements with a .avif source that haven't been processed yet.
// We check that its parent is NOT a <picture> element.
const images = document.querySelectorAll('img[src$=".avif"]:not(picture img)');
if (logToConsole) {
console.log(`Found ${images.length} AVIF images to replace.`);
}
images.forEach(async (img) => {
const avifSrc = img.src;
if (logToConsole) {
console.log(`Replacing ${avifSrc} with <picture> element`);
}
// Create the .jpg fallback URL
const jpgSrc = avifSrc.replace(/\.avif$/i, ".jpg");
// Optional: Check if JPG fallback exists (uncomment if needed)
/*
try {
const response = await fetch(jpgSrc, { method: 'HEAD' });
if (!response.ok) {
console.warn(`JPG fallback not found: ${jpgSrc}`);
return; // Skip this image if no fallback exists
}
} catch (error) {
console.warn(`Could not verify JPG fallback: ${jpgSrc}`, error);
return;
}
*/
// Create the <picture> wrapper
const picture = document.createElement("picture");
// Create and append the AVIF source element
const sourceAvif = document.createElement("source");
sourceAvif.type = "image/avif";
sourceAvif.srcset = avifSrc;
picture.appendChild(sourceAvif);
// Create the fallback <img> element
const imgFallback = document.createElement("img");
// Copy all attributes from the original <img> to the new one
for (const attr of img.attributes) {
imgFallback.setAttribute(attr.name, attr.value);
}
// Set the src of the fallback to the JPG version
imgFallback.src = jpgSrc;
// Add error handling for the fallback image
imgFallback.onerror = function() {
console.warn(`Fallback image failed to load: ${jpgSrc}`);
// Optionally, you could set a default placeholder image here
// this.src = '/path/to/placeholder.jpg';
};
// Append the fallback <img> to the <picture> element
picture.appendChild(imgFallback);
// Replace the original <img> with the new <picture> element
img.replaceWith(picture);
});
}
// For better robustness, you might also consider a MutationObserver
// to handle images added to the page dynamically after the initial load.
document.addEventListener("DOMContentLoaded", replaceAvifImagesWithPicture);
@jimdiroffii
Copy link
Author

Please visit Greg Benz Photography for more information:

If you’d like to share AVIF now to help offer vastly faster page load times but also wish to ensure that even the ~5% of viewers who lack support still see your images, you can easily automate that. Just batch export both AVIF and JPG versions of your image using the same name, insert the AVIF normally on your site, and use the following script to have the page automatically replace all <img> elements using an AVIF with <picture> elements which use either AVIF where possible but fallback to JPG if not supported.

@jimdiroffii
Copy link
Author

HTML Alternative - Performed at build time, rather than client-side. WebP fallback is optional.

<picture>
  <!-- AVIF first -->
  <source
    type="image/avif"
    srcset="path/to/image.avif 1x, path/to/[email protected] 2x"
    sizes="(max-width: 800px) 100vw, 800px">

  <!-- WebP fallback -->
  <source
    type="image/webp"
    srcset="path/to/image.webp 1x, path/to/[email protected] 2x"
    sizes="(max-width: 800px) 100vw, 800px">

  <!-- Final JPEG fallback -->
  <img
    src="path/to/image.jpg"
    alt="Description of image"
    width="800"
    height="600"
    loading="lazy"
    decoding="async">
</picture>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment