Исправляем проблемы с CLS (Cumulative Layout Shift) 1
Оптимизация

Исправляем проблемы с CLS (Cumulative Layout Shift)

Нововведение Google, Core Web Vitals, поглотило мир SEO и веб-разработки, и многие сайты заняты оптимизацией своего Page Experience, чтобы повысить фактор ранжирования. Метрика Cumulative Layout Shift доставляет проблемы многим сайтам, поэтому давайте рассмотрим способы решения любых проблем с данной метрикой.

Cumulative Layout Shift (CLS) пытается измерить в баллах каждый сдвиг контента на странице, например когда изображение, реклама или что-то еще — появляется позже, чем основная часть страницы. Он рассчитывает оценку, основанную на том, насколько большая часть страницы неожиданно перемещается и как часто. Такие смещения контента очень раздражают, заставляя вас терять место в статье, которую вы начали читать, или, что еще хуже, заставляя вас нажать не на ту кнопку!

В этой статье я расскажу о некоторых front-end приемах для уменьшения CLS. Я не буду много говорить об измерении CLS, так как об этом много написано в других статьях. Я также не буду много говорить о механике расчета CLS: У Google есть хорошая документация по этому вопросу, а Джесс Пек в своей книге «Почти полное руководство по кумулятивному сдвигу макета» (The Almost-Complete Guide to Cumulative Layout Shift) делает достаточно глубокое погружение в эту тему. Но прежде, добавим немного в теорию, необходимую для понимания некоторых приемов.

Отличия Cumulative Layout Shift

CLS, на мой взгляд, является самым интересным из основных веб-показателей, отчасти потому, что это то, что мы никогда раньше не измеряли и не оптимизировали. Поэтому для его оптимизации часто требуются новые методы и способы мышления. Это совсем другой зверь, чем два других основных веб-показателя Core Web Vitals.

Если кратко рассмотреть два других основных веб-показателя, то Largest Contentful Paint (LCP) делает именно то, что следует из его названия, и является скорее логическим продолжением предыдущих метрик загрузки, измеряющих, насколько быстро загружается страница. Да, мы изменили способ определения пользовательского опыта загрузки страницы, чтобы смотреть на скорость загрузки наиболее релевантного контента, но по сути это повторное использование старых методов обеспечения того, чтобы контент загружался как можно быстрее. Как оптимизировать LCP для большинства веб-сайтов, по идее не должно вызывать вопросов.

Задержка после первого ввода (FID) измеряет любые задержки при взаимодействии пользователя с сайтом, и также не должна стать проблемой для большинства сайтов. Для улучшения данного параметра обычно достаточно оптимизировать (или уменьшить) JavaScript у каждого конкретного сайта. Это не значит, что решить проблемы с этими двумя метриками легко, но это достаточно хорошо изученные проблемы.

Одна из причин отличия CLS заключается в том, что он измеряется в течение всего времени жизни страницы. Две другие метрики Core Web Vitals прекращают измерения после обнаружения основного компонента на странице после загрузки (для LCP) или до первого взаимодействия (для FID). Это означает, что традиционные инструменты, такие как Lighthouse, часто не совсем корректно отражают CLS, поскольку они рассчитывают только CLS начальной загрузки. В реальности же, пользователь будет прокручивать страницу вниз и может получить большее количество контента, что в итоге может привести к большему смещению.

По сути CLS является слегка искусственной метрикой, которая рассчитывается на основе того, насколько и как часто сдвигается страница. В то время как LCP и FID измеряются в миллисекундах, CLS — это число без единиц измерения, получаемое путем сложного расчета. Необходимо стремиться, чтобы CLS была 0.1 или меньше. Все, что выше 0.25, рассматривается как «плохо».

Сдвиги, вызванные взаимодействием с пользователем, не учитываются. Это определяется как время в пределах 500 мс после определенного набора действий пользователя, исключая события курсора мыши и прокрутку. Предполагается, что пользователь, нажимающий на кнопку, может ожидать появления контента, например, раскрытия свернутого раздела.

CLS — это измерение неожиданных сдвигов. Прокрутка не должна вызывать сдвига содержимого, если страница сверстана оптимально, и точно так же наведение курсора на изображение продукта, чтобы получить, например, масштабированную картинку, не должно вызывать скачков близлежащего контента. Но, конечно, бывают исключения, и владельцам таких сайтов необходимо продумать, как на это реагировать.

