SVG и медиа запросы

SVG и медиа запросы

От автора: одна из удивительных возможностей SVG позволяет делать изображения адаптивными. В данной статье мы поработаем с ней.

Посмотрим на следующий код:

<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
  <style>
    circle {
      fill: green;
    }
    @media (min-width: 100px) {
      circle {
        fill: blue;
      }
    }
  </style>
  <circle cx="50" cy="50" r="50"/>
</svg>

Но когда в таком случае круг будет синим? В спецификации говорится, что значение min-width должно быть равно ширине экрана, но…

Какого экрана?

<img src="circle.svg" width="50" height="50">
<img src="circle.svg" width="100" height="100">
<iframe src="circle.svg" width="50" height="50"></iframe>
<svg width="50" height="50">
  ...as above...
</svg>

Какой из кодов выше нарисует синий круг в HTML (возможно обрезанный)? А также какое разрешение экрана нужно использовать? Будет ли это:

размер CSS документа;

атрибуты width/height/viewBox тега svg;

атрибуты width/height тега img;

размер CSS макета тега img.

Большинство браузеров скажут…

SVG масштабируется под размеры тега img, а CSS размеры img составляют видимую область в SVG. Таким образом, у первого img видимая ширина равна 50, а у второго – 100. То есть второе изображение img «подхватит» медиа запрос и станет синего цвета, а первое нет.

Для тега iframe видимой областью в SVG будет видимая область встраиваемого документа. Так в верхнем примере видимая ширина составляет 50 пикселей CSS, так как это ширина iframe.

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

А что скажет Firefox?

Firefox думает не совсем так. Этот браузер ведет себя точно так же с отдельными исключениями. Для тега img видимая область – это размер области рендеринга в пикселях устройства. Видимая область меняется в зависимости от плотности изображения. Первое изображение из демо будет зеленым на 1х экранах, и синим на 2х и выше. Тут возникает проблема, так как большинство ноутбуков и мобильных телефонов имеют плотность отображения больше 1.

Это похоже на баг, особенно когда Firefox не применяет ту же логику к iframe. Но тут стоит немного пожалеть Firefox, так как в спецификации ничего не говорится про масштабирование SVG в img, не говоря уже о том, как обрабатывать медиа запросы.

Я подал запрос на исправление ошибки в спецификации, надеюсь, ситуация прояснится. Но все становится еще сложнее, когда дело доходит до…

Рисование SVG в canvas

В canvas также можно рисовать теги img:

canvas2dContext.drawImage(img, x, y, width, height);

Но когда круг будет синим? В этот раз видимых областей немного больше. Будет ли это:

CSS размер окна;

атрибуты width/height/viewBox тега svg;

атрибуты width/height тега img;

размеры CSS макета тега img;

размеры canvas в пикселях;

размеры CSS макета тега canvas;

width/height заданные в drawImage;

width/height заданные в drawImage, умноженные на контекст 2D трансформаций.

Как вы думаете? И опять в спецификации нет точного ответа, а браузеры пойдут своими путями. Насколько я могу судить, браузеры будут делать следующее.

Chrome

Chrome возьмет атрибуты width/height из SVG документа. То есть если документ SVG говорит, что ширина width=”50”, вы получите медиа запросы на видимую область в 50px. Если же вы хотите рисовать круг с помощью медиа запросов на видимую область шириной 100px, вам не повезло. Не важно, какого размера вы нарисуете круг на canvas, он будет отрисовываться с медиа запросами под ширину 50px.

Однако если в SVG задан viewBox, а не фиксированная ширина, Chrome возьмет ширину canvas в пикселях в качестве видимой области. Вы можете сказать, что это похоже на работу с инлайновым SVG, где видимая область совпадает со всем окном браузера, но разница в поведении с viewBox действительно странная. Chrome ведет себя хуже всех.

Safari

Как и Chrome, Safari использует размер из SVG документа, что означает, что данный браузер подвержен тем же недостаткам. Однако если в SVG используется viewBox, а не фиксированная ширина, браузер высчитывает ширину из viewBox. То есть viewBox=»50 50 200 200″ даст нам ширину 150. Лучше Chrome, но очень много ограничений.

Firefox

Firefox использует width/height из drawImage, умноженные на контекстные трансформации. То есть если вы рисуете SVG на canvas шириной 300 пикселей, видимая область будет в ширину 300px.

Браузер отражает странное поведение img, основанное на отрисованных пикселях. То есть вы получите те же несостыковки в плотности отображения, если умножите ширину и высоту canvas на devicePixelRatio (и обратно уменьшите с помощью CSS), что вам сделать потребуется, чтобы изображение не было мутным на экранах с высокой плотностью пикселей.

Логика тут есть, но это означает, что ваши медиа запросы связаны с отрисованными пикселями.

Microsoft Edge

Edge для определения видимой области использует размеры макета тега img. Если у img нет макета (display: none или отсутствует в дереве документа), тогда браузер берет атрибуты width/height. Если и их нет, Edge берет внутренние размеры img.

То есть вы можете рисовать SVG на холсте 1000х1000, но если у изображения задана ширина <img width=»100″>, то видимая область будет шириной в 100px.

Я считаю, это идеальное поведение. Так вы можете активировать медиа запросы для ширины вне зависимости от отрисовываемой ширины. Также такой подход хорошо соотносится с адаптивными изображениями. Когда вы рисуете <img srcset=»…» sizes=»…»> на canvas, все браузеры говорят, что нарисованное изображение должно быть отображением текущего тега img.

Вот и все!

Я подал заявку на исправление ошибки в спецификации для поведения браузера Edge, а также предложил дополнить createImageBitmap, чтобы видимую область можно было задавать в скрипте. Надеюсь, поведение во всех браузерах станет немного лучше! Данные я собирал отсюда, а по этой ссылке можно посмотреть результаты.

Автор: Jake Archibald

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

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

Практика HTML5 и CSS3 с нуля до результата!

Получите бесплатный пошаговый видеокурс по основам адаптивной верстки с полного нуля на HTML5 и CSS3

Получить

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

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

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

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree