Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you control how an SVG's stroke-width is drawn?

Tags:

offset

svg

rect

People also ask

How do I change the stroke width in SVG?

You can add a stroke with stroke="black" stroke-width="10" and then adjust your viewBox accordingly.

What displays the width of the stroke?

Distance is the answer.

How do you increase stroke width?

To use the Illustrator width tool, select the button in the toolbar or hold Shift+W. To adjust the width of a stroke, click and hold any point along the stroke path. This will create a width point. Pull up or down on these points to expand or contract that segment of the stroke.

What is stroke and stroke width?

The stroke-width attribute is a presentation attribute defining the width of the stroke to be applied to the shape.


No, you cannot specify whether the stroke is drawn inside or outside an element. I made a proposal to the SVG working group for this functionality in 2003, but it received no support (or discussion).

SVG proposed stroke-location example, from phrogz.net/SVG/stroke-location.svg

As I noted in the proposal,

  • you can achieve the same visual result as "inside" by doubling your stroke width and then using a clipping path to clip the object to itself, and
  • you can achieve the same visual result as 'outside' by doubling the stroke width and then overlaying a no-stroke copy of the object on top of itself.

Edit: This answer may be wrong in the future. It should be possible to achieve these results using SVG Vector Effects, by combining veStrokePath with veIntersect (for 'inside') or with veExclude (for 'outside). However, Vector Effects are still a working draft module with no implementations that I can yet find.

Edit 2: The SVG 2 draft specification includes a stroke-alignment property (with center|inside|outside possible values). This property may make it into UAs eventually.

Edit 3: Amusingly and dissapointingly, the SVG working group has removed stroke-alignment from SVG 2. You can see some of the concerns described after the prose here.


UPDATE: The stroke-alignment attribute was on April 1st, 2015 moved to a completely new spec called SVG Strokes.

As of the SVG 2.0 Editor’s Draft of February 26th, 2015 (and possibly since February 13th), the stroke-alignment property is present with the values inner, center (default) and outer.

It seems to work the same way as the stroke-location property proposed by @Phrogz and the later stroke-position suggestion. This property has been planned since at least 2011, but apart from an annotation that said

SVG 2 shall include a way to specify stroke position

, it has never been detailed in the spec as it was deferred - until now, it seems.

No browser support this property, or, as far as I know, any of the new SVG 2 features, yet, but hopefully they will soon as the spec matures. This has been a property I personally have been urging to have, and I'm really happy that it's finally there in the spec.

There seems to be some issues as to how to the property should behave on open paths as well as loops. These issues will, most probably, prolong implementations across browsers. However, I will update this answer with new information as browsers begin to support this property.


I found an easy way, which has a few restrictions, but worked for me:

  • define the shape in defs
  • define a clip path referencing the shape
  • use it and double the stroke with as the outside is clipped

Here a working example:

<svg width="240" height="240" viewBox="0 0 1024 1024">
<defs>
	<path id="ld" d="M256,0 L0,512 L384,512 L128,1024 L1024,384 L640,384 L896,0 L256,0 Z"/>
	<clipPath id="clip">
		<use xlink:href="#ld"/>
	</clipPath>
</defs>
<g>
	<use xlink:href="#ld" stroke="#0081C6" stroke-width="160" fill="#00D2B8" clip-path="url(#clip)"/>
</g>
</svg>

You can use CSS to style the order of stroke and fills. That is, stroke first and then fill second, and get the desired effect.

MDN on paint-order: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/paint-order

CSS code:

paint-order: stroke;

Here's a function that will calculate how many pixels you need to add - using the given stroke - to the top, right, bottom and left, all based on the browser:

var getStrokeOffsets = function(stroke){

        var strokeFloor =       Math.floor(stroke / 2),                                                                 // max offset
            strokeCeil =        Math.ceil(stroke / 2);                                                                  // min offset

        if($.browser.mozilla){                                                                                          // Mozilla offsets

            return {
                bottom:     strokeFloor,
                left:       strokeFloor,
                top:        strokeCeil,
                right:      strokeCeil
            };

        }else if($.browser.webkit){                                                                                     // WebKit offsets

            return {
                bottom:     strokeCeil,
                left:       strokeFloor,
                top:        strokeFloor,
                right:      strokeCeil
            };

        }else{                                                                                                          // default offsets

            return {
                bottom:     strokeCeil,
                left:       strokeCeil,
                top:        strokeCeil,
                right:      strokeCeil
            };

        }

    };