Astronaut
Astronaut

Reputation: 7031

SVG path with border

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

Upvotes: 17

Views: 40822

Answers (1)

Ruskin
Ruskin

Reputation: 6161

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

Upvotes: 18

Related Questions