Search code examples
svgmaterial-designsvg-filters

How can I create the material design shadows in SVG using SVG filters


I have found this SVG that creates some of the shadows but it only works in Chrome (Firefox and Safari on OS X do not display the shadows)

I'm trying to reimplement the visual look of Material Design in pure SVG for a project and I'm interested in a solution that follows as much of the design requirements from Elevation Shadows section in the Material Design Specs.

I have programatic control over the generated SVG so, if the parameters of the filters are easier to express in computations based on elevation, please specify so.


Solution

  • This is a comprehensive drop shadow filter structure that duplicates all the functionality of the drop shadow control in Photoshop. I wrote a mini-app to allow you to change any of these parameters and copy and paste the resulting filter: http://codepen.io/mullany/pen/sJopz

    <filter id="drop-shadow" color-interpolation-filters="sRGB" x="-50%" y="-50%" height="200%" width="200%">
    
    <!-- Take source alpha, offset it by angle/distance and blur it by size -->
    <feOffset id="offset" in="SourceAlpha" dx="-5.49" dy="-5.11" result="SA-offset"/> 
    <feGaussianBlur id="blur" in="SA-offset" stdDeviation="4.75" result="SA-o-blur"/>
    
    <!-- Apply a contour by using a color curve transform on the alpha and clipping the result to the input -->
    
    <feComponentTransfer in="SA-o-blur" result="SA-o-b-contIN"> 
      <feFuncA id="contour" type="table" tableValues="0 1"/> 
    </feComponentTransfer>
    
    <feComposite operator="in" in="SA-o-blur" in2="SA-o-b-contIN" result="SA-o-b-cont"/>
    
    <!-- Adjust the spread by multiplying alpha by a constant factor --> <feComponentTransfer in="SA-o-b-cont" result="SA-o-b-c-sprd"> 
      <feFuncA id="spread-ctrl" type="linear" slope="2.4"/> 
    </feComponentTransfer>
    
    <!-- Adjust color and opacity by adding fixed offsets and an opacity multiplier --> 
    <feColorMatrix id="recolor" in="SA-o-b-c-sprd" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 .8 0" result="SA-o-b-c-s-recolor"/>
    
    <!-- Generate a reasonably grainy noise input with baseFrequency between approx .5 to 2.0. And add the noise with k1 and k2 multipliers that sum to 1 --> 
    <feTurbulence result="fNoise" type="fractalNoise" numOctaves="6" baseFrequency="1.98"/> 
    <feColorMatrix in="fNoise" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 7 -3" result="clipNoise"/> 
    <feComposite id="noisemix" operator="arithmetic" in="SA-o-b-c-s-recolor" in2="clipNoise" k1="0" k2="1" result="SA-o-b-c-s-r-mix"/>
    
    <!-- Merge the shadow with the original --> 
    <feMerge> 
      <feMergeNode in="SA-o-b-c-s-r-mix"/> 
      <feMergeNode in="SourceGraphic"/> 
    </feMerge> 
    </filter>