Статьи

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

Ниже приведен небольшой отрывок из новой книги Тиффани « Мастер CSS», 2-е издание .

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

Очень реальный логотип для вымышленной компании

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

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

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

 <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; } } 

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

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

Отображение / скрытие элементов в зависимости от размера области просмотра SVG

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

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

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

viewBox , как следует из его названия, определяет видимую область элемента SVG. Регулируя его, мы можем определить, какая часть изображения SVG заполняет область просмотра. Ниже приведен пример использования matchMedia и 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 вернется к своему начальному значению, как показано ниже.

Настройка атрибута viewBox в зависимости от ширины области просмотра

Примечание. Чтобы получить более полное представление о создании интерактивных документов SVG, прочитайте главу « Динамический SVG и JavaScript » в «Учебнике SVG для современных браузеров W3C».

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

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

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

Мы начнем с этого документа 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> 

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

Чтобы сделать это, мы должны использовать наше изображение SVG в качестве фонового изображения и установить свойство background-size селектора. В этом случае мы будем использовать наше изображение в качестве фона для element 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; } 

Управление областью просмотра SVG с помощью свойства background-size CSS