Consider 2 html svg paths , a square (class inside
) and a rectangle (class outside
) having same height. When I apply stroke-width: 10px
, the stroke gets applied 5px
inside and 5px
outside. Fiddle
How do I stroke only inside or only outside?
.inside {
stroke: #333;
stroke-mode: inside; // property does not exist
stroke-width: 5px;
}
.outside {
stroke: #333;
stroke-mode: outside; // property does not exist
stroke-width: 5px;
}
If there is no such property, is there a workaround to achieve something like:
The comment above by @enxaneta is exactly right.
Normally, where a filled rectangle is 48px
wide and has a stroke
with a stroke-width
of 12px
, the rectangle will display with:
12px
wide border36px
Why 36px
rather than 48px
?
Because the 12px
-wide stroke painted along the left side of the rectangle is obscuring 6px
of the rectangle and the12px
-wide stroke painted along the right side of the rectangle is obscuring 6px
of the rectangle.
See this example where the stroke
has 50% opacity - you can see that half of the stroke
overlaps the fill
:
svg rect {
x: 10px;
y: 10px;
width: 200px;
height: 100px;
stroke: rgba(0, 0, 0, 0.5);
stroke-width: 12px;
fill: rgb(255, 0, 0);
}
<svg>
<rect />
</svg>
Solution to create an Outer Border of 12px:
To create an Outer Border, the solution is to paint the stroke first and then paint the fill over the top.
We can achieve this using:
paint-order: stroke;
Now the rectangle will display with:
6px
wide border (because half the width of the 12px
wide border is obscured by the fill
painted over the top)48px
svg rect {
x: 10px;
y: 10px;
width: 200px;
height: 100px;
stroke: rgba(0, 0, 0, 0.5);
stroke-width: 12px;
fill: rgb(255, 0, 0);
paint-order: stroke;
}
<svg>
<rect />
</svg>
Finally, to ensure the rectangle displays with:
12px
wide border48px
change the stroke-width
from 12px
to 24px (i.e. double the intended display width):
svg rect {
x: 10px;
y: 10px;
width: 200px;
height: 100px;
stroke: rgb(0, 0, 0);
stroke-width: 24px; /* double the intended display width */
fill: rgb(255, 0, 0);
paint-order: stroke;
}
<svg>
<rect />
</svg>
Solution to create an Inner Border of 12px:
To create an Inner Border, we need three steps instead of two.
The first two steps are straightforward:
stroke-width
(just as with the outer border)paint-order: fill
(instead of paint-order: stroke
)svg rect {
x: 10px;
y: 10px;
width: 200px;
height: 100px;
stroke: rgba(0, 0, 0, 0.5);
stroke-width: 24px; /* double the intended display width */
fill: rgb(255, 0, 0);
paint-order: fill;
}
<svg>
<rect />
</svg>
The third step is to define and apply a <clipPath>
which exactly duplicates the shape which is to have an Inner Border.
For instance, if the shape is:
<rect width="200" height="100" />
Then the <clipPath>
should be:
<clipPath id="my-clip-path">
<rect width="200" height="100" /> <!-- Same as the shape -->
</clipPath>
Working Example:
#my-rect {
stroke: rgb(0, 0, 0);
stroke-width: 24px;
fill: rgb(255, 0, 0);
paint-order: fill;
clip-path: url(#my-clip-path);
}
#my-rect,
#my-clip-path-rect {
x: 10px;
y: 10px;
width: 200px;
height: 100px;
}
<svg>
<defs>
<clipPath id="my-clip-path">
<rect id="my-clip-path-rect" />
</clipPath>
</defs>
<rect id="my-rect" />
</svg>
All of the rectangles together:
svg {
display: block;
float: left;
width: 220px;
margin-left: 12px;
}
svg:nth-of-type(1) rect {
x: 10px;
y: 10px;
width: 200px;
height: 100px;
stroke: rgba(0, 0, 0, 0.5);
stroke-width: 12px;
fill: rgb(255, 0, 0);
}
svg:nth-of-type(2) rect {
x: 10px;
y: 10px;
width: 200px;
height: 100px;
stroke: rgba(0, 0, 0, 0.5);
stroke-width: 24px;
fill: rgb(255, 0, 0);
}
svg:nth-of-type(3) rect {
x: 10px;
y: 10px;
width: 200px;
height: 100px;
stroke: rgb(0, 0, 0);
stroke-width: 24px;
fill: rgb(255, 0, 0);
paint-order: stroke;
}
#svg3clip {
width: 200px;
height: 100px;
}
svg:nth-of-type(4) rect {
x: 10px;
y: 10px;
width: 200px;
height: 100px;
stroke: rgb(0, 0, 0);
stroke-width: 24px;
fill: rgb(255, 0, 0);
paint-order: fill;
clip-path: url(#svg3clip);
}
<svg>
<rect />
</svg>
<svg>
<rect />
</svg>
<svg>
<defs>
<clipPath id="svg3clip">
<rect />
</clipPath>
</defs>
<rect />
</svg>
<svg>
<rect />
</svg>
Further Reading: