Содержание
- 1 Введение
- 2 Configuration
- 3 A Quick Review
- 4 Тип маркеров
- 5 Позиционирование нескольких иконок с помощью ‘preserveAspectRatio’
- 6 SVG Viewport
- 7 Масштабирование изображения в одиночном файле SVG
- 8 Runtime configuration
- 9 Позиционирование иконок в одиночном файле SVG
- 10 rbox()
- 11 Позиционирование изменением параметров команды ‘use’
- 12 Структура ‘symbol’, размещение в SVG файле
- 13 5.б Уменьшение масштаба М1:2
- 14 Правила и команды заполнения путей – fill-rule=”nonzero | evenodd”
- 15 Системы координат
- 16 Description
- 17 Позиционирование иконок с помощью ‘viewBox’
- 18 Вьюпорт
- 19 5.а Увеличение масштаба М2:1
- 20 Недостатки SVG формата
- 21 Reviews
Введение
Изменение параметров viewBox – атрибута элемента SVG позволяет масштабировать, фрагментировать, перемещать исходное изображение вдоль осей координат. Но довольно часто возникают вопросы: “Почему, изменив параметры viewBox, я получаю совсем не то, что ожидал увидеть?”. Вместо увеличения картинки в 2 раза, она совсем пропадает с дисплея или сдвигается не в ту сторону и т.д. Чтобы разобраться в причинах этих “аномалий” рассмотрим подробно процессы взаимодействия областей просмотра элемента SVG и его параметра viewBox.1 2 3 5 6 7 8 9 10 11 12 13 14 15 16 | <!DOCTYPE svg PUBLIC»-//W3C//DTD SVG 1.1//EN» «//www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd»> <svg width=»400″height=»400″version=»1.1″ xmlns=»//www.w3.org/2000/svg» style=»border: 2px dashed blue;»> <!—colored circles incorners of the canvas—> <circle cx=»55″cy=»55″r=»50″fill=»rgba(20,255,24, 0.5)»stroke=»rgba(6,90,6, 0.75)»stroke-width=»2″> <circle cx=»350″cy=»55″r=»50″fill=»rgba(57,65,212, 0.5)»stroke=»rgba(26,31,167, 0.75)»stroke-width=»2″> <circle cx=»350″cy=»350″r=»50″fill=»rgba(212,30,75, 0.5)»stroke=»rgba(212,30,75, 0.75)»stroke-width=»2″> <circle cx=»55″cy=»350″r=»50″fill=»rgba(255,221,0, 0.5)»stroke=»rgba(169,146,0, 0.75)»stroke-width=»2″> <!—the red rectangle outside viewing area svg—> <rectx=»390″y=»165″width=»100″height=»100″fill=»rgba(244,47,39, 0.6)»stroke=»rgba(244,47,39, 0.75)»stroke-width=»2″> <svg> |
Configuration
{ test\.svg$, loader'svg-sprite-loader', query{...}}{ test\.svg$, loaders`svg-sprite-loader?${JSON.stringify({...})}`,'svg-transform-loader','svgo-loader'}{ test\.svg$, loader'svg-sprite-loader', options{...}}{ test\.svg$, use{ loader'svg-sprite-loader', options{...}},'svg-transform-loader','svgo-loader'}
{symbolIdfilePath=>path.basename(filePath)}Passed to the symbolId interpolator to support the pattern in the loader-utils name interpolator Generated export format:
- when loader will produce .
- when the result is .
A Quick Review
Last week I presented a metaphor that helped me understand how SVG works and I want to offer it again as a reminder. Picture an infinite rectangular canvas on which you can draw anything you want, wherever you want in infinite space. This is the SVG canvas. It’s also called user space. Now imagine someone builds a wall in front of the canvas. The wall is equally infinite to the canvas and covers every bit of it exactly. Fortunately someone built a rectangular window into the wall. It’s flexible in that you get to set any width and height you want, but once set the window becomes fixed in size and space. This window is the viewport and you set its dimensions when you set the width and height of the element.Тип маркеров
Маркеры бывают следующих типов: marker-start, marker-mid, marker-end. Каждый тип указывают на расположение маркера, соответственно в начале, середине, конце линии или пути, к которым они присоединяются. На рисунке выше в качестве начального маркера marker-start использован круг (circle). Конечный маркер marker-end создан с помощью пути (path), нарисовавшего стрелку.1 2 3 4 5 6 8 9 10 12 13 14 15 16 18 19 20 21 22 | <!DOCTYPE svgPUBLIC»-//W3C//DTD SVG 1.1//EN» «http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd»> <svg width=»150″height=»150″version=»1.1″ viewBox=»0150150″preserveAspectRatio=»none» xmlns=»http//www.w3.org/2000/svg» > <defs> markerUnits=»userSpaceOnUse»orient=»auto» markerWidth=»20″markerHeight=»20″> <polyline id=»markerPoly1″points=»0,020,100,202,10″fill=»crimson»/> <marker id=»MarkerCircle»viewBox=»01010″refX=»0″refY=»5″ markerUnits=»userSpaceOnUse» markerWidth=»10″markerHeight=»10″> <circle cx=»5″cy=»5″r=»5″fill=»crimson»/> </marker> <line x1=»20″y1=»80″x2=»110″y2=»80″ style=»marker-starturl(#MarkerCircle);marker-endurl(#MarkerArrow); fillnone;strokegreen;stroke-width2;»/> </svg> |
Позиционирование нескольких иконок с помощью ‘preserveAspectRatio’
На ум сразу приходит решение этой задачи – использовать ‘preserveAspectRatio’. Одну иконку направить влево – ‘xMinYMin’, вторую разместить по центру – ‘xMidYMid’, третью вправо – ‘xMaxYMax’. Каждую иконку обернуть в свой ‘symbol’, так как у него есть свой ‘viewBox’ и ‘preserveAspectRatio’. Структура в примере ниже:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <svg xmlns=»http//www.w3.org/2000/svg»width=»310″height=»100″ viewBox=»0100100″preserveAspectRatio=»xMaxYMaxmeet» xmlnsxlink=»http//www.w3.org/1999/xlink»> <symbol id=»milk»viewBox=»0100100″ preserveAspectRatio=»xMinYMinmeet» > <path …/> </symbol> <symbol id=»like»viewBox=»0100100″ preserveAspectRatio=»xMidYmidmeet»> <path …/> </symbol> <symbol id=»letter»viewBox=»0100100″ preserveAspectRatio=»xMaxYMaxmeet» > <path …/> </symbol> <use xlinkhref=»#letter»/> <use xlinkhref=»#milk»/> <use xlinkhref=»#like»/> </svg> |
SVG Viewport
If you literally break down the word “viewport” you’ll get a hint as to its role in SVG; it creates a “port” through which you can “view” a section of an SVG. You can imagine this as being something akin to a porthole window through which you can see the world beyond. The SVG viewport is like a porthole window whose size determines what you can see through it As with a window, the size of the viewport determines how much you can see, but it doesn’t define the size of whatever might be visible through that viewport. What’s on the other side could theoretically be any size at all. For example, you might have a shape in your graphic that is by , but if you set the viewport to by you’ll only see a portion of that shape. The viewport size is set by adding and attributes to the element, like so: In the first SVG we see the entire by circle, but in the second SVG when we set our viewport size to by we only see a quarter of the circle.Масштабирование изображения в одиночном файле SVG
Берем файл иконки 48х48 px, всё как есть, без изменений кода.
1 2 3 4 5 6 7 8 | <svg version=»1″xmlns=»http://www.w3.org/2000/svg»viewBox=»0 0 48 48″> <path fill=»#37474F»d=»M6,36V8c0-2.2,1.8-4,4-4h14c2.2,0,4,1.8,4,4v28c0,2.2-1.8,4-4,4H10C7.8,40,6,38.2,6,36z»> <path fill=»#BBDEFB»d=»M24,7H10C9.4,7,9,7.4,9,8v25c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1V8C25,7.4,24.6,7,24,7z»> <rectx=»14″y=»36″fill=»#78909C»width=»6″height=»2″> <path fill=»#C556AF»d=»M20,40V12c0-2.2,1.8-4,4-4h14c2.2,0,4,1.8,4,4v28c0,2.2-1.8,4-4,4H24C21.8,44,20,42.2,20,40z»> <path fill=»#FFF3E0″d=»M38,11H24c-0.6,0-1,0.4-1,1v25c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1V12C39,11.4,38.6,11,38,11z»> <circle fill=»#FFF3E0″cx=»31″cy=»41″r=»1.5″> <svg> |
1 | <svg version=»1″xmlns=»http://www.w3.org/2000/svg»width=»48″height=»48″viewBox=»0 0 48 48″> |
1 | <svg version=»1″xmlns=»http://www.w3.org/2000/svg»width=»96″height=»96″viewBox=»0 0 48 48″> |
1 | <svg version=»1″xmlns=»http://www.w3.org/2000/svg»width=»24″height=»24″viewBox=»0 0 48 48″> |
Runtime configuration
When you require an image, loader transforms it to SVG , adds it to the special sprite storage and returns class instance that represents symbol. It contains , and (, and in extract mode) fields and can later be used for referencing the sprite image, e.g: When browser event is fired, sprite will be automatically rendered and injected in the . If custom behaviour is needed (e.g. a different mounting target) default sprite module could be overridden via option. Check example below.- for ‘web’ target.
- for other targets.
importBrowserSpritefrom'svg-baker-runtime/src/browser-sprite';importdomreadyfrom'domready';constsprite=newBrowserSprite();domready(()=>sprite.mount('#my-custom-mounting-target'));exportdefaultsprite;It’s highly recommended to extend default sprite classes: Same as , but for sprite symbol. By default also depends on webpack config option:
- for ‘web’ target.
- for other targets.
Позиционирование иконок в одиночном файле SVG
Позиционирование иконок внутри файла SVG становится необходимым, если при встраивании векторного изображения в страницу Html, появляются большие отступы текста вокруг иконок. Возьмем иконку с размерами 48x48px, и добавим её внутрь Html страницы, таким образом, чтобы текст обтекал её слева. Ниже код иконки.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <svg version=»1″xmlns=»http://www.w3.org/2000/svg»width=»96″height=»96″viewBox=»0 0 96 96″ style=»border:1px solid crimson»> <gfill=»#00BCD4″> <rectx=»37″y=»18″width=»6″height=»24″> <rectx=»29″y=»26″width=»6″height=»16″> <rectx=»21″y=»22″width=»6″height=»20″> <rectx=»13″y=»32″width=»6″height=»10″> <rectx=»5″y=»28″width=»6″height=»14″> <g> <gfill=»#3F51B5″> <circle cx=»8″cy=»16″r=»3″> <circle cx=»16″cy=»18″r=»3″> <circle cx=»24″cy=»11″r=»3″> <circle cx=»32″cy=»13″r=»3″> <circle cx=»40″cy=»9″r=»3″> <polygon points=»39.1,7.2 31.8,10.9 23.5,8.8 15.5,15.8 8.5,14.1 7.5,17.9 16.5,20.2 24.5,13.2 32.2,15.1 40.9,10.8″> <g> <svg> |
1 | style=»border1pxsolidcrimson» |
1 2 | <svg version=»1″xmlns=»http//www.w3.org/2000/svg»width=»48″height=»48″ viewBox=»04848″style=»border1pxsolidcrimson»> |
rbox()
Is similar to but will give you the box around the exact visual representation of the element, relative to the screen coordinate system, taking all transformations into account. Usually, what is needed is the box relative to the drawing. To get this, pass the of the drawing. This will return an instance of containing the following values relative either to the screen or the parameter:- (the actual visual width)
- (the actual visual height)
- (shorthand for )
- (shorthand for )
- (the actual visual position on the x-axis)
- (the actual visual position on the y-axis)
- (center of the bounding box)
- (center of the bounding box)
- (lower right of the bounding box)
- (lower right of the bounding box)
Позиционирование изменением параметров команды ‘use’
Команда ‘use’ создает прямоугольную область с началом координат – x=”0″ y=”0″ и служит для вывода изображений. Ширина и высота этой области, если не указаны другие значения, равны ширине и высоте ‘viewport’. В отличии от ‘viewBox’ сдвиг вправо начала координат ‘use’ сдвигает векторное изображенгие вправо. Последовательность позиционирования иконок по горизонтали следующая: Расширяем ‘viewport’ в шапке файла, чтобы хватило места для всех иконок. Высоту ‘viewport’ – назначаем равной высоте иконок. ‘viewBox’, если он есть в шапке файла удаляем. Это для того, чтобы исключить воздействие – ‘preserveAspectRatio’ Код каждой иконки оборачиваем в’symbol’, присваиваем ему ‘id’1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <svg xmlns=»http//www.w3.org/2000/svg»width=»600″height=»126″ xmlnsxlink=»http//www.w3.org/1999/xlink»> <rect x=»0″width=»600″height=»126″fill=»#C9E4FF»/> <symbol id <!— Здеськодиконки—> <path …/> </symbol> <symbol id=»google» > <!— Здеськодиконки»google»—> <path… /> </symbol> <symbol id=»linkedin» > <!— Здеськодиконки»linkedin»—> <path …»/> </symbol> <symbol id > <!— Здеськодиконки—> <path …/> </symbol> <symbol id=»vimeo» > <!— Здеськодиконки»vimeo»—> <path…/> </symbol> <!— Позиционированиеиконокпогоризонтали—> <use x=»-5″xlinkhref=»#vimeo»/> <use x=»112″xlinkhref/> <use x=»235″xlinkhref/> <use x=»358″xlinkhref=»#linkedin»/> <use x=»480″xlinkhref=»#google»/> </svg> |
Структура ‘symbol’, размещение в SVG файле
‘symbol’ – сам по себе не отображается, подобно элементам, размещенных в секции <defs> …</defs>, но его можно вызвать один или несколько раз по уникальному идентификатору id=”..” с помощью команды <use>1 2 3 4 | <usex=»0″y=»0″width=»24″height=»24″xlinkhref=»#pie»> <usex=»24″y=»0″width=»24″height=»24″xlinkhref=»#pie»> <usex=»0″y=»24″width=»24″height=»24″xlinkhref=»#pie»> <usex=»24″y=»24″width=»24″height=»24″xlinkhref=»#pie»> |
1 2 3 4 6 7 8 10 11 12 13 14 15 16 17 18 19 | <?xml version=»1.0″encoding=»utf-8″?> <svg xmlns=»http://www.w3.org/2000/svg» xmlnsxlink=»http://www.w3.org/1999/xlink»version=»1.0″ width=»256″height=»256″viewBox=»0 0 48 48″> <defs> <symbolid=»pie»viewBox=»0 0 48 48″preserveAspectRatio=»xMidYMid meet»> <title>Pie chart<title> <path fill=»#00BCD4″d=»M24,30c-3.3,0-6-2.7-6-6s2.7-6,6-6V5C13.5,5,5,13.5,5,24s8.5,19,19,19c4.4,0,8.5-1.5,11.8-4.1l-8-10.2 C26.7,29.5,25.4,30,24,30z»> <path fill=»#448AFF»d=»M30,24h13c0-10.5-8.5-19-19-19v13C27.3,18,30,20.7,30,24z»> <path fill=»#3F51B5″d=»M43,24H30c0,1.9-0.9,3.6-2.3,4.7l8,10.2C40.2,35.4,43,30,43,24z»> <symbol> <usex=»0″y=»0″width=»24″height=»24″xlinkhref=»#pie»> <usex=»24″y=»0″width=»24″height=»24″xlinkhref=»#pie»> <usex=»0″y=»24″width=»24″height=»24″xlinkhref=»#pie»> <usex=»24″y=»24″width=»24″height=»24″xlinkhref=»#pie»> <svg> |

