Формат WebP - современный и прогрессивный формат изображений. За счёт его использования, можно здорово сократить время загрузки любой страницы сайта, особенно, если изображений на сайте много. Без какой-либо видимой глазу потери качества можно уменьшить размер картинок на 50%. Также, WebP поддерживает сжатие с потерями без, а ещё анимацию и частичную прозрачность.
Конвертировать в формат WebP можно как вручную, так и автоматически (на сервере). Если Вы знакомы с Node.js и Gulp (а любой уважающий себя веб-разработчик с ними прекрасно знаком), то в конвертации нам поможет imagemin, совместно с imagemin-webp. Функции для конвертации стандартны, нет смысла описывать их здесь, да и наша статья не про это. Здесь я просто хочу донести до Вас, что данный формат очень крут и его использования не нужно бояться, даже несмотря на тот прискорбный факт, что его не поддерживает IE и Safari (информация от caniuse.com). Если всё же Вы захотите углубиться в вопрос автоматизированной конвертации в WebP, то обратите внимание на Cwebp (самый лучший на мой взгляд инструмент под Node.js).
Стандартно (для поддерживаемых браузеров), WebP используется следующим образом:
<picture> <source type="image/webp" srcset="путь_на_файл.webp"> <source type="image/jpeg" srcset="путь_на_файл.jpg"> <img src="путь_на_файл.jpg" alt=""> </picture>
Элемент <picture> вместе с несколькими <source> используется для совместимости. Браузер смотрит сверху вниз и выбирает тот первый элемент, который он поддерживает. В случае, если он не поддерживает в том числе и элемент <picture> (т.е. используется html менее 5-й версии), тогда он всё это пропускает и просто берёт элемент <img>, который идёт последним в нашей связке.
Для ручной конвертации в WebP есть много сервисов (Google Вам в помощь). Для разовой конвертации лично я использую webp-converter.com. Он лёгкий, быстрый и имеет возможность указать качество сжатия.
Итак, мы подошли к самому главному вопросу:
Как использовать WebP на сайте в тех браузерах, которые его не поддерживают?
Например, в IE11 (который всё ещё активно используется). Или, что ещё более печально, в Safari. Я пользуюсь (и Вам советую) сервисом modernizr.com (привожу ссылку сразу на выбранный полифилл). Здесь можно получить полифилл на все случаи жизни под все известные проблемы совместимости. Причём, эти полифиллы просты в использовании и минимальны в плане количества кода. Вот полифилл, определяющий поддержку WebP:
<script> !function(e,n,A){function o(e,n){return typeof e===n}function t(){var e,n,A,t,a,i,l;for(var f in r)if(r.hasOwnProperty(f)){if(e=[],n=r[f],n.name&&(e.push(n.name.toLowerCase()),n.options&&n.options.aliases&&n.options.aliases.length))for(A=0;A<n.options.aliases.length;A++)e.push(n.options.aliases[A].toLowerCase());for(t=o(n.fn,"function")?n.fn():n.fn,a=0;a<e.length;a++)i=e[a],l=i.split("."),1===l.length?Modernizr[l[0]]=t:(!Modernizr[l[0]]||Modernizr[l[0]]instanceof Boolean||(Modernizr[l[0]]=new Boolean(Modernizr[l[0]])),Modernizr[l[0]][l[1]]=t),s.push((t?"":"no-")+l.join("-"))}}function a(e){var n=u.className,A=Modernizr._config.classPrefix||"";if(c&&(n=n.baseVal),Modernizr._config.enableJSClass){var o=new RegExp("(^|\\s)"+A+"no-js(\\s|$)");n=n.replace(o,"$1"+A+"js$2")}Modernizr._config.enableClasses&&(n+=" "+A+e.join(" "+A),c?u.className.baseVal=n:u.className=n)}function i(e,n){if("object"==typeof e)for(var A in e)f(e,A)&&i(A,e[A]);else{e=e.toLowerCase();var o=e.split("."),t=Modernizr[o[0]];if(2==o.length&&(t=t[o[1]]),"undefined"!=typeof t)return Modernizr;n="function"==typeof n?n():n,1==o.length?Modernizr[o[0]]=n:(!Modernizr[o[0]]||Modernizr[o[0]]instanceof Boolean||(Modernizr[o[0]]=new Boolean(Modernizr[o[0]])),Modernizr[o[0]][o[1]]=n),a([(n&&0!=n?"":"no-")+o.join("-")]),Modernizr._trigger(e,n)}return Modernizr}var s=[],r=[],l={_version:"3.6.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,n){var A=this;setTimeout(function(){n(A[e])},0)},addTest:function(e,n,A){r.push({name:e,fn:n,options:A})},addAsyncTest:function(e){r.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=l,Modernizr=new Modernizr;var f,u=n.documentElement,c="svg"===u.nodeName.toLowerCase();!function(){var e={}.hasOwnProperty;f=o(e,"undefined")||o(e.call,"undefined")?function(e,n){return n in e&&o(e.constructor.prototype[n],"undefined")}:function(n,A){return e.call(n,A)}}(),l._l={},l.on=function(e,n){this._l[e]||(this._l[e]=[]),this._l[e].push(n),Modernizr.hasOwnProperty(e)&&setTimeout(function(){Modernizr._trigger(e,Modernizr[e])},0)},l._trigger=function(e,n){if(this._l[e]){var A=this._l[e];setTimeout(function(){var e,o;for(e=0;e<A.length;e++)(o=A[e])(n)},0),delete this._l[e]}},Modernizr._q.push(function(){l.addTest=i}),Modernizr.addAsyncTest(function(){function e(e,n,A){function o(n){var o=n&&"load"===n.type?1==t.width:!1,a="webp"===e;i(e,a&&o?new Boolean(o):o),A&&A(n)}var t=new Image;t.onerror=o,t.onload=o,t.src=n}var n=[{uri:"data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA=",name:"webp"},{uri:"data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAABBxAR/Q9ERP8DAABWUDggGAAAADABAJ0BKgEAAQADADQlpAADcAD++/1QAA==",name:"webp.alpha"},{uri:"data:image/webp;base64,UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA",name:"webp.animation"},{uri:"data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=",name:"webp.lossless"}],A=n.shift();e(A.name,A.uri,function(A){if(A&&"load"===A.type)for(var o=0;o<n.length;o++)e(n[o].name,n[o].uri)})}),t(),a(s),delete l.addTest,delete l.addAsyncTest;for(var p=0;p<Modernizr._q.length;p++)Modernizr._q[p]();e.Modernizr=Modernizr}(window,document); </script>
Обратите внимание, как немного кода и как он прекрасен! Его вполне можно разместить в области <head>, дабы не создавать дополнительный запрос к серверу и максимально быстро определять поддержку данного формата. Некоторые из Вас сейчас скажут: "Фууу... Какой дурной тон - размещать скрипты инлайном в хеде...". На что я отвечу - наша задача моментально и ДО отображения контента определить поддержку элемента. И запихивать скрипт в общий файл со всеми библиотеками нелогично. Во-первых, общие файлы со всеми библиотеками загружаются во многих случаях в самой конце разметки, а именно перед закрывающим тегом <body>. Во-вторых, инлайном я рекомендую загружать скрипт, т.к. он небольшой по размеру и данный способ размещения не создаёт лишнего запроса к стороннему серверу, а значит, что мы экономим наше время и время наших драгоценных пользователей.
Как только полифилл отработает, у корневого элемента нашего сайта появятся классы, которые мы можем использовать для создания CSS-правил, либо для дальнейшей обработки скриптами (если мы хотим использовать файлы WebP не в качестве background-image, а в качестве изображения в разметке).
А вот и пример с использованием WebP в качестве background-image в CSS-файле:
.no-webp .elementWithBackgroundImage { background-image: url("путь_на_файл.jpg"); } .webp .elementWithBackgroundImage { background-image: url("путь_на_файл.webp"); }
Надеюсь, формат WebP поможет Вам сэкономить много-много мегабайт данных и много-много миллисекунд для Ваших пользователей!
Подписывайтесь на группу в ВКонтакте, вступайте в сообщество на Facebook, чтобы всегда быть в курсе актуальных выпусков
Web development blog!