Last active
August 6, 2025 01:57
-
-
Save jimdiroffii/e9ee83d9fb906a43f8a8ff8026d8a929 to your computer and use it in GitHub Desktop.
How to enable JPG fallback for any AVIF image on your website
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* 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); |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
HTML Alternative - Performed at build time, rather than client-side. WebP fallback is optional.