В очередном проекте мы пробуем встраивать на страницы графику в виде SVG. Заказчик не требует полной поддержки старых браузеров, но ожидает в них доступность основного контента. Для некоторых пиктограмм мы выбрали inline SVG, так как можем легко управлять их внешним видом через стили и даже трансформировать их.
Все изображения собраны в одном SVG-файле shapes.svg
.
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
<defs>
<rect id="shape-rectangle" x="1" y="1" width="30" height="30"/>
<circle id="shape-circle" cx="16" cy="16" r="24"/>
</defs>
</svg>
Тут у нас две фигуры: квадрат и круг. Чтобы в дальнейшем мы могли сослаться на них, у каждой фигуры должны быть уникальные значения id
. Забегая вперёд скажу, что их уникальность должна быть не только в пределах SVG, но и в пределах всего документа, где в дальнейшем будет отображаться эта иконка.
На заметку:
Все фигуры определены внутри тега <defs> . Они не будут отображаться, если попытаться открыть этот файл в каком-нибудь редакторе или просмотрщике. На них можно только сослаться. Несколько контуров могут быть объединены в одну фигуру с помощью тега <g>.
Затем в HTML можно сослаться на заготовленные контуры
<svg xmlns="http://www.w3.org/2000/svg"
style="width: 32px; height: 32px;">
<use xlink:href="shapes.svg#shape-rectangle"></use>
</svg>
Браузер отобразит квадрат в блоке размером 32 на 32 пиксела. Габариты блока, разумеется, нужно задавать с помощью CSS. В данном примере я указал их в атрибуте style
только для наглядности.
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="-9 -9 50 50"
style="width: 32px; height: 32px;">
<use xlink:href="shapes.svg#shape-circle"></use>
</svg>
C кругом чуть сложнее так как он не вписывается в желаемые габариты 32 на 32 пиксела. Поэтому inline SVG нужно указать атрибут viewBox. Браузер сам правильно смасштабирует фигуру до размеров блока.
Подводные камни
При использование inline SVG нужно знать и помнить несколько особенностей.
Поддержка
Все современные браузеры прекрасно справляются с базовыми конструкциями SVG. Если вам нужны какие-то особенные фильтры, то стоит протестировать их отдельно.
Internet Explorer
Мы обнаружили, что ссылка на внешний SVG-файл с контурами не работает, если страница отображается в IE. Это известное поведение и исправить хаками его нельзя. Остаётся только явно включить этот SVG в HTML страницу. Соответственно при использовании в
<use xlink:href="#shape-rectangle"></use>
остаётся один якорь (для этого и нужна была уникальность id
).
Если SVG-файл с картинками стал достаточно большим и его уже обременительно каждый раз передавать на странице, то его специально для IE можно загружать динамически и затем уже вставлять на страницу.
<script id="svg-loader">
$.ajax({url: "shapes.svg", cache: true, dataType: "html"})
.done(function (data) {
$("#svg-loader").before(data);
$(".svg-icon > use").attr("xlink:href", function (i, href) {
return href.substr(href.indexOf("#"));
});
});
</script>
Важно, чтобы браузер доставал файл из своего кеша, если это возможно.
Ещё важно, чтобы в SVG разметке не было самозакрывающихся тегов. Нужно явно указывать закрывающий тег, если нет контента. Старые парсеры HTML-супа допускали лишь ограниченное количество самозакрывающихся тегов (
<hr/>
, <br/>
, <input/>
и т.п.) — поэтому мы не можем писать <div/>
. Конструкции SVG могут поломать весь документ при определённом стечении обстоятельств.
Коментарии к заметке
Хм-м, а какие проблемы? Я замечал только проблемы с
<use/>
в Сафари 6: не работал, пока не развернёшь в<use></use>
.Посмотри какое дерево получится, если открыть файл типа:
С некоторыми SVG-тегами в старых IE (реальных, а не в режиме эмуляции) происходит примерно тоже самое. Пробовал создавать теги с помощью JS, как это делается для HTML5 элеметов, — никаких изменений не происходит. Я не выяснил ещё как конкретно и от чего оно ломается, но когда нет самозакрывающихся тегов, то DOM строится правильно.
Старые же IE просто не понимают нестандартные теги.
Проблема где-то глубже. Читай комент выше.
Я ещё подозреваю Modernizr в набросе на вентилятор. Опять же никаких улик и доказательств нет. Тесты писать не было времени.
URL из файла не работает в iOS 5.
Ещё выяснилось, что если SVG динамически добавить после загрузки страницы, то иконки не отобразятся в iOS 6. Ни какие трюки с обновлением атрибутов не помогли.
Я бы сказал, что старые парсеры супа вообще не допускали самозакрывающихся тегов:). Они тупо игнорировали концевой слеш как недопустимый атрибут, а также знали ограниченный набор элементов, не нуждающихся в закрывающем теге (пустых). Новый парсер по стандарту обязан знать «foreign elements» (в т.ч. SVG), для которых концевой слеш означает честное «самозакрытие», а в прочих тегах концевой слеш по-прежнему игнорируется (хотя для пустых элементов допускается). Но это если браузер соблюдает стандарт. IE9, к сожалению, не соблюдает.
SelenIT, спасибо за уточнение.