Чёткость до последнего байта: как делать веб-графику хорошо — часть 1
По-серьёзному о графике в интернете: основы форматов изображений, инструменты для оптимизации и то, как люди воспринимают веб-графику.
Мы заботливо подготовили перевод крутой статьи от наших коллег из блога Evil Martians (оригинал материала авторства Полины Гуртовой, Риты Клубочкиной и Энди Барнова ищите здесь). Статья будет полезна фронтендерам, ПМ-мам, контентщикам и вообще всем, кто имеет дело с изображениями в интернетах (возможно, даже вашей маме).
Знаете ли вы, что средняя веб-страница для десктопа в 2019 занимала 2 МБ трафика, и половина всего, что веб-сервер отправляет браузеру пользователя, — это графика? JPEG, PNG, SVG, GIF и некоторые другие аббревиатуры известны каждому, кто когда-либо создавал хоть что-либо в «цифре». Может показаться, что всё отображаемое на странице касается только фронтенд-разработки, но на самом деле понимание специфики веб-изображений важно для всех членов продуктовой группы: от тех, кто отвечает за серверную часть, до дизайнеров, менеджеров и специалистов техподдержки клиентов.
Если у вас не так много времени, чтобы читать эту длинную и извилистую статью, вот инфографика.
Технически гипертекст (текст, который ссылается на другой текст), представленный Дугласом Энгельбартом в 1968 году как основа современной веб-коммуникации, не нуждается в изображениях для передачи информации. Но реальность такова, что вниманием пользователя нужно управлять с помощью графического контента. Изображения, видео, CSS-анимация, рисованная графика Canvas API, WebGL, даже Flash — тёмная технология древних времен — все средства хороши в постоянной борьбе за удержание пользователя.
Для компьютера каждое изображение — это просто последовательность конкретных инструкций. То, как они переводятся в аппаратные пиксели, отображаемые на экране, — само по себе захватывающая история. Большинство форматов изображений, за исключением BMP (кто там
в пейнте ещё рисует?), в точности не хранит значения пикселей. Немножко математики, и данные, содержащиеся в файле, декодируются в массив значений с цветовой кодировкой. Кодировка RGB (red, green, blue) — самая очевидная для передачи цвета.
Кодировка YCbCr тоньше, поскольку учитывает работу человеческого глаза и мозга: на самом деле мы более восприимчивы к изменениям яркости, чем к изменениям цвета.
Когда мы имеем дело с векторной графикой, то особенно не задумываемся о тройных или четверных кодировках (CMYK), как в растровых форматах. Больше интересуют геометрические примитивы: линии, круги и квадраты, которые по факту являются просто кривыми Безье.
PNG, GIF, JPEG, WebP, HEIC, AVIF (для видео) — растровые форматы, SVG — векторный формат. Ниже о каждом будет поподробнее.
Исходный размер изображения ниже, полученного на профессиональную видеокамеру — 37,8 МБ. Из уважения к вашему интернет-провайдеру, его сжали его до 3,5 МБ без потери качества.
Но оптимизация самого изображения — это не первое, что стоит учитывать при работе с визуальным контентом в интернете. Для начала, оцените весь стек, стоящий за доставкой этих сочных байтов по сети к конечному пользователю. Для этого задайте себе пару вопросов:
- Загружаете ли вы все изображения одновременно или сосредотачиваетесь только на тех, которые должны отображаться в первую очередь (используете Lazy Loading)?
- Думали ли вы про HTTP/2, который поддерживает мультиплексирование (передачу нескольких потоков данных с меньшей скоростью по одному каналу) на уровне протокола?
- Вы эффективно сжимаете ваши файлы?
Запишите эти вопросы себе шпаргалочкой, а теперь — поговорим о самих изображениях.
Ваша ответственность перед пользователями в том, чтобы предоставить им изображения самого высокого качества, используя при этом минимум ресурсов: вычислительной мощности (как сервера, так и клиента), памяти компьютера и пропускной способности канала связи.
Мы будем говорить о техническом качестве изображения и не будем учитывать композицию, перспективу или цветовую гармонию. Просто представим, что у нас уже есть идеальное изображение, которое нужно разместить в интернете самым оптимальным способом.
Качество изображения — степень, в которой полученное изображение отличается от идеального. И под качеством имеется в виду следующее:
Как фронтенд-разработчик, верстающий макет в HTML и CSS, или как дизайнер, создающий этот макет, вы решаете одну и ту же проблему: иллюстрируете некоторую концепцию для ваших пользователей с помощью изображений. Поэтому они имеют значение ещё до того, как вы начнете применять какие-то инструменты. Например:
На первой картинке изображение — ключевой контент: мы ожидаем, что пользователь потратит некоторое время на его просмотр, поэтому нам нужно максимально возможное качество. На второй картинке текст важнее. Картинка там для антуража, поэтому её можно сжать по-максимуму, и никто не заметит.
На третьем изображении — интерактивный элемент, где и текст, и изображение одинаково важны, поскольку они требуют действий пользователя. Такие элементы должны быть масштабируемыми, «многоразовыми» и занимать как можно меньше места, поэтому имеет смысл отказаться от растра в пользу вектора.
Другой критический фактор — человеческое восприятие. Яркость и контрастность важнее цвета, поэтому на нём можно сэкономить (и, опять же, никто не заметит).
Также следует помнить, что разные экраны и разные браузеры отображают графику немного по-разному. Иногда уловить это почти невозможно (особенно, если у вас нет экрана Retina), а учитывать — стоит:
Что такое пиксель, в конце концов? Сейчас даже малыш, который некоторое время смотрел «Свинку Пеппу» на родительском телефоне, вероятно, имеет некоторое представление об этом. Однако всё не то, чем кажется.
Когда мы говорим «пиксель», то на самом деле имеем в виду одну из, по крайней мере, трех совершенно разных вещей:
- точку в аппаратном смысле,
- точку в смысле CSS,
- точку в смысле «данных изображения».
Самый хитрый из них — это так называемый пиксель CSS. Его описывают как единицу длины, которая приблизительно равна ширине или высоте одной точки, которую человеческий глаз может комфортно видеть без напряжения.
Когда вы читаете текст на своем телефоне, вы держите экран на определенном расстоянии от глаз, но когда вы смотрите на экран компьютера, вы стараетесь отодвинуться подальше, чтобы читать было удобно. Чем больше расстояние между сетчаткой и экраном, тем больше будет размер «пикселя CSS».
Не вдаваясь в подробности, мы можем просто помнить, что «физический размер» пикселя CSS — это неизменное значение в миллиметрах, своё для каждого типа экрана. На экранах Apple Retina (iPhone, iPad, Mac) это значение варьируется от 0,11 до 0,23 мм. Даже не спрашивайте нас о форме пикселя (это сложный вопрос!), просто помните — используется одно значение, а не набор чисел.
Пиксель CSS также не совпадает с аппаратным пикселем — тот является минимальным размером точки в соответствии с физическими характеристиками конкретного экрана.
Теперь мы можем наконец поговорить о device pixel ratio (DPR) — соотношении пикселей устройства. Понимание DPR чрезвычайно важно, если вы хотите, чтобы ваши изображения выглядели одинаково хорошо на всех устройствах.
Вы можете открыть вкладку DevTools в любом браузере (нажмите F12), который вы используете прямо сейчас, и набрать devicePixelRatio, чтобы узнать DPR вашего текущего экрана. При этом, если перетащить окно на другой экран (например, на внешний дисплей) — значение обновится. Оно рассчитывается по формуле:
devicePixelRatio = размер пикселя CSS / размер аппаратного пикселя
Возьмем изображение с шириной 1000 пикселей и высотой 1000 пикселей.
Поместим его на странице:
<img src=»https://vc.ru/design/cake.jpg» style=»width: 1000px;»>
Установив width равным 1000px, вы говорите браузеру отображать 1000*1000 = 1 млн пикселей CSS. Если DPR (соотношение пикселей вашего устройства) равно единице (экран — не Retina), то задействуется 1000 * 1 * 1000 * 1 = 1 млн аппаратных пикселей.
Один аппаратный пиксель отвечает за один пиксель «изображения», как и должно быть интуитивно.
Но что, если у вас Retina, и DPR=2? Теперь ваше изображение отображается с помощью 1000 * 2 * 1000 * 2 = 4 млн аппаратных пикселей. Это означает, что один пиксель вашего изображения отображается четырьмя аппаратными пикселями. Иными словами, изображение масштабируется: каждый пиксель его данных «растягивается» для отображения на экране.
Как мы выяснили, размеры изображения иногда не соответствуют аппаратному обеспечению один к одному. А поскольку браузеры не могут определить содержание растрового изображения, они используют универсальные алгоритмы (математика!), чтобы подгадать лучшую стратегию изменения размера. И, как вы можете догадаться, они не всегда угадывают правильно.
Вы можете управлять этим процессом с помощью CSS-свойства image-rendering (отображение изображения). Оно помогает задать стратегию, но вы по-прежнему не можете контролировать конкретный алгоритм, выбранный браузером.
При масштабировании области 4px до 16px в браузере доступно только четыре пикселя изображения, остальные 12 необходимо угадать. Размытые края и другие артефакты — результат такого «угадывания» или интерполяции, выполняемой алгоритмом изменения размера.
Ваша цель в том, чтобы избежать вот такого масштабирования любым способом:
- Постарайтесь понять контекст изображения и установить приемлемое качество.
- Измените размер оригинальной картинки на max_size_of_your_container * DPR.
- Подготовьте несколько версий изображений для большинства распространенных DPR (равному 1, 2 и даже 3).
- Учтите это в вашей разметке:
SVG — это масштабируемая векторная графика. Так что по определению SVG-изображения не боятся масштабирования. Почему?
Взглянем поближе на анатомию файла SVG. Во-первых, содержимое написано в виде простого текста, который читается человеком и подозрительно напоминает старый-добрый XML.
Ниже — печенька, созданная при помощи простых геометрических фигур, и экспортированная в виде svg-файла:
<svg xmlns=»http://www.w3.org/2000/svg» width=»200″ height=»120″ viewBox=»0 0 200 120″> <g fill=»none»> <ellipse cx=»100″ cy=»60″ fill https://vc.ru/tag/FDC970″>#FDC970″ rx=»100″ ry=»60″/> <path fill https://vc.ru/tag/794545″>#794545″ d=»M69.5433628,33.5480878 C65.8626549,33.5480878 61.7766372,31.1161129 58.1720354,32.2999373 C56.2746903,32.9232602 56.3815929,38.2702194 60.5900885,38.6347335 C65.4106195,39.0530408 69.8828319,39.0225705 69.3709735,33.1215047 C69.3550443,32.9383072 69.0442478,32.9992476 68.881062,32.9383072 M122.896283,19.855674 C118.705133,19.4005016 114.333451,17.1182445 110.322832,18.4897806 C108.631504,19.0679624 108.557522,23.9431975 110.322832,24.1549843 L110.835398,24.7019436 C113.283894,24.9953605 115.762124,25.3203762 118.217699,25.1021944 C121.980531,24.7681505 123.187611,20.541442 119.776283,18.861442 M153.981593,50.2878997 C152.356106,49.1322884 150.801062,47.8563009 149.105841,46.8206897 C143.614159,43.4659561 139.981239,46.0728527 142.624779,53.3021944 C142.882478,54.0071473 143.838938,54.2219436 144.547965,54.2862696 C146.88177,54.499185 149.286726,54.6590596 151.573097,54.1188715 C152.198584,53.9710345 152.378407,51.1380564 152.378407,48.2467712 M90.3642478,74.3676489 C90.1281416,74.2999373 82.6669027,71.6516614 80.7334513,72.3396865 C79.4789381,72.7862069 76.300177,74.2623197 77.5178761,74.8126646 L77.1681416,78.876489 C84.1083186,82.0122884 88.0523894,79.6845141 87.441062,74.061442 M41.1472566,60.9460815 C34.3621239,61.3455799 42.7111504,61.193605 35.5578761,60.1429467 C32.7461947,59.729906 25.1047788,62.6068966 30.1058407,66.3366771 C36.7384071,71.2830094 41.4778761,66.7895925 40.3543363,60.5902194 M141.784425,93.0744828 C135.735221,93.0744828 143.533451,93.3603762 131.213451,89.6674608 C127.678938,88.6081505 125.312566,93.9363009 127.677168,96.1651411 C130.754336,99.0647022 140.590442,98.4154232 140.590442,93.0221944 M113.093097,50.5941066 C110.309381,50.4473981 107.51823,49.9011912 104.740885,50.1547335 C103.281416,50.2878997 102.962832,56.4951724 105.088142,56.8611912 C108.850973,57.5097179 119.12708,58.2022571 112.47292,49.9373041″/> </g> </svg>
Пока её нельзя увидеть. Вместо этого — набор тегов:
- <svg> — это контейнер для нашей картинки,
- <g> — единица композиции (на самом деле этот тег бесполезен в примере кода выше, он только для демонстрации),
- <ellipse>, <path> — геометрические примитивы. <path> — самая универсальная форма, которую можно использовать для всех других фигур (круги, треугольники, сложные кривые).
Внешний вид фигуры определяется атрибутами. В нашем примере rx, d, cx, и другие подобные атрибуты отвечают за размер и положение. Это координаты, но не в системе координат экрана — они рассчитываются относительно параметра viewBox у SVG-изображения. В нашем случае:
Это значит, что изображение имеет отступ в 0 пикселей слева и 0 пикселей сверху, ширину 200 пикселей и высоту 120 пикселей. Это размер и расположение области просмотра, в которой находится наше изображение. Наш SVG также имеет width- и height-атрибуты — они определяют реальный размер самого изображения. В нашем случае это будет 200×120 CSS-пикселей (картинка 1).
Удалим width- и height-атрибуты. Теперь размер нашего изображения определяется размером окна браузера (картинка 2). Другой способ установить размер для изображения — задать width и/или height в CSS. Например:
<svg xmlns=»http://www.w3.org/2000/svg» viewBox=»0 0 200 120″ style=»width: 90px» >
Теперь размер изображения составляет 20% от высоты окна браузера (картинка 3). Но подождите, почему наше печенье расположено по центру? Причина — еще один атрибут, который называется preserveAspectRatio. Его значение по умолчанию — xMidYMid meet. Это значит: сохранить исходные пропорции изображения, сохранить содержимое текущего viewBox видимым, масштабировать изображение как можно больше, центрировать результат как по вертикали, так и по горизонтали. Но если поиграть с его значениями, получится три разных результата — картинки 4−6.
А если нам нужна только половинка печенья, можно просто уменьшить ширину viewBox (картинка 6):
<svg xmlns=»http://www.w3.org/2000/svg» viewBox=»0 0 100 120″ preserveAspectRatio=»xMinYMin meet» style=»width: 90px»>
Используя атрибуты viewBox и preserveAspectRatio вместе, можно масштабировать изображения миллионами способов.
Помимо тегов, кривых и координат, SVG скрывает ещё некоторые сюрпризы. Во-первых, вы можете поместить растровые изображения внутрь. Этот прием полезен, если нужно добавить интерактивность к другому растровому изображению или как-то пометить его. Поэтому всегда проверяйте, а действительно ли SVG-изображение, с которым вы имеете дело, векторное.
Во-вторых, мы можем анимировать пафы (<path>) внутри SVG-изображения, и сделать само изображение анимированным.
Наконец, SVG-файлы могут быть опасны. Ничто не мешает кому-то поместить тег <script> и немного JavaScript в синтаксис XML. А браузер запустит этот код. Так что соблюдайте осторожность при работе с SVG из ненадежных источников и тщательно проверяйте, что там внутри.
Ну ок, SVG-изображения имеют суперспособности. Но должны ли мы всегда использовать их для простой графики? Нет! Использование SVG дает нам файл с изображением печеньки в 26 КБ, в то время как растровый WebP (подробнее о нем позже) того же изображения умещается в 16 КБ. И если нет никакой разницы, зачем платить больше?
Вы можете работать с SVG — создавать и редактировать его — прямо в консоли браузера. Но удобнее и профессиональнее заняться этим в редакторе векторных изображений. Например, в Boxy SVG с полным набором опций для работы с векторной графикой, а также встроенным редактором кода, если очень хочется поковыряться.
А теперь пришло время оптимизировать SVG-изображение с помощью svgo. Благодаря этому можно получить SVG-файл в 13 Кб вместо растрового файла формата WebP в 16 Кб. Вектор снова выиграл!
Поскольку изображения SVG — это просто текстовые файлы, они очень хорошо сжимаются. Мы ещё раз повторим: «Идеального формата не существует», но вы можете выбрать подходящий формат для вашей задачи и применить столько оптимизаций, сколько захотите.
На самом интересном месте останавливаемся — впереди вторая часть материала, в которой подробно расскажем о сжатии изображений, особенностях растровых форматов и о том, как их использовать в интернете.
what exactly is device pixel ratio?
this is mentioned every article about mobile web, but nowhere I can found an explanation of what exactly does this attribute measure.
Can anyone please elaborate what does queries like this check?
![]()
5 Answers 5
Short answer
The device pixel ratio is the ratio between physical pixels and logical pixels. For instance, the iPhone 4 and iPhone 4S report a device pixel ratio of 2, because the physical linear resolution is double the logical linear resolution.
- Physical resolution: 960 x 640
- Logical resolution: 480 x 320
Where alt=»res_p» />is the physical linear resolution, and alt=»res_l» />is the logical linear resolution.
Other devices report different device pixel ratios, including non-integer ones. For example, the Nokia Lumia 1020 reports 1.6667, the Samsumg Galaxy S4 reports 3, and the Apple iPhone 6 Plus reports 2.46 (source: dpilove). But this does not change anything in principle, as you should never design for any one specific device.
Discussion
The CSS "pixel" is not even defined as "one picture element on some screen", but rather there is a reference pixel, which is a non-linear angular measurement of alt=»0.0213°» />viewing angle. This is approximately alt=»1/96″ />of an inch at arm’s length. Source: CSS Absolute Lengths
This has lots of implications when it comes to web design, such as preparing high-definition image resources and carefully applying different images at different device pixel ratios. You wouldn’t want to force a low-end device to download a very high resolution image, only to downscale it locally. You also don’t want high-end devices to upscale low resolution images for a blurry user experience.
If you are stuck with bitmap images, to accommodate for many different device pixel ratios, you should use CSS Media Queries or the HTML picture Element to provide different sets of resources for different groups of devices. Combine this with nice tricks like background-size: cover or explicitly set the background-size to percentage values.
Example
This way, each device type only loads the correct image resource. Also keep in mind that the px unit in CSS always operates on logical pixels.
A case for vector graphics
As more and more device types appear, it gets trickier to provide all of them with adequate bitmap resources. In CSS, media queries is currently the only way, and in HTML5, the picture element lets you use different sources for different media queries, but the support is still not 100 % since most web developers still have to support IE11 for a while more (source: caniuse).
If you need crisp images for icons, line-art, design elements that are not photos, you need to start thinking about SVG, which scales beautifully to all resolutions.
Что определяет коэффициент dpr
The viewport of a device is the size of the screen area. This doesn’t include the space the browser window takes up with its menu, bookmarks etc.
Different devices have different viewport sizes. Laptops and monitors have larger viewports than smartphones do.
A website will display on the viewport of the device. This is where HTML and CSS code is displayed.
Web developers use CSS to style and position elements. There are many units they can choose from. One of these units is called the CSS pixel, or px .
Each viewport is some number of CSS pixels wide and high. A smartphone viewpoint might be 320 x 568 CSS pixels. A larger smartphoen might have a viewport of 360 x 640 CSS pixels. A laptop viewport will be much bigger.
The screen of each device is made up of physical square pixels. This pixel is different from a CSS pixel.
There isn’t a one-to-one mapping between CSS pixels and device pixels. Some devices use four smaller pixels to one CSS pixel, arranged in a 2×2 grid. Some use one, and some use nine (3×3 grid). There can even be a fractional ratio between the two, like 1.5 or 2.25.
The number of device pixels that make up a CSS pixel in one direction is its Device Pixel Ratio (DPR). You can interpret this as the width (or height) of the grid of device pixels that fit inside one CSS pixel.
Every device has a different DPR. Higher resolution devices have a higher DPR. These devices can see sharper images because they devote more screen pixels to each CSS pixels. This means nuances in the image are better represented.
As a developer, it makes sense that you want to know the DPR of each device that views your webpage. If the device has a high DPR, you can serve it a big, high resolution image. If the device has a low DPR, you can serve it a smaller image.
You wouldn’t serve a high resolution image to a device with low DPR. It’d be wasted kilobytes because the screen can’t render all the detail properly.
Interpreting DPR
DPR applies in two situations: for a device, and for an image. This can be confusing.
Let’s stop and think: what is DPR really measuring?
- For a device: the ratio of how many device pixels fit into each CSS pixel
- For an image: the ratio of how many image pixels fit into each CSS pixel
Looks like there’s a one-to-one mapping between device pixels and image pixels. They’re measuring the same thing in both cases.
How do I choose what image to serve?
You use srcset . Look at this code:
This gives the browser three images to choose between. It suggests to use hd.jpg for devices with a DPR close to 2, because that image has 2x next to it. For devices with DPR around 1.5, sd.jpg will be suggested. The backup image is base.jpg and is suggested for devices with DPR around 1.
How do I know what multiple of x to use?
Notice above that somebody has written in 1.5x and 2x next to the different images. It would help to know how to choose this number for an image.
Your multiple depends on
- the viewport size (in CSS pixels, or px )
- the DPR of the device
Say you have a viewport that is 600 px wide, and you have the following images to use:
- orig.jpg with width of 600 (or 600w )
- wider.jpg with width of 1200 ( 1200w )
- widest.jpg with width of 2000 ( 2000w )
The DPR is the ratio of the picture width to the viewport width. It’s calcuated like this: (picture width) / (viewport width)
- orig.jpg : DPR = 600 ⁄600 = 1
- wider.jpg : DPR = 1200 ⁄600 = 2
- widest.jpg : DPR = 2000 ⁄600 = 3.33
So you would put 1x next to orig.jpg , 2x next to wider.jpg , and 3.33x next to widest.jpg .
I’m lost.
Here’s how I understand it.
Firstly, higher resolution devices have more pixels available to display the image.
Let’s say there were two devices that were 4 inches wide. Device 1 can fit 2000 pixels in that space, and device 2 can only fit 1000.
Device 1 is 2000 pixels wide, so it could display the image with width 2000w perfectly. But device 2 is 1000 pixels wide, so it can’t display this image perfectly. It would have to “average out” the colour values of some pixels. There’s no point serving this device with the 2000w image: it’s just unnecessary data downloading. You’d give it a smaller image.
Device 2 would even struggle with the image with width 1200w . It would still have to average out some pixels. But it’s a lot better than the 2000w image, and a lot smaller too.
Remember, the CSS pixel is just a unit of measurement, like pt , or mm , or in . It doesn’t correspond to any physical pixels. This means that even if a viewport is 600px wide, it doesn’t mean the image is represented by 600 physical pixels on the device. Neither is the scaled down to 600 pixels and then scaled back up. The px unit is just a unit of length.
Device Pixel Ratio
The Internet has come a long way from its humble origins, and so have devices. Modern web design needs to be able to render pages on all sorts of different display sizes, from ultrawide monitors, TVs, cell phones, and everything in between. To do this, UI/UX designers must keep a specific measurement in mind: device pixel ratio.
What is Device Pixel Ratio?
Device Pixel Ratio (DPR) is the ratio between the physical pixel density of a device and its logical pixel density. The physical pixels can be seen on your screen, while logical pixels measure how many can fit into each inch or cm (depending on your settings).
DPR is calculated as DPR = Physical Pixels / Logical Pixels
Why Does DPR matter?
Before you start designing and building your website, it’s important to know what device pixel ratio the end user will be viewing it on. The device pixel ratio is a measure of how many physical pixels there are in a virtual inch of space on that device.
Normally, web developers use HTML and CSS to position elements on a page, using CSS’s measurement of pixels for exact placement. However, a CSS pixel doesn’t completely line up with all devices – there are too many different screen sizes to keep up with!
For example, if we have an iPhone 6 with a resolution of 1334 x 750 (375dpi), then this means that there are:
- 1334/750 = 1.6 physical pixels per virtual inch (PPI). In other words, each “pixel” on this screen is 16 x 16 physical units wide by 16 x 16 physical units tall – or 3×3 square blocks total!
This means that if we want something that’s 50px wide on our website design when viewed at 100% zoom level (1x), then its width should be 50 / 3 = 16px for optimal legibility across all devices with different PPIs – including desktop computers!
How Can I Use Device Pixel Ratio in My Design Process?
You can use device pixel ratio to design your website. By using the right size image for the right device, you can ensure that it looks good on all devices. You also have to make sure that your media queries change the layout and CSS changes the font size or background color of elements in different breakpoints.
You can also use Cloudinary to help your site dynamically set DPR for images on your site with a dpr_auto parameter allowing you to set images at different resolutions as needed across your pages. Don’t have a Cloudinary account? Get started today, it’s free!