Трюк на CSS для поддержки SVG в старых браузерах

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

Очевидный недостаток способа состоит в том, что мы должны отдельно позаботиться о том, чтобы нужный нам класс был — при генерации страницы на сервере или же определив браузер с помощью JS.

Второй очевидный недостаток состоит в том, что способ не годится для других браузеров без поддержки инлайнового SVG, например, Оперы Мини и Андроидов 2.x.

Мне стало интересно: можно ли обеспечить поддержку во всех старых браузерах, используя только CSS?

И, кажется, я нашла решение. Оно странное, но работает. Меня интересовала его работоспособность в следующих браузерах:

  • IE8 и 9
  • Android 2.x
  • Opera 12, Opera Mini

Тестировалось вот на такой конструкции:

SVG:

<svg xmlns="http://www.w3.org/2000/svg" class="svg-icon">
    <circle r="55" cx="50%" cy="50%" fill="yellowgreen"/>
    <text x="50%" y="50%" dy=".4em" text-anchor="middle"
          style="font: 38px/1 Trebuchet MS; fill: #FFF">SVG</text>
</svg>

CSS:

.svg-icon {
    display: inline-block;
    margin: 3em 2em;
    width: 180px;
    height: 130px;
    background: url(https://img-fotki.yandex.ru/get/5807/5091629.a3/0_86371_b2660de0_orig)
                no-repeat center center;
    border: 1px solid #555;
    }

Если SVG не поддерживается браузером, мы увидим — только эту фоновую картинку:

Если поддерживается — и фон, и SVG. Если вы смотрите страницу в современном браузере, демо покажет вам именно этот вариант:

See the Pen Test support of SVG fallback by yoksel (@yoksel) on CodePen.

На самом деле, в браузерах без поддержки SVG также будет виден текст “SVG”, но в реальной жизни это вряд ли будет проблемой, если только вы не кладете текст в иконки.

Задача состоит в том, чтобы в браузерах с поддержкой SVG убирать фон.

Картинки для понятности:

— сейчас демо выглядит вот так

— так оно должно выглядеть в браузерах без поддержки SVG

— а вот так в браузерах, где SVG поддерживается

То есть по умолчанию всегда показывается PNG-заглушка, и её нужно скрыть только в современных браузерах. Нам нужна некая конструкция в CSS, поддержка которой в разных браузерах совпадает с поддержкой SVG.

Первым делом в голову приходит вариант с множественными фонами, например:

background: none, none;

Хороший вариант, но браузеры Android 2.x понимают множественные фоны и не понимают SVG, поэтому в них при таком способе на странице не будет ни того, ни другого.

Ссылка для тестирования: http://codepen.io/yoksel/full/FirKg.

Следующая идея убирать фон с помощью невидимого градиента.

Примерный код:

background: linear-gradient(transparent, transparent);

Способ работает везде, где нужно, кроме IE9 — он не понимает градиенты, поэтому в нем будут отображаться и SVG, и фон.

Ссылка для тестирования: http://codepen.io/yoksel/full/fxCzH.

Нужно какое-то решение, которое уберет фон в IE9 и ничего не поломает в остальных.

Мне не удалось найти ничего подходящего в CSS-свойствах для управления фоном, но зато кое-что интересное неожиданно обнаружилось в единицах измерения.

Если для управления размерами или положением фона использовать единицы вьюпорта — vw или vh, браузеры Android 2.x и Opera Mini полностью проигнорируют свойство, где они содержатся. То есть можно написать:

background-position: -1000vh 0;

и этот код уберет фоновое изображение в IE9.

Не все браузеры понимают единицы вьюпорта, так что в финальной версии кода нужно комбинировать оба последних способа:

background: linear-gradient(transparent, transparent); /* современные браузеры кроме IE9 */
background-position: -1000vh 0; /* IE9 */

Демо:

See the Pen Test support of SVG fallback by yoksel (@yoksel) on CodePen.

Ссылка для тестирования: codepen.io/yoksel/full/tKzeB

Возможно, я что-то упустила, но на данный момент мои тесты показывают, что этот способ работает.

Браузеры, где проверяла:

  • IE8 и 9
  • Android 2.3
  • Opera 12, Opera Mini

Для проверки в Android 2.3 я использовала browserstack.com/screenshots, выбрав там Samsung Galaxy S2. Буду признательна, если кто-то потестит на реальном девайсе и сообщит о результатах.

Вообще если у вас есть возможность потестить демо на устройствах, где может быть проблема с инлайновым SVG, — проверьте, пожалуйста, и сообщите как оно там — этот способ на данный момент нуждается в основательном тестировании.

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

Ссылки по теме:
The invisible gradient technique: Cross-browser support for SVG (with image fallback) using CSS
Грабли на чистом SVG
svg_fallback (plugin)
Зачем я написала плагин для Grunt
Using SVG on Android 2.x
Если вы нашли ошибку или неточность, вы можете отредактировать статью с помощью prose.io, а также можно написать мне в комментариях или в Twitter.
Система комментирования от Disqus