Kristoffer Lund Kristoffer Lund - 1 month ago 11
CSS Question

How to color path elements in SVG?

A couple of days ago I received an SVG from some designers, and I am to implement it with some color alterations and the typical hover effects and such, /edit: but the main thing for now is to just be able to control the background color /edit/.

The HTML looks like this:

<div>
<svg class="drawelements" viewBox="50 200 550 360">
<polygon fill="red" points="312.200 265.600, 312.200 332.300, 265.600 332.300, 265.600 265.600, 312.200 265.600, 312.700 265.100, 265.100 265.100, 265.100 332.800, 312.700 332.800, 312.700 265.100, 312.700 265.100"></polygon>
<path class="st0" d="M369 265.6v66.7h-46.6v-66.7H369M369.5 265.1h-47.6v67.7h47.6V265.1L369.5 265.1z"></path>
<path class="st0" d="M425.7 265.6v66.7h-46.6v-66.7H425.7M426.2 265.1h-47.6v67.7h47.6V265.1L426.2 265.1z"></path>
<path class="st0" d="M480.6 265.6v66.7H434v-66.7H480.6M481.1 265.1h-47.6v67.7h47.6V265.1L481.1 265.1z"></path>
<path class="st0" d="M537.3 265.6v66.7h-46.6v-66.7H537.3M537.8 265.1h-47.6v67.7h47.6V265.1L537.8 265.1z"></path>
<path class="st0" d="M255.5 265.6v66.7H209v-66.7H255.5M256 265.1h-47.6v67.7H256V265.1L256 265.1z"></path>
<path class="st0" d="M537.3 207.3v49.4H209v-49.4H537.3M537.8 206.8H208.5v50.4h329.3V206.8L537.8 206.8z"></path>
</svg>
</div>


Here is a fiddle of how it looks: fiddle

I wanted to test with a polygon at the top, just to make sure that it was not the path element that was working against me.

Regular styling with CSS doesn't work, and hard coded styling within each element does not work. Is it because I need to use something else than background-color or fill?

If you look at the fiddle, please don't mind the viewBox. The actual svg contains many more elements which I removed for this post.

Answer

The code that you had used was not wrong. Generally, the way to fill a SVG box or a shape with color is to make use of the fill property but the problem was with the path elements.

In the code that is provided in question, the path elements are created in such a way that the leave a gap at the center of the shape. The shape is actually more like a frame than a solid board and that is the reason that applying a fill doesn't look like it is applying a background color to the shape.

The d attribute of the path element has the coordinates and defines how the shape is drawn - below is an explanation of how it can be interpreted:

  • M369 265.6 - moves the imaginary pen to the coordinate (369,265.6)
  • v66.7 - draws a vertical line to a point which is below the previous point by a distance of 66.7 units
  • h-46.6 - draws a horizontal line to a point which is to the left of the previous point (the end-point of the vertical line) by a distance of 46.6 units (left because the value is negative)
  • v-66.7 - draws a vertical line to a point which is above the previous point by a distance of 66.7 units
  • H369 - draws a Horizontal line to the point that represents 369 units in the X-axis (its not relative to the previous point in this case because the alphabet is upper-case).

Now the above alone would produce a rectangle. You can then apply a stroke (equivalent to border) or a fill (equivalent to background color) to it. But in your case, the d attribute also had the below commands + parameters which create an inner box.

M369.5 265.1h-47.6v67.7h47.6V265.1L369.5 265.1z

So, the final shape is something like the below:

enter image description here

When you apply a fill here to the shape, you'd see only the orange colored area and that's why it just looks like a border instead of a fill.

This MDN tutorial has more information about the SVG path element and its commands.


I have no idea why the designer had used such an approach but in my opinion this is both weird and wrong. If the need was to just have an outline, the designer must have just used the stroke property of the path rather than create an inner box and give it a fill.

Anyway the fix for your case would be to just do away with everything starting from the second M of the d attribute of all path elements and then just apply a fill to them. For the polygon element also the second set of coordinates can be removed like in the below snippet:

.st0 {
  fill: #AAA;
}
<div>
  <svg class="drawelements" viewBox="50 200 550 360">
    <polygon fill="red" points="312.200 265.600, 312.200 332.300, 265.600 332.300, 265.600 265.600, 312.200 265.600"></polygon>
    <path class="st0" d="M369 265.6v66.7h-46.6v-66.7H369z"></path>
    <path class="st0" d="M425.7 265.6v66.7h-46.6v-66.7H425.7z"></path>
    <path class="st0" d="M480.6 265.6v66.7H434v-66.7H480.6z"></path>
    <path class="st0" d="M537.3 265.6v66.7h-46.6v-66.7H537.3z"></path>
    <path class="st0" d="M255.5 265.6v66.7H209v-66.7H255.5z"></path>
    <path class="st0" d="M537.3 207.3v49.4H209v-49.4H537.3z"></path>
    <path class="st0" d="M537.3 341.1v42.3H209v-42.3H537.3z"></path>
  </svg>
</div>

Note:

  • By default there would be a black fill if no fill is specified either through attribute or CSS. You can overcome it by specifying the required color as fill (or) by setting it to transparent/none.
  • The fill property specified in CSS will take priority over the fill attribute specified in the SVG element. This is as per spec.