CLS также постоянно совершенствуется, внося изменения и исправляя ошибки. Недавно было анонсировано крупное обновление, которое должно положительно сказаться в первую очередь на долгоживущих страницах, таких как одностраничные приложения (SPA) и страницы с бесконечной прокруткой, по мнению многих несправедливо «обделенные» в CLS. Вместо того, чтобы накапливать сдвиги за все время существования страницы для расчета оценки CLS, как это делалось до сих пор, оценка будет рассчитываться на основе наибольшего набора сдвигов в определенном временном интервале.

Это означает, что если у вас есть три значения CLS 0.05, 0.06 и 0.04, то раньше это было бы записано как 0.15 (т.е. превышение «хорошего» предела в 0.1), тогда как теперь это будет оценено как 0.06. Это по-прежнему обобщенно, в том смысле, что оценка может состоять из отдельных сдвигов в течение этого периода времени (т.е. если оценка 0.06 CLS была вызвана тремя отдельными сдвигами на 0.02), но она больше не совокупна в течение всего времени жизни страницы.

Если же вы устраните причины сдвига на 0.06, то ваш CLS будет представлен как следующий по величине сдвиг (0.05). Таким образом, система по-прежнему рассматривает все сдвиги за время существования страницы — просто она решает представить в качестве оценки CLS только самый большой из них.

После этого краткого введения в методологию CLS давайте перейдем к решениям данной проблемы! Все эти методы в основном подразумевают резервирование определенной области страницы для загрузки дополнительного контента — будь то медиа или контент с JavaScript.

Установите ширину и высоту для изображений и IFrame

Одна из самых простых вещей, которые вы можете сделать для уменьшения CLS — это установить атрибуты width и height для ваших изображений. Без них изображение будет вызывать смещение последующего содержимого, чтобы освободить место для него после загрузки:

Пример макета с заголовком и двумя абзацами, где второй абзац должен сдвинуться вниз, чтобы освободить место для изображения.

Для этого нужно просто изменить разметку изображения:

<img src="hero_image.jpg" alt="...">

на:

<img src="hero_image.jpg" alt="..."
   width="400" height="400">

Размеры изображения можно узнать, открыв DevTools и наведя курсор на элемент.

Снимок экрана Chrome Dev Tools, показывающий изображение, отображаемый размер, отображаемое соотношение сторон, внутренний размер, внутреннее соотношение сторон, размер файла и текущий источник.

Я советую использовать Intrinsic Size (это фактический размер исходника изображения), а браузер затем уменьшит их до оптимального размера, в зависимости от используемого вьюпорта.

Если у вас есть адаптивные изображения (подробную статью про изображения в WordPress можно прочитать по этой ссылке) и вы используете CSS для изменения размеров изображения (например, max-width 100% от размера экрана), то эти атрибуты могут быть использованы для расчета высоты — при условии, что вы установили в стилях ее значение в auto:

img {
  max-width: 100%;
  height: auto;
}

Сейчас это поддерживают все современные браузеры, хотя до недавнего времени все было не так оптимистично. Это также работает для элементов picture и изображений srcset (установка ширины и высоты для fallback элемента img), но пока не для изображений с различным aspect-ratio — над этим работают, а пока вам все равно следует установить ширину и высоту, поскольку любые значения будут лучше, чем 0 на 0 по умолчанию!

Также данный метод работает с изображениями, загруженными в режиме ленивой загрузки (хотя Safari пока не поддерживает ленивую загрузку по умолчанию).

Новое CSS свойство aspect-ratio

Приведенная выше техника расчета ширины и высоты для адаптивных изображений может быть распространена на другие элементы с помощью нового CSS свойства aspect-ratio, которое теперь поддерживается браузерами на базе Chromium и Firefox, а также находится в Safari Technology Preview, так что, надеюсь, оно скоро появится и в стабильной версии.

Таким образом, вы можете использовать его, например, для встроенного видео в соотношении 16:9:

video {
  max-width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
}
<video controls width="1600" height="900" poster="...">
    <source src="/media/video.webm"
            type="video/webm">
    <source src="/media/video.mp4"
            type="video/mp4">
    Sorry, your browser doesn't support embedded videos.
</video>

