How do I add a drop shadow to an SVG path element? - css

I've been attempting to apply a drop shadow to my SVG Path. I googled across the filter option which when applied to path by applying: -webkit-filter: drop-shadow( -5px -5px 10px #000 ); which didn't seem to get applied.
Here's a fiddle with my SVG path demonstrating the problem

Within your JSFiddle, I deleted your CSS and added a filter definition. It seems to work:
<svg width="100%" height="300px">
<defs>
<filter id="filter1" x="0" y="0">
<feOffset result="offOut" in="SourceAlpha" dx="-5" dy="-5" />
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="3" />
<feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
</defs>
<path stroke-linejoin="round" stroke-linecap="round" stroke="red" stroke-opacity="1" stroke-width="5" fill="none" class="leaflet-clickable" d="M1063 458L1055 428L1034 433L1030 421L1017 423L911 452L895 455L885 441L859 424L809 410L788 394L774 377L744 309L730 313L727 304L669 319L599 341L596 331L491 364L488 357L498 343L490 343L450 352L417 256L371 270L366 253L355 256L351 242L217 282L194 210L191 196L166 113L45 147L44 140L13 150" filter="url(#filter1)"></path>
</svg>
Maybe a few tweaks to the dx, dy, and stdDeviation values will get it just the way you want.

Related

How can I add a specific box shadow to my svg?

