На сайте много svg-иконок, как лучше с ними взаимодействовать?
Прочитал я про спрайты и сделал следующее:
svg {
width: 40px;
height: 40px;
}
svg:hover {
fill: red;
}
<svg display="none" xmlns="http://www.w3.org/2000/svg">
<symbol id="home" width="14" height="14" viewBox="0 0 14 14">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="14" height="14">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0.000152588H13.717V13.272H0V0.000152588Z"/>
</mask>
<g mask="url(#mask0)" >
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.92999 9.71699H7.78499V6.91199H5.92999V9.71699ZM8.28499 10.717H5.42999C5.15299 10.717 4.92999 10.493 4.92999 10.217V6.41199C4.92999 6.13599 5.15299 5.91199 5.42999 5.91199H8.28499C8.56199 5.91199 8.78499 6.13599 8.78499 6.41199V10.217C8.78499 10.493 8.56199 10.717 8.28499 10.717Z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5859 13.272H3.13092C2.85492 13.272 2.63092 13.048 2.63092 12.772V6.31601C2.63092 6.04001 2.85492 5.81601 3.13092 5.81601C3.40692 5.81601 3.63092 6.04001 3.63092 6.31601V12.272H10.0859V6.31601C10.0859 6.04001 10.3099 5.81601 10.5859 5.81601C10.8619 5.81601 11.0859 6.04001 11.0859 6.31601V12.772C11.0859 13.048 10.8619 13.272 10.5859 13.272Z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.2168 7.3584C13.0888 7.3584 12.9608 7.3094 12.8628 7.2124L6.85882 1.2074L0.853817 7.2124C0.657817 7.4074 0.341817 7.4074 0.146817 7.2124C-0.0491831 7.0164 -0.0491831 6.7004 0.146817 6.5044L6.50482 0.146403C6.69982 -0.0485974 7.01682 -0.0485974 7.21182 0.146403L13.5708 6.5044C13.7658 6.7004 13.7658 7.0164 13.5708 7.2124C13.4728 7.3094 13.3448 7.3584 13.2168 7.3584Z" />
</g>
</symbol>
<symbol id="toggle" width="28" height="22" viewBox="0 0 28 22">
<path opacity="0.5" d="M0 15.7143H28V12.5714H0V15.7143ZM0 22H28V18.8571H0V22ZM0 9.42857H28V6.28571H0V9.42857ZM0 0V3.14286H28V0H0Z" fill="black"/>
</symbol>
</svg>
<svg>
<use href="#home"></use>
</svg>
<svg>
<use href="#toggle"></use>
</svg>
Спрайт выношу в отдельный файл и ссылаюсь на иконки из него, например, вот так:
<use href="assets/sprite.svg#home"></use>.
Как видно в примере выше, к одной иконке применяются стили при наведении, а ко второй нет. Почему так? Хотелось бы в целом узнать как я ограничен используя подобный способ. Что могу анимировать, а что нет. Правильно ли я вообще делаю?
Ещё не совсем понятно, как работает следующее:
svg:hover {
fill: red;
}
Конкретно к тегу svg применяется стиль и дальше этот стиль наследуется дочерними элементами?
Ну и ещё вопрос: почему не применяется стиль при наведении?
svg {
width: 40px;
height: 40px;
}
.first-line {
stroke: red;
}
svg:hover .first-line {
stroke: green;
}
<svg display="none" xmlns="http://www.w3.org/2000/svg">
<symbol id="toggle">
<path class="first-line" d="M0 5 H 90" />
<path class="second-line" d="M0 10 H 90" stroke="black"/>
<path class="third-line" d="M0 15 H 90" stroke="black"/>
</symbol>
</svg>
<svg id="xxx" width="60px" viewBox="0 0 16 24"><use xlink:href="#toggle"/></svg>
Ответы (2 шт):
Когда вы используете команду <use> SVG попадает, в так называемый Shadow DOM.
SVG вроде, как есть и нет его в тоже время. Так как на него хранится из основного DOM только ссылка.
Поэтому нужно, чтобы свойства fill, stroke, stroke-width принудительно наследовались.
path {
fill:inherit;
stroke:inherit;
}
В примере ниже я присвоил каждому <use> клону иконки свой класс и теперь их можно стилизовать вместе и по отдельности при наведении :hover
svg {
width: 40px;
height: 40px;
}
path {
fill:inherit;
stroke:inherit;
}
use.home, use.toggle {
fill: black;
}
use.home:hover {
fill:red;
}
use.toggle:hover {
fill: green;
}
<svg display="none" xmlns="http://www.w3.org/2000/svg">
<symbol id="home" width="14" height="14" viewBox="0 0 14 14">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="14" height="14">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0.000152588H13.717V13.272H0V0.000152588Z"/>
</mask>
<g mask="url(#mask0)" >
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.92999 9.71699H7.78499V6.91199H5.92999V9.71699ZM8.28499 10.717H5.42999C5.15299 10.717 4.92999 10.493 4.92999 10.217V6.41199C4.92999 6.13599 5.15299 5.91199 5.42999 5.91199H8.28499C8.56199 5.91199 8.78499 6.13599 8.78499 6.41199V10.217C8.78499 10.493 8.56199 10.717 8.28499 10.717Z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5859 13.272H3.13092C2.85492 13.272 2.63092 13.048 2.63092 12.772V6.31601C2.63092 6.04001 2.85492 5.81601 3.13092 5.81601C3.40692 5.81601 3.63092 6.04001 3.63092 6.31601V12.272H10.0859V6.31601C10.0859 6.04001 10.3099 5.81601 10.5859 5.81601C10.8619 5.81601 11.0859 6.04001 11.0859 6.31601V12.772C11.0859 13.048 10.8619 13.272 10.5859 13.272Z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.2168 7.3584C13.0888 7.3584 12.9608 7.3094 12.8628 7.2124L6.85882 1.2074L0.853817 7.2124C0.657817 7.4074 0.341817 7.4074 0.146817 7.2124C-0.0491831 7.0164 -0.0491831 6.7004 0.146817 6.5044L6.50482 0.146403C6.69982 -0.0485974 7.01682 -0.0485974 7.21182 0.146403L13.5708 6.5044C13.7658 6.7004 13.7658 7.0164 13.5708 7.2124C13.4728 7.3094 13.3448 7.3584 13.2168 7.3584Z" />
</g>
</symbol>
<symbol id="toggle" width="28" height="22" viewBox="0 0 28 22">
<path opacity="0.5" d="M0 15.7143H28V12.5714H0V15.7143ZM0 22H28V18.8571H0V22ZM0 9.42857H28V6.28571H0V9.42857ZM0 0V3.14286H28V0H0Z" fill="black"/>
</symbol>
</svg>
<svg>
<use class="home" href="#home" ></use>
</svg>
<svg>
<use class="toggle" href="#toggle" ></use>
</svg>
Ну и ещё вопросец: почему не применяется стиль при наведении?
Всё по той же причине, что и в первом примере. Надо сначала прописать принудительное наследование inherit
svg {
width: 30vw;
height: 30vh;
}
path {
fill:inherit;
stroke:inherit;
}
use.tog {
stroke:black;
}
use.tog:hover {
stroke:green;
cursor:pointer;
}
/* Работает только в Firefox
.first-line:hover{
stroke:green;
cursor:pointer;
}
.second-line:hover {
stroke:blue;
cursor:pointer;
}
.third-line:hover {
stroke:gold;
cursor:pointer;
}*/
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="toggle">
<path class="first-line" d="M0 5 H 90" stroke-width="2" />
<path class="second-line" d="M0 10 H 90" stroke-width="2" />
<path class="third-line" d="M0 15 H 90" stroke-width="2" />
</symbol>
</svg>
<svg id="xxx" viewBox="0 0 16 24">
<use class="tog" xlink:href="#toggle" href="#toggle" ></use>
</svg>
Сейчас идет переходной период, некоторые браузеры перешли на короткую запись только href Другие браузеры не перешли (IOS Safari) и поэтому понимают только xlink:href=""
С другой стороны, когда будет принят стандарт SVG2 длинная запись будет запрещена
Поэтому уже сейчас часто вижу комбинированную запись:
<use class="tog" xlink:href="#toggle" href="#toggle" ></use>
Если вы хотите, чтобы у вас работала анимация, то сразу пропишите её внутри svg файла, до клонирования SVG командой USE
Update
Несколько практических советов:
Если вы сделали всё правильно, но одна или несколько иконок не поддаются стилизации, то логично предположить, что всё дело в иконке.
- Во первых удалите все стили внутри иконки, так как у SVG довольно сложная схема иерархии стилей. Например если внутри иконки прописан атрибут представления
<path ...style="fill:black" />, то вы не сможете его изменить внешними стилями CSS
Конечно можно применить!importantcss но это очень опасный метод. - Необходимо посмотреть код используемой иконки. Если есть внутри
clip-Pathmask,pattern,filter,gradientто это прямой путь к проблемам стилизации. - Элементы SVG нарисованы двойными контурами. То есть иконку рисовали не подходящими инструментами (карандаш, кисть) Такую иконку тоже будет проблематично стилизовать. Будет закрашиваться не объем, а узкое расстояние между контурами.
- Иконка в формате
base64стилизуется только с помощью фильтров. - Главный признак, чем больше код (>1kb) тем более вероятно, что иконка нарисована не профессионалом и с ней неизбежно будут проблемы.
- Иконки взятые из разных мест имеют разные
viewBox, разную структуру внутреннего кода<defs>,<symbol>,<g>подгоняя их под один размер опять возникают проблемы с позиционированием.
Вывод один, чтобы избежать всей этой головной боли, нужно серьезно подходить к выбору иконок, использовать иконки, сделанные профессионалами и из одного набора.
Ниже набор ссылок откуда вы можете скачать стандартные иконки практически для всех целей:
Есть ещё один способ добавлять иконки SVG в свой проект, не размещая их код в HTML, не добавляя спрайты и не мучиться со стилизацией иконок. Всё будет в штатном порядке, как вы привыкли работать с CSS.
Во многих случаях можно использовать символьный шрифт svg иконок от Google, состоящий из 900 иконок.
Подключение и использование шрифта от Google не составит труда
- Подключение шрифта:
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet">
- Выбирать иконки по названиям можно здесь
- Пример использования гугловского символьного шрифта:
i {
margin: 100px 20px 50px 40px;
transition: transform 1s ease-in-out;
}
i:hover {
transform: scale(5) rotateZ(360deg);
color:crimson;
}
.purple{color:purple}
.green{color:green}
.blue{color: dodgerblue}
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<i class="material-icons purple">menu</i>
<i class="material-icons green">sync</i>
<i class="material-icons blue">stars</i>