Интересно, что без определения свойства aspect-ratio браузеры будут игнорировать высоту адаптивных видеоэлементов и использовать соотношение сторон по умолчанию 2:1, поэтому вышеуказанный способ необходим, чтобы избежать смещения макета.

В будущем можно будет даже динамически устанавливать соотношение сторон на основе атрибутов элемента, используя aspect-ratio: attr(width) / attr(height); но, к сожалению, это пока не поддерживается.

Или же вы можете использовать aspect-ratio для элемента какого-то пользовательского элемента управления, который вы создаете, чтобы сделать его адаптивным:

#my-square-custom-control {
  max-width: 100%;
  height: auto;
  width: 500px;
  aspect-ratio: 1;
}
<div id="my-square-custom-control"></div>

В тех браузерах, которые не поддерживают aspect-ratio, можно использовать старый хак padding-bottom, но, учитывая простоту нового aspect-ratio и широкую поддержку (особенно после перехода из Safari Technical Preview в обычный Safari), трудно оправдать использование данного метода.

Chrome — единственный браузер, который передает данные CLS в Google, и он поддерживает aspect-ratio, что означает, что он решит ваши проблемы с CLS с точки зрения Core Web Vitals. Мне не нравится идея отдавать приоритет метрикам, а не пользователям, но то, что в браузерах Chromium и Firefox это есть, а в Safari, надеюсь, скоро появится, и что это прогрессивное улучшение, то я бы сказал, что мы находимся на том этапе, когда можно оставить хак padding-bottom позади и писать более чистый код.

Свободно используйте min-height

Для тех элементов, которым не нужна адаптивность, а нужна фиксированная высота, можно использовать min-height. Например, это может быть заголовок фиксированной высоты, и мы можем иметь разные заголовки для разных брэкпоинтов, используя, как обычно, медиа-запросы:

header {
  min-height: 50px;
}
@media (min-width: 600px) {
  header {
    min-height: 200px;
  }
}
<header>
 ...
</header>

Конечно, то же самое относится и к min-width для горизонтально расположенных элементов, но обычно проблемы с CLS возникают из-за высоты.

Более продвинутый метод для вставляемого контента и расширенных селекторов CSS — нацеливание на то, когда ожидаемый контент еще не был вставлен. Например, если у вас есть следующее содержимое:

<div class="container">
  <div class="main-content">...</div>
</div>

А дополнительный div вставляется с помощью JavaScript:

<div class="container">
  <div class="additional-content">.../div>
  <div class="main-content">...</div>
</div>

Тогда вы можете использовать следующий фрагмент кода, чтобы зарезервировать место для дополнительного содержимого, когда div main-content отображается изначально.

.main-content:first-child {
   margin-top: 20px; 
 }

Этот код фактически создаст смещение элемента main-content, поскольку margin считается частью этого элемента, поэтому при удалении margin он будет казаться смещенным (хотя на самом деле он не перемещается на экране). Однако, по крайней мере, содержимое под ним не будет смещено, что должно уменьшить CLS.

В качестве альтернативы можно использовать псевдоэлемент ::before для добавления отступа, чтобы избежать сдвига и для элемента main-content:

.main-content:first-child::before {
   content: '';
   min-height: 20px;
   display: block;
 }

Но, честно говоря, лучшим решением будет размещение div в HTML и использование для него min-height.

Проверка элементов fallback

Мне нравится использовать прогрессивные методы для разработки обычных веб-сайтов без JavaScript. К сожалению, недавно это сослужило мне плохую службу на одном поддерживаемом сайте, когда версия без JavaScript отличалась от версии с JavaScript.

Проблема была связана с кнопкой меню «Оглавление» в заголовке. До включения JavaScript это простая ссылка, стилизованная под кнопку, которая ведет на страницу оглавления. После включения JavaScript она становится динамическим меню, позволяющим переходить непосредственно на нужную страницу.

Скриншоты двух компонентов навигации "Оглавление", стилизованных под кнопку. С помощью JavaScript открывается динамическое меню, как показано на втором изображении.

Я использовал семантические элементы и поэтому применил якорь (‹a href="#table-of-contents"›) для обратной ссылки, но заменил его на ‹button› для динамического меню, управляемого JavaScript. Эти элементы внешне выглядели одинаково, но ссылка оказалась на пару пикселей меньше, чем кнопка!

