SVG drop shadow using css3

后端 未结 7 1540
谎友^
谎友^ 2020-11-22 12:34

Is it possible to set drop shadow for an svg element using css3 , something like

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


        
相关标签:
7条回答
  • 2020-11-22 13:11

    I'm not aware of a CSS-only solution.

    As you mentioned, filters are the canonical approach to creating drop shadow effects in SVG. The SVG specification includes an example of this.

    0 讨论(0)
  • 2020-11-22 13:18

    Here's an example of applying dropshadow to some svg using the 'filter' property. If you want to control the opacity of the dropshadow have a look at this example. The slope attribute controls how much opacity to give to the dropshadow.

    Relevant bits from the example:

    <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 is defined to work on CSS boxes (read: rectangles), while svg is a bit more expressive than just rectangles. Read the SVG Primer to learn a bit more about what you can do with SVG filters.

    0 讨论(0)
  • 2020-11-22 13:18

    You can easily add a drop-shadow effect to an svg-element using the drop-shadow() CSS function and rgba color values. By using rgba color values you can change the opacity of your shadow.

    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" />

    0 讨论(0)
  • 2020-11-22 13:20

    Easiest way I've found is with feDropShadow. I will never go back to using those incredibly esoteric filter tag names that I don't understand.

    <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>
    
    0 讨论(0)
  • 2020-11-22 13:21

    Use the new CSS filter property.

    Supported by webkit browsers, Firefox 34+ and Edge.

    You can use this polyfill that will support FF < 34, IE6+.

    You would use it like so:

    /* 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>

    This approach differs from the box-shadow effect in that it accounts for opacity and does not apply the drop shadow effect to the box but rather to the corners of the svg element itself.

    Please Note: This approach only works when the class is placed on the <svg> element alone. You can NOT use this on an inline svg element such as <rect>.

    <!-- This will NOT work! -->
    <svg><rect class="shadow" ... /></svg>
    

    Read more about css filters on html5rocks.

    0 讨论(0)
  • 2020-11-22 13:27

    Probably an evolution, it appears that inline css filters works nicely on elements, in a certain way.

    Declaring a drop-shadow css filter, in an svg element, in both a class or inline does NOT works, as specified earlier.

    But, at least in Firefox, with the following wizardry:

    Appending the filter declaration inline, with javascript, after DOM load.

    // Does not works, with regular dynamic css styling:
    
    shadow0.oninput = () => {
      rect1.style.filter = "filter:drop-shadow(0 0 " + shadow0.value + "rem black);"
    }
    
    // Okay! Inline styling, appending.
    
    shadow1.oninput = () => {
      rect1.style += " ;filter:drop-shadow(0 0 " + shadow1.value + "rem black);"
      rect2.style += " ;filter:drop-shadow(0 0 " + shadow1.value + "rem black);"
    }
    <h2>Firefox only</h2>
    <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>

    0 讨论(0)
提交回复
热议问题