Использование SVG с медиа-запросами

Использование SVG с медиа-запросами

От автора: с помощью HTML-документов мы можем отображать, скрывать или реорганизовать части страницы в зависимости от условий окна просмотра. Если, например, окно браузера имеет ширину 480 пикселей, мы можем изменить панель навигации с горизонтальной на вертикальную. Мы можем сделать что-то подобное, используя медиа запросы CSS и документы SVG. Рассмотрим, например, логотип вымышленной компании Hexagon Web Design & Development ниже.

Без медиа-запросов этот SVG-логотип будет просто растягиваться или сжиматься, чтобы соответствовать окну просмотра или его контейнеру. Но с помощью медиа-запросов мы можем сделать больше.

Давайте разберем область просмотра HTML-документов и окно просмотра SVG-документов. Когда SVG встроен, окно просмотра HTML и окно просмотра SVG являются одними и теми же. Документ SVG ведет себя как любой другой элемент HTML. С другой стороны, когда SVG-документ связан как с объектом, так и с элементами img, мы имеем дело с окном просмотра SVG-документа.

Медиа-запросы работают в обоих случаях, но когда SVG-документ связан, его окно просмотра не зависит от HTML-документа. В этом случае размер окна браузера не определяет размер окна просмотра SVG. Вместо этого размер окна просмотра определяется размерами объекта, iframe или img. Возьмем в качестве примера (сокращенный) SVG-документ:

<svg version="1.1" id="HexagonLogo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 555 174" xml:space="preserve"> <defs> <style type="text/css"> /* CSS goes here */ </style> </defs> <g id="hex"> <polygon id="hexagonbg" points="55.2,162 10,86.5 55.2,11 145.5,11 190.7,86.5 145.5,162 "/> <path id="letterH" fill="#FFFFFF" d="M58,35.5h33v35.2h18.4V35.5 h33.2v103.4h-33.2v-38.3H91v38.3H58V35.5z M77.5,126.5V87.3h45.6v39.2h4V47.9h-4v35.6H77.5V47.9h-4v78.6H77.5z"/> </g> <g id="word-mark"> <g id="hexagon-word"> ... </g> <g id="web-design-and-dev"> ... </g> </g>
</svg>

В меньших окнах просмотра давайте покажем только H в виде шестиугольника:

@media (max-width: 20em) { [id=word-mark] { display: none; }
}

Теперь, когда наш контейнер SVG меньше или равен 20em, будет отображаться только часть символа нашего логотипа, как показано ниже.

Чтобы запустить это представление из HTML-документа, установите ширину контейнера SVG:

<object data="hexlogo.svg" type="image/svg+xml" style="width: 20em;"></object>

Как вы могли заметить, SVG-изображение сохраняет свои внутренние размеры, хотя часть его скрыта. Это, к сожалению, является ограничением SVG. Чтобы исправить это, нам нужно изменить атрибут viewBox документа SVG, но только тогда, когда область просмотра меньше определенного размера. Это отличный вариант для matchMedia.

Атрибут viewBox, как следует из его названия, определяет видимую область элемента SVG. Скорректировав его, мы можем определить, какая часть изображения SVG заполняет окно просмотра. Ниже приведен пример использования matchMedia и медиа-запроса для обновления атрибута viewBox:

<script type="text/javascript">
var svg, originalViewBox, max20em, mq, updateViewBox; svg = document.querySelector('svg'); /* Store the original value in a variable */
originalViewBox = svg.getAttribute('viewBox'); /* Define our media query and media query object */
mq = matchMedia("(max-width: 20em)"); /* Define the handler */
updateViewBox = function(){ if (mq.matches) { /* Change the viewBox dimensions to show the hexagon */ svg.setAttribute('viewBox', "0 0 200 174"); } else { svg.setAttribute('viewBox', originalViewBox); }
} /* Fire on document load */
// WebKit/Blink browsers
svg.onload = updateViewBox; // Firefox & IE
svg.addEventListener('SVGLoad', updateViewBox, true); /* Fire if the media condition changes */
mq.addListener(updateViewBox); </script>

Примечание. Браузеры немного бесполезны, когда дело доходит до обработки события SVGLoad. В моих тестах addEventListener работал наиболее последовательно с Firefox. Для достижения наилучших результатов в Chrome и Safari используйте атрибут события onload. Microsoft Edge также лучше всего работает с onload, но только при использовании в качестве атрибута тега svg. Другими словами, <svg onload = «updateViewBox»>.

Теперь, когда контейнер SVG равен 20em или меньше, значение viewBox будет «0 0 200 174». Когда он превысит 20em, viewBox будет восстановлен до его начального значения, как показано ниже.

Поскольку этот метод использует либо атрибут события onload, либо событие SVGLoad, рекомендуется вставлять CSS и JavaScript в SVG-файл. Когда CSS является внешним, событие SVGLoad может срабатывать, прежде чем связанный с ним CSS завершит загрузку.

Использование медиа-запросов с background-size

SVG-документы и медиа-запросы не ограничиваются изображениями переднего плана. Мы также можем изменить размер окна SVG, используя свойство CSS background-size. Все новые браузеры поддерживают этот метод, но более старые версии браузеров — нет. Будьте осторожны при использовании этой техники в производстве. Мы начнем с этого документа SVG:

<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-20 -20 250 250" xml:space="preserve"> <style type="text/css"> circle { stroke: #000; stroke-width: 30; fill: #009688; } @media (width: 100px) { circle { fill: #673ab7; } } @media (width: 300px) { circle { fill: #ffc107; } } </style> </defs> <circle cx="100" cy="100" r="100" /> <circle cx="100" cy="100" r="50" />
</svg>

Это простой случай. Элементы нашего круга получат новый цвет заливки при определенных ширинах окна просмотра. Когда область просмотра имеет ширину 20 пикселей, заливка будет оранжевой. Когда он будет шириной 300 пикселей — желтой.

Чтобы сделать это, мы должны использовать изображение SVG в качестве фонового изображения и установить для селектора свойство background-size. В этом случае мы будем использовать изображение в качестве фона для элемента body и для элементов li. На изображении ниже показаны результаты:

body, li { background: url(../images/circles.svg);
}
body { background-color: #9c27b0; background-size: 300px auto;
}
li { background-size: 20px auto; background-repeat: no-repeat; background-position: left 3px; padding-left: 25px;
}

Автор: Tiffany Brown

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

Редакция: Команда webformyself.