Это было так незначительно, а JavaScript обычно срабатывал так быстро, что я не заметил этого. Однако Chrome заметил это при расчете CLS и, поскольку ссылка находилась в заголовке, сместил всю страницу на пару пикселей вниз. Это довольно сильно повлияло на оценку CLS — достаточно, чтобы все наши страницы попали в категорию «Требует улучшения».

Это была ошибка с моей стороны, и исправление заключалось в том, чтобы просто привести два элемента в соответствие (это также можно было исправить, установив min-height для заголовка, как говорилось выше), но меня это немного смутило. Я уверен, что я не единственный, кто допустил эту ошибку, поэтому будьте внимательны к тому, как страница отображается без JavaScript. Думаете, что ваши пользователи не отключают JavaScript? Все ваши пользователи не используют JS, пока страница подгружает ваши скрипты.

Веб-шрифты вызывают сдвиг в макете

Веб-шрифты являются еще одной распространенной причиной CLS, поскольку браузер изначально рассчитывает необходимое пространство для резервного шрифта, а затем пересчитывает его при загрузке веб-шрифта. Обычно CLS невелик, если используется аналогичный по размеру резервный шрифт, поэтому часто они не вызывают достаточно серьезных проблем, чтобы не пройти проверку Core Web Vitals, но, тем не менее, могут наблюдаться рывки содержимого страницы, раздражающие пользователей.

Два скриншота статьи с разными шрифтами. Текст заметно отличается по размеру, и при использовании веб-шрифтов может уместиться дополнительное предложение.

К сожалению, даже предварительная загрузка веб-шрифтов здесь не поможет, поскольку, хоть это и уменьшает время использования резервных шрифтов (что хорошо для производительности загрузки — LCP), все равно требуется время для их получения, и поэтому в большинстве случаев резервные шрифты все равно будут использоваться браузером, что не позволяет избежать CLS. Однако если вы знаете, что веб-шрифт необходим на следующей странице (например, вы находитесь на странице входа в систему и знаете, что на следующей странице используется специальный шрифт), вы можете предварительно загрузить его.

Чтобы полностью избежать сдвигов макета, вызванных шрифтами, можно, конечно, вообще не использовать веб-шрифты — в том числе использовать вместо них системные шрифты или использовать font-display: optional, чтобы не использовать их, если они не загружены вовремя для первоначального рендеринга. Но, если чесно, ни один из этих вариантов не является удовлетворительным.

Другой вариант — задать соответствующий размер секций (например, с помощью min-height), так что, если даже текст в них немного сместится, содержимое под ними не будет сдвинуто вниз. Например, установка min-height для элемента ‹h1› может предотвратить смещение всей статьи вниз при загрузке более высоких шрифтов — при условии, что разные шрифты не приводят к различному количеству строк. Это уменьшит влияние сдвигов, однако в большинстве случаев (например, общих абзацев) будет сложно обобщить минимальную высоту.

Больше всего меня радует решение этой проблемы с помощью новых дескрипторов шрифтов CSS, которые позволят вам легче настраивать резервные шрифты в CSS:

@font-face {
  font-family: 'Lato';
  src: url('/static/fonts/Lato.woff2') format('woff2');
  font-weight: 400;
}

@font-face {
    font-family: "Lato-fallback";
    size-adjust: 97.38%;
    ascent-override: 99%;
    src: local("Arial");
}

h1 {
    font-family: Lato, Lato-fallback, sans-serif;
}

До этого для настройки резервного шрифта требовалось использовать API загрузки шрифтов в JavaScript, что было сложнее, но эта опция, которая очень скоро появится, наконец предоставит нам более простое решение, которое, скорее всего, получит распространение.

Начальные шаблоны для рендеринговых страниц на стороне клиента

Многие клиентские рендеринговые страницы, или Single Page Apps, создают начальную базовую страницу, используя только HTML и CSS, а затем «связывают» его после загрузки и выполнения JavaScript.

Эти начальные шаблоны легко рассинхронизировать с версией JavaScript, поскольку новые компоненты и функции добавляются в приложение в JavaScript, но не добавляются в начальный HTML-шаблон, который отрисовывается первым. Это приводит к возникновению CLS, когда эти компоненты внедряются в JavaScript.

Поэтому пересмотрите все свои начальные шаблоны, чтобы убедиться, что они по-прежнему являются правильными. И если начальный шаблон состоит из пустых ‹div›, то используйте описанные выше приемы, чтобы убедиться, что они имеют соответствующий размер, чтобы попытаться избежать смещений макета.

