├── README.md └── imgsupport.js /README.md: -------------------------------------------------------------------------------- 1 | # imgsupport 2 | 3 | Detecting support for AVIF, WebP, JPEG 2000, JPEG XR and SVG to supply the best image for the UA 4 | 5 | ## Install 6 | 7 | Download/fork the script to your server. 8 | 9 | Insert script before any `` tag to css file, so browser will start to download right images. 10 | 11 | ``` 12 | 13 | 14 | My Page 15 | 16 | ... 17 | 18 | ... 19 | ``` 20 | 21 | ## What this script do? 22 | 23 | Like modernizr, it injects one or a few CSS class names to the document element, e. g. ``, according to which image formats are supported by the browser: 24 | 25 | - `jxl` – if browser supports JPEG XL, then this class will be added. Currently it's Chrome and Firefox behind a flag. 26 | - `avif` – if browser supports AVIF, then this class will be added. Currently it's available on Chrome and Opera (not Edge) and in Firefox it's still behind a flag. 27 | - `webp` – it's already in all modern browsers. But be careful Safari started to support it not that long ago and it's available only in v14+ (BigSur, iOS14+). 28 | - `jp2` – browser supports JPEG 2000. It's Safari for Mac OS X and all browsers for iOS (based on iOS WebKit). 29 | - `jpx` – browser supports JPEG XR... Internet Explorer 9+ and old MS Edge till v18. 30 | - `svg` – all modern browsers, but this class is set only if none of the above formats are supported. Currently it's Firefox only. 31 | - `png` – if even SVG is not supported... fallback variant. 32 | - Additionally are added classes if the format is not supported: `notjxl`, `notavif`, `notwebp`, `notjp2`, `notjpx` and `notsvg`. 33 | 34 | ### Example results 35 | 36 | Chrome 37 | 38 | ``` 39 | 40 | ``` 41 | 42 | Safari 43 | 44 | ``` 45 | 46 | ``` 47 | 48 | Firefox 49 | 50 | ``` 51 | 52 | ``` 53 | 54 | ## Usage 55 | 56 | You can use css-cascade to specify what kind of image your browser must download: 57 | 58 | ``` 59 | .jxl .myelem { 60 | background-image: url('myimage.jxl'); 61 | } 62 | .avif.notjxl.notwebp .myelem { 63 | background-image: url('myimage.avif'); 64 | } 65 | .webp.notjxl.notavif .myelem { 66 | background-image: url('myimage.webp'); 67 | } 68 | .jpx.notavif.notwebp .myelem { 69 | background-image: url('myimage.wdp'); 70 | } 71 | .jp2.notavif.notwebp .myelem { 72 | background-image: url('myimage.jp2'); 73 | } 74 | .svg .myelem { 75 | background-image: url('myimage.svg'); 76 | } 77 | .png .myelem { 78 | background-image: url('myimage.png'); 79 | } 80 | ``` 81 | -------------------------------------------------------------------------------- /imgsupport.js: -------------------------------------------------------------------------------- 1 | (function (document) { 2 | var checkCount = 0, 3 | formatFound = false; 4 | 5 | function setHTMLClass(height, className) { 6 | checkCount++; 7 | if (height == 2) { 8 | formatFound = true; 9 | document.documentElement.className += " " + className; 10 | } else { 11 | document.documentElement.className += " not" + className; 12 | if (checkCount == 4 && !formatFound) { 13 | if ( 14 | document.implementation.hasFeature( 15 | "http://www.w3.org/TR/SVG11/feature#Image", 16 | "1.1" 17 | ) 18 | ) { 19 | document.documentElement.className += " svg"; 20 | } else { 21 | document.documentElement.className += " notsvg png"; 22 | } 23 | } 24 | } 25 | } 26 | 27 | var JXL = new Image(); 28 | JXL.onload = JXL.onerror = function () { 29 | setHTMLClass(JXL.height, "jxl"); 30 | }; 31 | JXL.src = 32 | "data:image/jxl;base64,/woIELASCAgQAFwASxLFgkWAHL0xqnCBCV0qDp901Te/5QM="; 33 | 34 | var AVIF = new Image(); 35 | AVIF.onload = AVIF.onerror = function () { 36 | setHTMLClass(AVIF.height, "avif"); 37 | }; 38 | AVIF.src = 39 | "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A="; 40 | 41 | var WebP = new Image(); 42 | WebP.onload = WebP.onerror = function () { 43 | setHTMLClass(WebP.height, "webp"); 44 | }; 45 | WebP.src = 46 | "data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA"; 47 | 48 | var JPX = new Image(); 49 | JPX.onload = JPX.onerror = function () { 50 | setHTMLClass(JPX.height, "jpx"); 51 | }; 52 | JPX.src = 53 | "data:image/vnd.ms-photo;base64,SUm8AQgAAAAFAAG8AQAQAAAASgAAAIC8BAABAAAAAQAAAIG8BAABAAAAAgAAAMC8BAABAAAAWgAAAMG8BAABAAAARgAAAAAAAAAkw91vA07+S7GFPXd2jckQV01QSE9UTwAZAMFxAAAAATAAoAAKAACgAAAQgCAIAAAEb/8AAQAAAQDCPwCAAAAAAAAAAAAAAAAAjkI/AIAAAAAAAAABIAA="; 54 | 55 | var JP2 = new Image(); 56 | JP2.onload = JP2.onerror = function () { 57 | setHTMLClass(JP2.height, "jp2"); 58 | }; 59 | JP2.src = 60 | "data:image/jp2;base64,/0//UQAyAAAAAAABAAAAAgAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAEBwEBBwEBBwEBBwEB/1IADAAAAAEAAAQEAAH/XAAEQED/ZAAlAAFDcmVhdGVkIGJ5IE9wZW5KUEVHIHZlcnNpb24gMi4wLjD/kAAKAAAAAABYAAH/UwAJAQAABAQAAf9dAAUBQED/UwAJAgAABAQAAf9dAAUCQED/UwAJAwAABAQAAf9dAAUDQED/k8+kEAGvz6QQAa/PpBABr994EAk//9k="; 61 | })( 62 | (window.sandboxApi && 63 | window.sandboxApi.parentWindow && 64 | window.sandboxApi.parentWindow.document) || 65 | document 66 | ); 67 | --------------------------------------------------------------------------------