Отбрасывание SVG с помощью css3

Можно ли установить тень для элемента SVG с помощью CSS3, что-то вроде

box-shadow: -5px -5px 5px #888;
-webkit-box-shadow: -5px -5px 5px #888;

Я видел некоторые замечания по созданию тени с использованием эффектов фильтра. Есть ли пример использования только CSS? Ниже приведен рабочий код, в котором стиль Cusor применяется правильно, но без эффекта тени. Пожалуйста, помогите мне получить эффект тени с наименьшим количеством кода.

svg .shadow { 
  cursor:crosshair; 
  -moz-box-shadow: -5px -5px 5px #888;
  -webkit-box-shadow: -5px -5px 5px #888;
  box-shadow: -5px -5px 5px #888; 
}	
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full"  viewBox="0 0 120 70">	
    <rect class="shadow" x="10" y="10" width="100" height="50" fill="#c66" />
</svg>

Ответ 1

Вот пример применения drophadow к некоторому svg с использованием свойства filter. Если вы хотите контролировать прозрачность тени, взгляните на этот пример. Атрибут slope определяет, сколько непрозрачности дать теням.

Соответствующие биты из примера:

<filter id="dropshadow" height="130%">
  <feGaussianBlur in="SourceAlpha" stdDeviation="3"/> <!-- stdDeviation is how much to blur -->
  <feOffset dx="2" dy="2" result="offsetblur"/> <!-- how much to offset -->
  <feComponentTransfer>
    <feFuncA type="linear" slope="0.5"/> <!-- slope is the opacity of the shadow -->
  </feComponentTransfer>
  <feMerge> 
    <feMergeNode/> <!-- this contains the offset blurred image -->
    <feMergeNode in="SourceGraphic"/> <!-- this contains the element that the filter is applied to -->
  </feMerge>
</filter>
<circle r="10" style="filter:url(#dropshadow)"/>

Box-shadow определен для работы с CSS-блоками (читай: прямоугольники), тогда как svg немного более выразителен, чем просто прямоугольники. Прочтите учебник по SVG, чтобы узнать больше о том, что вы можете делать с фильтрами SVG.

Ответ 2

Используйте новое свойство filter CSS.

Поддерживается браузерами webkit, Firefox 34+ и Edge.

Вы можете использовать этот polyfill, который будет поддерживать FF <34, IE6+.

Вы бы использовали это так:

/* Use -webkit- only if supporting: Chrome < 54, iOS < 9.3, Android < 4.4.4 */

.shadow {
  -webkit-filter: drop-shadow( 3px 3px 2px rgba(0, 0, 0, .7));
  filter: drop-shadow( 3px 3px 2px rgba(0, 0, 0, .7));
  /* Similar syntax to box-shadow */
}
<img src="https://upload.wikimedia.org/wikipedia/commons/c/ce/Star_wars2.svg" alt="" class="shadow" width="200">

<!-- Or -->

<svg class="shadow" ...>
    <rect x="10" y="10" width="200" height="100" fill="#bada55" />
</svg>

Ответ 3

Итак, как упоминалось в скрытых комментариях принятого ответа Лоренцо Полидори, самый простой вариант, который работает для меня в Chrome (и я уверен, что другие браузеры Webkit):

-webkit-svg-shadow: 0 0 7px #53BE12;

Ответ 4

Самый простой способ, который я нашел, это с feDropShadow. Я никогда не вернусь к использованию тех невероятно эзотерических имен тегов фильтров, которые я не понимаю.

<filter id="shadow" x="0" y="0" width="200%" height="200%">
  <feDropShadow dx="40" dy="40" stdDeviation="35" flood-color="#ff0000" flood-opacity="1" />
</filter>

Ответ 5

Я не знаю о решении только для CSS.

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

Ответ 6

Черный текст с белой тенью

Другой способ, который я использовал для белой тени (для текста): создать клон для тени:

Примечание: для этого требуется xmlns:xlink="http://www.w3.org/1999/xlink" в объявлении SVG.

Настоящий текст находится в разделе <defs> с позицией, стилем, но без определения fill.

Реальный тест клонируется два раза: первый для тени и второй для самого текста.

<svg xmlns="http://www.w3.org/2000/svg" width="640" height="70"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
  <filter id="Blur"><feGaussianBlur stdDeviation="0.8" /></filter>
  <text style="font-family:sans,helvetica;font-weight:bold;font-size:12pt"
      id="Text"><tspan x="12" y="19">
        Black text with white shadow
    </tspan></text>
  </defs>
  <rect style="fill:#8AB" width="640" height="70" />
  <use style="fill:white;" filter="url(#Blur)" xlink:href="#Text"
      transform="translate(1.8,.9)"/>
  <use style="fill:black;" xlink:href="#Text"/>
</svg>

Ответ 7

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

Объявление фильтра css-shadow в элементе svg как в классе, так и во встроенном НЕ работает, как указано ранее.

Но, по крайней мере, в Firefox, со следующим волшебством:

После объявления DOM добавление объявления фильтра в строке с javascript.

// Does not works, with regular dynamic css styling:

shadow0.onchange = () => {
  rect1.style.filter = "filter:drop-shadow(0 0 " + shadow0.value + "rem black);"
}

// Okay! Inline styling, appending.

shadow1.onchange = () => {
  rect1.style += " ;filter:drop-shadow(0 0 " + shadow1.value + "rem black);"
  rect2.style += " ;filter:drop-shadow(0 0 " + shadow1.value + "rem black);"
}
<h4>
Does not works! 
<input id="shadow0" type="number" min="0" max="100" step="0.1">

 | Okay!
<input id="shadow1" type="number" min="0" max="100" step="0.1">

<svg viewBox="0 0 120 70">  
    <rect id="rect1" x="10" y="10" width="100" height="50" fill="#c66" />
    
    <!-- Inline style declaration does NOT works at svg level, no shadow at loading: -->
    <rect id="rect2" x="40" y="30" width="10" height="10" fill="#aaa" style="filter:drop-shadow(0 0 20rem black)" />
    
</svg>

Ответ 8

Вы можете легко добавить эффект drop-shadow к svg-элементу, используя CSS-функцию drop-shadow() и значения цвета rgba. Используя значения цвета rgba, вы можете изменить непрозрачность вашей тени.

img.light-shadow{
  filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 0.4));
}

img.dark-shadow{
  filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 1));
}
<img class="light-shadow" src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.svg" />
<img class="dark-shadow" src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.svg" />