Кроме того, начальный div, который вводится в приложение, должен иметь min-height, чтобы он не отображался с высотой 0 еще до вставки начального шаблона.

<div id="app" style="min-height:900px;"></div>

Если min-height больше, чем для большинства вьюпортов, это позволит избежать CLS, например, для нижнего колонтитула сайта. CLS измеряется только тогда, когда он находится в области просмотра и, таким образом, влияет на пользователя. По умолчанию пустой div имеет высоту 0px, поэтому задайте ему min-height, которая будет ближе к фактической высоте при загрузке приложения.

Обеспечение завершения взаимодействия с пользователем в течение 500 мс

Взаимодействие с пользователем, вызывающее смещение содержимого, исключается из оценки CLS, и оно ограничено 500 мс после начала взаимодействия. Поэтому если вы нажмете на кнопку, выполните сложную обработку, которая займет более 500 мс, а затем отобразите новый контент, ваш показатель CLS ухудшится.

Вы можете проверить, был ли исключен сдвиг, в Chrome DevTools, используя вкладку Performance для записи страницы, а затем найдя сдвиги, как показано на следующем скриншоте. Откройте DevTools, перейдите на очень страшную (но после освоения, очень полезную!) вкладку Performance, затем нажмите на кнопку записи в левом верхнем углу (обведена на рисунке ниже) и взаимодействуйте со своей страницей, остановив запись после завершения.

Снимок экрана Chrome Dev Tools с выбранным Cumulative Layout Shift

На вкладке Performance, под строкой Experience, Chrome поместит красновато-розовую рамку для каждого смещения, при нажатии на которую, вы получите более развернутую информацию на вкладке Summary ниже.

Здесь видно, что мы получили совершенно неприемлемый результат 0.3359 — намного больше допустимого порога 0.1, но в суммарном показателе это не учитывается, поскольку для параметра Had recent input установлено значение Uses.

Обеспечение взаимодействия только смещает содержимое в пределах 500 мс, которые оценивает First Input Delay (FID), но есть случаи, когда пользователь может видеть, что ввод оказал влияние (например, отображается индикатор загрузки), поэтому FID хороший, но содержимое не может быть добавлено на страницу до истечения 500 мс, поэтому для CLS — это плохо.

В идеале все взаимодействие не должно превышать 500 мс, но вы можете сделать некоторые шаги, чтобы зарезервировать необходимое пространство с помощью описанных выше методов, пока идет обработка, так что если она займет больше, чем магические 500 мс, то вы уже справились со сдвигом и CLS не пострадает. Это особенно полезно при получении контента из сети, который может быть динамическим и не контролироваться вами.

Также следует обратить внимание на анимацию, которая загружается больше 500 мс и может повлиять на CLS. Несмотря на кажущуюся строгость и декларативность, цель CLS — не ограничить «веселье», а установить разумные ожидания в отношении пользовательского опыта, и не совсем правильно ожидать, что анимация будет занимать 500 мс или меньше. Но если вы с этим не согласны, или у вас есть уникальный опыт использования, то команда Chrome открыта для обратной связи по этому вопросу.

Синхронный JavaScript

Последняя техника, которую я собираюсь обсудить, немного спорная, поскольку она противоречит известным советам по производительности веб-сайтов, но в определенных ситуациях она может оказаться единственным решением. В принципе, если у вас есть контент, который, как предполагается, может вызвать смещение, то одно из решений, предотвращающих сдвиги — это не отображать его, до тех пор пока он не стабилизируется!

Приведенный ниже HTML сначала скроет div, затем загрузит блокирующий рендеринг скрипт, чтобы заполнить контейнер, а затем скроет его. Поскольку JavaScript блокирует отрисовку, ничего ниже этого не будет отрисовано (включая второй блок со стилями), и поэтому сдвигов не произойдет.

<style>
.cls-inducing-div {
    display: none;
}
</style>

<div class="cls-inducing-div"></div>
<script>
...
</script>

<style>
.cls-inducing-div {
    display: block;
}
</style>

При использовании этой техники важно вставлять стили в HTML разметку, чтобы они применялись по порядку. Альтернативой является скрытие содержимого с помощью JavaScript, но мне нравится вышеописанная техника тем, что она скрывает содержимое, даже если JavaScript не работает или он отключен в браузере.

