Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SVG path with border

Tags:

css

svg

How can I create a path with a fill and outline similar to enter image description here

So far I have found a couple of ways but none that is particularly clean.

One way would be to use paint-order but this does not work in mobile and IE.

Another way duplicate the path... but this would create needless amounts of data.

Is there a different way to use CSS to simply create an outline or border for an SVG path?

<svg height="50" width="300">
    <path d="M5 20 1215 20" />
</svg>

path {
  fill: red;
  stroke: #646464;
  stroke-width:10px;
  stroke-linejoin: round;
}

Here is a codepen

like image 320
Astronaut Avatar asked Feb 01 '17 15:02

Astronaut


People also ask

How do you add a border to SVG?

Try adding CSS filter() dropshadow (this can be applied on any svg: <img> , background-image , in the dom, etc.) Or, create some javascript function that clones each of the elements within the svg, removing fill/stroke attributes, and wrapping them in a g tag that has fill="none" and stroke attributes set.

Why does my SVG have a border?

This is caused by the svg renderer in browsers trying to smooth out your svg images.

Is it possible to draw any path in SVG?

The element in SVG is the ultimate drawing element. It can draw anything! I've heard that under the hood all the other drawing elements ultimately use path anyway. The path element takes a single attribute to describe what it draws: the d attribute.


1 Answers

You have to draw the path as an outline as so:

<svg xmlns="http://www.w3.org/2000/svg" width="220" height="220" viewBox="0 0 220 220">
    <path fill="#ddd" stroke="#3f4141" d="M0 0h220v220H0z"/>
    <path fill="#fff" stroke="#00b400" stroke-width="4" 
     d="M 159.8 30.3
        h -110
        v 120
        h-20
        l 30 40 
          30 -40
        h-20
        v-100
        h90"/>
</svg>

Sketched in Inkscape, optimised in SVGOMG then tweaked by hand.

EDIT

I have a working solution using markers that works as follows:

  • Create the line (any line) as a symbol
  • Create a faux - stroke by layering two instances of the line on top of each other, with different line widths
  • Add arrow with pre-defined stroke as marker
  • Hairline stroke shows through sometimes at start of line ... solve this using another marker that masks using the background color.
    • this technique would only work over a plain background.

<svg style="display: inline-block; margin-left: 2em;" width="220" height="220" viewBox="0 0 220 220" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <style>
      .arrow-stroke {
        stroke: #00b400;
        stroke-width: 28;
        /* marker-end etc should be supported but unsure of browser support */
      }
      .arrow-fill {
        stroke: white;
        stroke-width: 20
      }
    </style>
    <marker id="arrow" markerWidth="45" markerHeight="70" refX="5" refY="35" orient="auto" markerUnits="userSpaceOnUse">
      <path fill="#fff" stroke="#00b400" stroke-width="4" d="M 2 25  v-20  l 40,30 -40,30 v-20"/>
    </marker>

    <!-- Used to hide hairline that shows through, fill color must match background color -->
    <marker id="startMask" markerWidth="2" markerHeight="30" refX="1" refY="15" orient="auto" markerUnits="userSpaceOnUse">
      <path fill="#ddd" d="M0 0 v30 h2 v-30 z" />
    </marker>
    
    <symbol id="line">
      <path d="M 159.8 30.3  h -110 v 120"/>
    </symbol>

    <symbol id="line2">
      <path d="M 140 60 l 20 30"/>
    </symbol>
    <symbol id="line3">
      <path d="M 100 80 q 0 40 20 70"/>
    </symbol>
  </defs>
  
  <path id="grey-box" fill="#ddd" stroke="#3f4141" d="M0 0h220v220H0z"/>
  
  <g fill="none">
    <use xlink:href="#line" class="arrow-stroke" />
    <use xlink:href="#line" class="arrow-fill" marker-end="url(#arrow)" marker-start="url(#startMask)" />
  
    <use xlink:href="#line2" class="arrow-stroke" />
    <use xlink:href="#line2" class="arrow-fill" marker-end="url(#arrow)" marker-start="url(#startMask)" />
  
    <use xlink:href="#line3" class="arrow-stroke" />
    <use xlink:href="#line3" class="arrow-fill" marker-end="url(#arrow)" marker-start="url(#startMask)" />
  </g>
</svg>

Hope this helps

like image 127
Ruskin Avatar answered Oct 17 '22 13:10

Ruskin