Логотип Workflow

Article

Svg Components Styles

The magic of style. Strokes, dashes and gradients

In previous lessons, we learned how to create shapes and paths. But so far they look like black and white drawings. In this step, we will breathe life into them.

SVG has a unique styling system. It is similar to regular CSS, but the properties are named differently. Forget about background-color and border - here they are called fill and stroke.


1. Attributes vs CSS

You can style SVG in two ways.

Method A: Presentation attributes

You write styles directly in the tag. This is reliable (it works everywhere, even when saving a picture to disk), but it clutters the code.

<rect width="100" height="100" fill="red" stroke="black" stroke-width="5" />

Method B: CSS (Classes)

The most professional approach. You can use classes, hovers (:hover), and media queries.

<style>
  .my-box {
    fill: red;
    stroke: black;
    stroke-width: 5px;
    transition: fill 0.3s;
  }
  .my-box:hover {
    fill: blue; /* SVG supports interactivity! */
  }
</style>

<rect class="my-box" width="100" height="100" />

Important: SVG CSS properties are specific.

  • color → does not work (usually). Use fill.
  • border → does not work. Use stroke.

2. Deep dive into stroke

A stroke in SVG is not just a colored line. It has settings for the shape of the ends and corners, which are critical for icons and graphs.

Line caps (stroke-linecap)

Determines what the beginning and end of an open line looks like.

  • butt (default) - a truncated edge. The line ends exactly at the coordinate point.
  • round - rounded edge. Adds a semicircle after the coordinate point.
  • square - a square protrusion. Similar to butt, but extends the line by half its thickness.

Corners (stroke-linejoin)

Determines how two lines are joined at a bend.

  • miter (default) - sharp corner.
  • round - rounded corner (the most pleasant to the eye).
  • bevel - cut corner (chamfer).

Example:

<svg width="300" height="120" viewBox="0 0 300 120">
  <!-- Butt + Miter (Hard style) -->
  <polyline points="20,80 50,20 80,80" fill="none"
            stroke="black" stroke-width="15"
            stroke-linecap="butt" stroke-linejoin="miter"/>
</svg>

Output:

<svg width="300" height="120" viewBox="0 0 300 120">
  <!-- Round + Round (Soft style) -->
  <polyline points="120,80 150,20 180,80" fill="none"
            stroke="crimson" stroke-width="15"
            stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Output:

<svg width="300" height="120" viewBox="0 0 300 120">
  <!-- Square + Bevel (Technical style) -->
  <polyline points="220,80 250,20 280,80" fill="none"
            stroke="steelblue" stroke-width="15"
            stroke-linecap="square" stroke-linejoin="bevel"/>
</svg>

Output:


3. Secret technique: stroke-dasharray

This property creates a dashed line. But it is on it that the most popular SVG animation in the world is built - the effect of a "self-drawing" line.

How it works?

stroke-dasharray takes a list of numbers: "dash length, space length".

  • 5 → 5px dash, 5px space, 5px dash...
  • 10, 5 → 10px dash, 5px space...

The second property is stroke-dashoffset. It shifts the beginning of the dash.

"Self-drawing line" trick

Imagine you have a line 100 pixels long.

  1. Make a dash 100px long (the whole line) and a space 100px long.

    stroke-dasharray="100"
    

    Now we see a solid line.

  2. Make an offset of 100px back.

    stroke-dashoffset="100"
    

    Now the visible part of the line (the dash) has gone out of sight, and in front of us is an empty space 100px long. The line has disappeared!

  3. If you animate the offset from 100 to 0, the line will "emerge" from the void.

Demonstration:

<svg width="300" height="50" viewBox="0 0 300 50">
  <style>
    .draw-me {
      fill: none;
      stroke: darkorange;
      stroke-width: 4;
      /* 1. Set a dash the length of the entire line (say, 280px) */
      stroke-dasharray: 280;
      /* 2. Hide the line by shifting the dash */
      stroke-dashoffset: 280;
      /* 3. The animation returns the offset to 0 */
      animation: draw 2s ease-in-out infinite alternate;
    }

    @keyframes draw {
      to { stroke-dashoffset: 0; }
    }
  </style>

  <line x1="10" y1="25" x2="290" y2="25" class="draw-me"/>
</svg>

We will talk about animations in chapter 7


4. Gradients: <defs> and <linearGradient>

Unlike CSS, where a gradient is a background property (background: linear-gradient...), in SVG a gradient is a separate object.

It does not live inside a shape. It lives in a special technical section <defs> (Definitions) and has a unique id. And the shape simply refers to it via url(#id).

Linear gradient

<svg width="200" height="100" viewBox="0 0 200 100">
  <!-- 1. Define the gradient -->
  <defs>
    <!-- x1,y1 - start of the vector, x2,y2 - end.
         0% 0% -> 100% 0% means a gradient from left to right -->
    <linearGradient id="myGradient" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" stop-color="gold" />
      <stop offset="100%" stop-color="red" />
    </linearGradient>
  </defs>

  <!-- 2. Use it -->
  <rect x="10" y="10" width="180" height="80" rx="10"
        fill="url(#myGradient)" />
</svg>

Radial gradient

It works the same way, but we use the <radialGradient> tag with the attributes cx, cy (center) and r (radius).

<defs>
  <radialGradient id="sunGradient" cx="50%" cy="50%" r="50%">
    <stop offset="20%" stop-color="white" />
    <stop offset="100%" stop-color="orange" />
  </radialGradient>
</defs>
<circle cx="100" cy="50" r="40" fill="url(#sunGradient)" />

Final example: Neon button

Let's combine everything: CSS classes, beautiful strokes and gradients.

<svg width="300" height="100" viewBox="0 0 300 100">
  <defs>
    <linearGradient id="neonGrad" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" stop-color="#00f260" />
      <stop offset="100%" stop-color="#0575E6" />
    </linearGradient>
  </defs>

  <style>
    .btn-rect {
      fill: none;
      stroke: url(#neonGrad);
      stroke-width: 4;
      stroke-linejoin: round;
      /* Dashed effect */
      stroke-dasharray: 200 600;
      stroke-dashoffset: 200;
      transition: all 0.5s;
    }

    .btn-text {
      font-family: Arial, sans-serif;
      font-weight: bold;
      fill: #333;
      transition: fill 0.3s;
    }

    /* Hover effect: close the path and color the text */
    svg:hover .btn-rect {
      stroke-dasharray: 600 0; /* Make the line solid */
      stroke-dashoffset: 0;
    }
    svg:hover .btn-text {
      fill: #0575E6;
    }
  </style>

  <g cursor="pointer">
    <!-- Rectangle -->
    <rect class="btn-rect" x="50" y="25" width="200" height="50" rx="25" />

    <!-- Text -->
    <text class="btn-text" x="150" y="55" text-anchor="middle" dominant-baseline="middle">
      HOVER ME
    </text>
  </g>
</svg>
HOVER ME

Quiz

Check what you learned

Please login to pass quizzes.