So I know there is a question similar to this: How to add box-shadow to a svg path circle shape but I am having trouble understanding how they transitioned the box shadow characteristics to the svg drop shadow characteristics. (Especially as SVG Drop shadows don't have the concept of a spread radius.)
I am trying to get this exact box shadow: box-shadow: 0px 10px 25px 0px rgba(18, 103, 17, 0.15);
And I currently have:
<svg width="250" height="250">
<defs>
<filter id="drop-shadow">
<feGaussianBlur in="SourceAlpha" stdDeviation="25" />
<feOffset dx="0" dy="10" result="offsetblur" />
<feOffset dx="-10" dy="0" result="offsetblur" />
<feFlood flood-color="rgba(18, 103, 17, 0.15)" flood-opacity="1" />
<feComposite in2="offsetblur" operator="in" />
<feMerge>
<feMergeNode />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<circle cx="112.53" cy="112.53" r="87" fill="none" stroke="#74C947" stroke-width="25.53" style="filter: url(#drop-shadow);"></circle>
</svg>
Also if I can just use box-shadow css on the svg circle I'm happy to do so, but that doesn't seem to be an option (it only allows drop shadows).
Add a class to the svg and define the shadow in the class.
<svg class='svg-shadow'>...</svg>
.svg-shadow {
box-shadow: 10px 5px 5px #000;
}
In the specification for box shadow it says...
...the image that would be generated by applying to the shadow a Gaussian blur with a standard deviation equal to half the blur radius
So if you want to create a drop shadow in SVG you need to divide the box shadow blur radius (in your case 25px) by two and therefore you want stdDeviation="12.5"
Note that you can simplify your code.
SVG actually has a feDropShadow element so you could just use that
<svg width="250" height="250">
<defs>
<filter id="drop-shadow">
<feDropShadow stdDeviation="12.5" dx="10" dy="-10" flood-color="rgba(18, 103, 17, 0.15)" />
</filter>
</defs>
<circle cx="112.53" cy="112.53" r="87" fill="none" stroke="#74C947" stroke-width="25.53" style="filter: url(#drop-shadow);"></circle>
</svg>
but there's an even easier way using the canned drop-shadow filter i.e.
<svg width="250" height="250">
<circle cx="112.53" cy="112.53" r="87" fill="none" stroke="#74C947" stroke-width="25.53" style="filter: drop-shadow(10px -10px 12.5px rgba(18, 103, 17, 0.15))"></circle>
</svg>

Circular arrows with gradient

I tried to make it with border but gradient makes it impossible. Maybe I can make four divs and make it like that?
CSS might not be the best way to create such shapes. You should use SVG instead.
We can use SVG's path element to create a pointing arrow like shape and fill it with gradient created with linearGradient.
Only one attribute d is used to define shapes in path element. This attribute itself contains a number of short commands and few parameters that are necessary for those commands to work.
Here is a detailed information about SVG paths:
body {
text-align: center;
background: #333;
margin: 20px;
}
<svg width="400" height="400" viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0" stop-color="#212121"></stop>
<stop offset="1" stop-color="#a7a7a7"></stop>
</linearGradient>
<path id="arrow" x="0" y="0" d="M0,200
A200,200 0, 0, 1, 200,0
L225,25
L200,50
A150,150, 0, 0, 0 50,200
L25,175" fill="url(#gradient)" />
</defs>
<use xlink:href="#arrow" transform="translate(0,400) rotate(270)"></use>
<use xlink:href="#arrow" transform="translate(400,400) rotate(180)"></use>
<use xlink:href="#arrow" transform="translate(400,0) rotate(90)"></use>
<use xlink:href="#arrow"></use>
</svg>

SVG artwork clipped on right edge

I am fairly new to SVG, and the part that always confuses me is the size of the SVG and the clipping at the edges. I have an SVG square in the below checkbox art I was trying to add a dropshadow to:
Turned out the code to do this is simple; but the right edge is clipped off. I tried various combinations of widths and such, no luck. What am I missing?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">
<defs>
<filter id="blurFilter" y="-5" height="40">
<feOffset in="SourceAlpha" dx="3" dy="3" result="offset2" />
<feGaussianBlur in="offset2" result="blurredRect" stdDeviation="2" y="-"/>
<feMerge>
<feMergeNode in="blurredRect" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<g width="30" height="30" stroke="#00B140" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none" >
<rect x="2" y="2" height="20" width="20" style="stroke: #3E53A4; fill: none; stroke-width=2px;filter: url(#blurFilter);" />
<path id="check" d="M21.542 11.271l-9.063 8.458-3.021-3.021"/>
</g>
</svg>
</body>
</html>
you need to set width on the filter:
<filter id="blurFilter" y="-5" height="40" width="40">
fiddle
for an explanation you can look into filter feOffset definition;
shortly the reason is this filter primitive offsets the input image relative to its current position in the image space by the specified vector.
updated fiddle based on Holgerwill's comment

hand drawing (crayon) style for SVG path?

The SVG path usually looks like a solid line:
Is it possible to implement a hand-drawing (crayon) style for SVG path?
You can try something like this using svg's filter
<svg width="1000" height="500">
<defs>
<filter id="filter" height="2" width="2">
<feTurbulence baseFrequency="0.2" numOctaves="3" type="fractalNoise" />
<feDisplacementMap scale="80" xChannelSelector="R" in="SourceGraphic" />
</filter>
</defs>
<path d="m 100 100 l 200 10" stroke="black" stroke-width="20" style="filter:url(#filter)"/>
If you don't want the edges clipped and want a more solid stroke, then you can tweak Akshay's settings by setting filterUnits in userSpace and reducing the displacement scale like so:
<svg width="1000" height="500">
<defs>
<filter id="filter" filterUnits="userSpaceOnUse" x="-5" y="-5" height="200" width="2000">
<feTurbulence baseFrequency="0.2" numOctaves="3" type="fractalNoise" />
<feDisplacementMap scale="8" xChannelSelector="R" in="SourceGraphic" />
</filter>
</defs>
<path d="m 100 100 l 200 10" stroke="black" stroke-width="20" style="filter:url(#filter)"/>

Creating a linear gradient SVG filter

Essentially I'm trying to create an gradient alpha mask in using SVG and CSS (like this), and since the mask property is no longer on the standards track I'm exploring the filter route.
I've created a vertical alpha mask in Sketch, with the top being 0% #000000 and the bottom being 100% #000000, then exported it as an SVG and tweaked it using guidance from this O' Reilly article. It now looks like this:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<!-- Start by creating our vertical linear gradient -->
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="alphaLinear">
<stop offset="0%" style="stop-color: #000000; stop-opacity: 0%;" />
<stop offset="100%" style="stop-color: #000000; stop-opacity: 100%;" />
</linearGradient>
<!-- Create a rectangle and apply the gradient as its fill -->
<rect id="boxRect" x="0" y="0" width="100%" height="200" style="fill: url(#alphaLinear);" />
<!-- Using that rectangle, we'll create a filter -->
<filter id="alphaGrad">
<feImage xlink:href="#boxRect" result="grad"/>
<feDisplacementMap scale="10" xChannelSelector="R" yChannelSelector="G" in="SourceGraphic" in2="grad"/>
</filter>
</defs>
<use id="gradientBox" fill="url(#alphaGradient)" xlink:href="#boxRect"></use>
</svg>
My knowledge of SVG isn't the greatest so I'm suspecting this is where I've gone wrong.
Next, I applied the filter using filter (and -webkit-filter) along with referencing the filter ID #alphaGrad:
-webkit-filter: url('http://blahblah.com/alphagradient.svg#alphaGrad');
But, of course, this it doesn't work. Can anyone help me get the hang of this? Or is this even possible? If not, can someone recommend a method of how to achieve this?
Thanks in advance!
Update: here's a pretty basic fiddle of what I'm doing...
There are many errors and misconceptions in your example (why did you think a displacementMap would help you?)
Why don't you start from the code below - pure SVG using an SVG mask and an SVG image.
<svg width="600px" height="600px" viewbox="0 0 600 600">
<defs>
<linearGradient id="alphaLinear">
<stop offset="0%" stop-color="#FFFFFF" stop-opacity="0%" />
<stop offset="100%" stop-color="#999999" stop-opacity="100%" />
</linearGradient>
<mask id="Mask">
<rect x="0" y="0" width="600" height="600" fill="url(#alphaLinear)" />
</mask>
</defs>
<image xlink:href="http://upload.wikimedia.org/wikipedia/commons/7/71/Anadama_bread_(1).jpg" width="600" height="600" x="0" y="0" preserveAspectRatio="xMinYMin meet" mask="url(#Mask)"/>
</svg>
Few remarks:
SVG (and CSS) opacity value is not percertentual range but 0.0 - 1.0 range.
Mentioned mask property appears to be just prefixed in Webkit and unprefixed in Gecko.
If your target environment is HTML + CSS, you might not necessarily need SVG: you could get similar effect using linear-gradient and RGBA
background-image: linear-gradient(to bottom, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 50%); on some overlay (pseudo) element. pointer-events: none; could be useful then.

Resources