5.б Уменьшение масштаба М1:2
1 2 | <svg width=»400″height=»400″version=»1.1″ viewBox=»0 0 800 800″preserveAspectRatio=»none» |
Правила и команды заполнения путей – fill-rule=”nonzero | evenodd”
Я думаю, что все, кто рисовал в любом векторном редакторе, встречались с эффектом белых, непрокрашенных пятен при заполнении фигур цветом. Это не вызывало больших проблем и легко устранялось дополнительными щелчками мышки по незакрашенным областям рисунка. Но как быть, если нужно написать скрипт, реализующий анимацию с закрашиванием всей фигуры или её отдельных сегментов? Для этого нужно чётко разобраться в алгоритме заполнения цветом сегментов фигур. Логично предположить, что должны заполняться внутренние области фигуры, а наружные оставаться незакрашенными. Но как понять, где внутренняя, а где наружная область фигуры, если она имеет сложные контуры с многократными пересечениями линий. Что брать за точку отсчета, относительно чего смотреть? Ответы на эти вопросы дает команды fill-rule, которая имеет два значения:nonzero | evenodd fill-rule=”nonzero” Это правило определяет внутреннию точку на холсте, путем рисования луча от этой точки до бесконечности в любом направлении и затем проверяются места, где сегмент фигуры пересекает луч . Отсчет начинается с нуля. Единица (+1) добавляется каждый раз, когда сегмент пересекает луч слева направо и вычитается единица (-1), когда сегмент пересекает луч справо налево . После подсчета пересечений, если результат равен нулю, то точка считается снаружи пути (сегмент не закрашивается). В противном случае она внутри. Примечание. Правило действительно только для совокупности нескольких подпутей внутри одного параметра d=”…” команды path.1 2 3 | <pathd=»M25,225 25,25 225,25 225,225 25,225 M75,175 75,75 175,75 175,175 75,175″ style=»strokeblue;fill-rulenonzero;stroke-width2;filldodgerblue;> |
1 2 3 | <pathd=»M25,225 25,25 225,25 225,225 25,225 M75,175 175,175 175,75 75,75 75,175″ style=»strokeblue;fill-rulenonzero;stroke-width2;filldodgerblue;> |
1 2 3 4 | <pathd=»M25,225 25,25 225,25 225,225 25,225 M65,185 185,185 185,65 65,65 65,185 M105,145 105,105 145,105 145,145 105,145″ style=»strokeblue;fill-rulenonzero;stroke-width2;filldodgerblue;> |
Системы координат
В SVG-документе есть две системы координат:- Система координат области отрисовки — viewport space.
- Система координат содержимого — user space.
- Understanding SVG Coordinate Systems and Transformations (Part 1) — The viewport, viewBox, and preserveAspectRatio
- Understanding SVG Coordinate Systems and Transformations (Part 2) — The transform Attribute
- Understanding SVG Coordinate Systems and Transformations (Part 3) — Establishing New Viewports
Description
Safe SVG is the best way to Allow SVG Uploads in WordPress! It gives you the ability to allow SVG uploads whilst making sure that they’re sanitized to stop SVG/XML vulnerabilities affecting your site. It also gives you the ability to preview your uploaded SVGs in the media library in all views.Free Features
- Sanitised SVGs – Don’t open up security holes in your WordPress site by allowing uploads of unsanitised files.
- View SVGs in the Media Library – Gone are the days of guessing which SVG is the correct one, we’ll enable SVG previews in the WordPress media library.
Pro Features
- SVGO Optimisation – You’ll have the option to run your SVGs through our SVGO server on upload to save you space.
- Choose Who Can Upload – Restrict SVG uploads to certain users on your WordPress site or allow anyone to upload.
- Premium Support – Pro users get premium support whilst free support is offered in the WordPress forums in our spare time
Позиционирование иконок с помощью ‘viewBox’
Этот способ позиционирования является наиболее простым и понятным. Он может быть использован на практике, если отступы от векторного объекта до краев области просмотра не критичны для вёрстки страницы. Центрирование по горизонтали. Возьмем иконку с геометрическими размерами 100×100 px и поместим её в прямоугольную область просмотра ‘viewport’ с шириной width =”200″ и высотой height=”100″ пикселей.1 2 3 | <svg xmlns=»http//www.w3.org/2000/svg»width=»200″height=»100″viewBox=»0100100″ xmlnsxlink=»http//www.w3.org/1999/xlink» style=»border1pxdottedcrimson;»> |
1 2 | <svg xmlns=»http//www.w3.org/2000/svg»xmlnsxlink=»http//www.w3.org/1999/xlink»width=»300″height=»100″ viewBox=»0100100″preserveAspectRatio=»xMinYMinmeet» > |
1 2 | <svg xmlns=»http//www.w3.org/2000/svg»xmlnsxlink=»http//www.w3.org/1999/xlink»width=»300″height=»100″ viewBox=»0100100″preserveAspectRatio=»xMidYMidmeet» > |
1 2 | <svg xmlns=»http//www.w3.org/2000/svg»xmlnsxlink=»http//www.w3.org/1999/xlink»width=»300″height=»100″ viewBox=»0100100″preserveAspectRatio=»xMaxYMaxmeet» > |
1 2 | <svg xmlns=»http//www.w3.org/2000/svg»xmlnsxlink=»http//www.w3.org/1999/xlink»width=»100″height=»200″ viewBox=»0100100″preserveAspectRatio=»xMidYMidmeet» > |
Вьюпорт
Содержимое SVG-элемента отрисовывается на бесконечном холсте и может быть сколь угодно большого размера, но видимая часть холста соответствует размерам SVG-элемента. Эта область отрисовки называется (вьюпорт). SVG позволяет управлять как размерами вьюпорта, так и поведением содержимого относительно него: оно может обрезаться или показываться полностью, может растягиваться с потерей пропорций или стараться уместиться целиком, даже если при этом появляются пустые поля. Этим поведением можно управлять с помощью атрибутов. Если просто вставить SVG на страницу и не задавать ему никакие размеры, он отобразится размером 300px на 150px, что не поместилось — обрежется:5.а Увеличение масштаба М2:1
1 2 | <svg width=»400″height=»400″version=»1.1″ viewBox=»0 0 200 200″preserveAspectRatio=»none» |
Недостатки SVG формата
- С увеличением количества мелких деталей в изображении, быстрее растёт размер файла SVG-данных. Предельный случай — когда изображение представляет собой белый шум. В этом случае SVG не только не даёт никаких преимуществ в размере файла, но даже имеет проигрыш по отношению к растровому формату. На практике, SVG становится невыгоден уже задолго до того, как изображение дойдёт до стадии белого шума.
- Трудность использования в крупных картографических приложениях из-за того, что для правильного отображения маленькой части изображения документ необходимо прочитать целиком.
- В настоящее время SVG формат применяется в Интернете сравнительно мало, из-за недостаточной кроссбраузерности. Лучше всего обстоят дела у Mozilla Firefox со встроенным просмотрщиком SVG, так как ее разработчики находятся в рабочей группе Консорциума Всемирной паутины (W3C) по разработке и внедрению стандарта SVG. Хуже всего дела по поддержке формата SVG у Microsoft, которая покинула группу 2003 г. Для Internet Explorer – необходим Adobe SVG Viewer (ASV). С 9 версии IE частично поддерживает функции SVG. Браузеры Apple Safari, Google Chrome намного лучше поддерживают SVG, но не полностью, так как SVG – это большая спецификация (вдвое больше HTML 4.01), именно поэтому разработчики браузеров внедряют функции постепенно, от версии к версии. Но абсолютно все разработчики современных браузеров заявляют, что за форматом SVG будущее в области графики вебдизайна.
Reviews
http-equiv=»Content-Type» content=»text/html;charset=UTF-8″>lass=»plugin-reviews»> I struggled modifying my PNGs in order not to lose pixelation, to no avail, until I discovered this plugin. Now all my graphics are SVGs and there’s no turning back! One little feature request though: make the image size appear in the media library list screen, as other images format do. This is the plugin that I have been waiting for. Adding SVG implementation in easy way with full support of Gallery thumbnails. Plugin is doing the rest in securing SVG/XML code to avoid exploits. Great. No issues when working with cache plugins like W3 Total Cache and CloudFlare. Simple and effective. I was able to use an svg as a menu image for the site header using this in combination with the plugin «Menu Image» — without this plugin I couldn’t do it. Funciona bem It works, thank you!С этим читают
- Png to svg
- Svg
- Часть 4. основы maven
- Как вставить svg картинку на свой сайт
- Векторный редактор онлайн: 8 лучших бесплатных браузерных альтернатив adobe illustrator
- Clip
- Как поменять разрешение в игре, в т.ч., даже не заходя в неё (если вылетает ошибка, или вы ничего не видите при ее запуске)
- Quick tip: don’t forget the viewport meta tag
- Перевод писем в почте
- Что такое протокол http/2 и чем он полезен для сайтов?