Эту технику можно применять даже с внешним JavaScript, но это может вызвать большую задержку, чем при использовании встроенных скриптов, поскольку внешний JavaScript необходимо еще загрузить. Эту задержку можно минимизировать, предварительно загрузив скрипты, чтобы не было задержек, когда парсер дойдет до этого участка кода:

<head>
...
<link rel="preload" href="cls-inducing-javascript.js" as="script">
...
</head>
<body>
...
<style>
.cls-inducing-div {
    display: none;
}
</style>
<div class="cls-inducing-div"></div>
<script src="cls-inducing-javascript.js"></script>
<style>
.cls-inducing-div {
    display: block;
}
</style>
...
</body>

Как уже говорилось выше, я уверен, что эти техники заставят некоторых спецов по оптимизации скривиться, так как совет использовать async, defer или более новый type="module" (которые отложены по умолчанию) специально для того, чтобы избежать блокировки рендеринга, в то время как мы здесь пытаемся добиться обратного! Однако, если контент не может быть заранее предопределен, и он будет вызывать резкие смещения, то нет смысла рендерить его раньше времени.

Я использовал эту технику для баннера cookie, который загружался в верхней части страницы и смещал содержимое вниз:

Снимок экрана веб-страницы, на котором содержимое смещается вниз, когда баннер cookie добавляется в верхнюю часть страницы.

Это требовало считывания cookie, чтобы определить, показывать баннер или нет, и, хотя это можно было сделать на стороне сервера, в данном случае это был статический сайт без возможности динамически изменять возвращаемый HTML.

Баннеры cookie можно реализовать различными способами, чтобы избежать CLS. Например, расположить их в нижней части страницы или наложить поверх контента, а не смещать контент вниз. Мы предпочли оставить контент в верхней части страницы, поэтому пришлось использовать этот прием, чтобы избежать смещения.

Эту техника используется и на другой странице, где JavaScript перемещает содержимое в «главную» и «побочную» колонки (по ряду причин этого невозможно было добиться на стороне сервера). Снова смещение контента, пока JavaScript не переставит его, и только потом показав его, удалось избежать проблем с CLS, которые приводили к снижению оценки Core Web Vitals этих страниц.

Использование этой техники может повлиять на другие показатели (в частности, LCP и First Contentful Paint), поскольку вы блокируете рендеринг страницы, а также потенциально блокируете предзагрузку браузера, но это еще один инструмент, который стоит рассмотреть в тех случаях, когда других вариантов нет.

Заключение

Cumulative Layout Shift (CLS) вызывается изменением размеров контента или внедрением нового контента на страницу с помощью поздно запущенного JavaScript. В этой статье мы рассмотрели различные советы и приемы, позволяющие избежать этих проблем. Я рад, что Core Web Vitals обратил внимание на эту раздражающую проблему — слишком долго мы, веб-разработчики (и я, безусловно, отношу себя к ним), игнорировали её.

Оптимизация моих собственных веб-сайтов привела к росту поведенческих факторов. Я призываю вас также обратить внимание на проблемы CLS, и надеюсь, что некоторые из этих советов будут вам полезны. Кто знает, возможно, вам даже удастся добиться неуловимого показателя CLS 0 для всех ваших страниц!

Источник: https://www.smashingmagazine.com/

Вконтакте
Linkedin
Telegram
Whatsapp

Похожие статьи

Как улучшить атрибуты адаптивного изображения (sizes и srcset) в WordPress


Атрибуты адаптивного изображения (sizes и srcset) в ядре WordPress появились в версии 4.4. В этой статье мы рассмотрим, как их можно улучшить, а также добавить другие атрибуты. Изображения будут получать эти два атрибута (sizes и srcset) только в том случае, если HTML-код изображения будет получен с помощью функции wp_get_attachment_image


Как загрузить файлы SVG в WordPress


Масштабируемая векторная графика или SVG — это векторный формат изображения на основе XML, который предназначен для работы с двумерной графикой и позволяет масштабировать изображения, не ухудшая при этом их качество. Если стандартное изображение в формате JPG или PNG нельзя увеличить без пикселизации, то векторный формат позволяет поддерживать достаточно высокое качество картинки


У этой статьи пока нет комментариев


Добавить комментарий


Ваш адрес email не будет опубликован. Обязательные поля помечены *

семь − 6 =