Styling and Attributes with the new Snap.svg (Basics - part 2)

Published: (December 15, 2025 at 02:52 PM EST)
5 min read
Source: Dev.to

Source: Dev.to

Introduction

This is the second tutorial in our Snap.svg series. In the first part we learned how to build hierarchical SVG structures with g(), g_a(), and Snap.FORCE_AFTER. Now we want to make those shapes look good by learning how to:

  • set visual attributes like fill, stroke, opacity, etc. using attr(),
  • apply inline styles directly to the style property with setStyle(),
  • understand the style precedence hierarchy (inline style > CSS > attribute),
  • manage CSS classes with addClass(), removeClass(), toggleClass(),
  • automatically generate and retrieve element IDs with getId(),
  • build an interactive color palette that responds to user clicks.

The underlying theme is that Snap.svg gives you fine‑grained control over how attributes and styles are applied, with clear methods for each approach.

Forked + extended Snap.svg:
Access to the library:

1. Understanding the Style Precedence Hierarchy

Before we dive into code, it’s important to understand how browsers determine which styles to apply when multiple sources define the same property. The precedence order is:

  1. Inline style attribute (highest priority)
  2. CSS rules (from <style> tags or external stylesheets)
  3. SVG presentation attributes (e.g., fill="red")

This means:

  • setStyle() (inline style) overrides any CSS rules or attributes.
  • CSS rules override presentation attributes.
  • Presentation attributes are the baseline and have the lowest priority.

Snap.svg respects this hierarchy and provides methods to target each level explicitly.

2. Basic Attribute Styling with attr()

The attr() method is both a getter and a setter for attributes. It intelligently decides whether to set values as presentation attributes or route them to the style property. These have the lowest precedence but are the most common way to style SVG elements.

Example: Colored Rectangles with Attributes

// basic-attr.js
var s = Snap("#mySvg");

// Create a group to hold our shapes
var group = s.g().attr({ id: "attrGroup" });

// Rectangle 1: Basic fill and stroke via attr() - object syntax
group
  .rect(20, 20, 80, 60)
  .attr({
    fill: "#3498db",        // blue fill
    stroke: "#2c3e50",      // dark border
    strokeWidth: 2
  });

// Rectangle 2: Using attr() with key‑value syntax (alternative way)
var rect2 = group.rect(120, 20, 80, 60);
rect2.attr("fill", "#e74c3c");           // Set fill
rect2.attr("opacity", 0.7);              // Set opacity
rect2.attr("stroke", "#c0392b");
rect2.attr("strokeWidth", 3);
rect2.attr("strokeDasharray", "5,3");    // dashed: 5px dash, 3px gap

// Rectangle 3: No fill, thick rounded stroke
group
  .rect(220, 20, 80, 60)
  .attr({
    fill: "none",
    stroke: "#2ecc71",
    strokeWidth: 4,
    strokeLinecap: "round",  // rounded ends
    strokeLinejoin: "round"   // rounded corners
  });

// Rectangle 4: Gradient‑ready (using a solid color for now)
group
  .rect(320, 20, 80, 60)
  .attr({
    fill: "#f39c12",
    stroke: "#e67e22",
    strokeWidth: 2,
    rx: 10,                  // rounded corners
    ry: 10
  });

Output: Four rectangles in a row, each with different fill, stroke, and opacity settings applied as attributes.

attr() as Getter and Setter

// Setter
element.attr("fill", "red");                     // single attribute
element.attr({ fill: "red", opacity: 0.5 });    // multiple attributes

// Getter
var currentFill = element.attr("fill");
var currentOpacity = element.attr("opacity");

Using attr_force() for Pure Presentation Attributes

attr() may route some properties to the style attribute for better CSS interaction. If you need to force a value to be a presentation attribute (i.e., stay in the markup), use attr_force():

// Smart attr() – may route to style or attribute
element.attr("fill", "blue");

// Force as presentation attribute
element.attr_force("fill", "blue");  // Guarantees a presentation attribute

When to use attr_force()

  • When a presentation attribute is required for downstream SVG manipulation.
  • When you want CSS to easily override the value (attributes have the lowest precedence).
  • When working with SVG editors or tools that expect presentation attributes.

Common Attributes

  • Fill: fill – color, gradient, pattern, or "none"
  • Stroke: stroke, strokeWidth, strokeDasharray, strokeLinecap, strokeLinejoin
  • Opacity: opacity (0 – 1), fillOpacity, strokeOpacity
  • Geometry: element‑specific like x, y, width, height, rx, ry, r, cx, cy

3. Inline Styles with setStyle() – Flexible Input

The setStyle() method sets properties directly on the element’s style attribute, giving them highest priority in the cascade. It accepts multiple input formats.

Multiple Ways to Use setStyle()

// inline-style.js
var s = Snap("#mySvg");
var group = s.g().attr({ id: "styleGroup" });

// Create circles for demonstration
var circle1 = group.circle(60, 140, 30);
var circle2 = group.circle(160, 140, 30);
var circle3 = group.circle(260, 140, 30);
var circle4 = group.circle(360, 140, 30);

// Method 1: Object with multiple properties
circle1.setStyle({
  fill: "red",
  stroke: "#c0392b",
  strokeWidth: 3,
  opacity: 0.8
});

// Method 2: Single property with key‑value syntax
circle2.setStyle("fill", "green");
circle2.setStyle("strokeWidth", "2");
circle2.setStyle("stroke", "#27ae60");

// Method 3: CSS string (like inline style attribute)
circle3.setStyle("fill: blue; stroke: navy; stroke-width: 2;");

// Method 4: Mixed – object for one property, then key‑value
circle4.setStyle({ fill: "orange" });
circle4.setStyle("stroke", "darkorange");

// All circles have inline styles that override any CSS or attributes

Understanding the Flexibility

// Object notation (most common)
element.setStyle({
  fill: "purple",
  strokeWidth: 4,
  opacity: 0.5
});

// Property‑value pairs (useful for single properties)
element.setStyle("fill", "purple");
element.setStyle("strokeWidth", 4);
element.setStyle("opacity", 0.5);

// CSS string (useful when copying from CSS)
element.setStyle("fill: purple; stroke-width: 4; opacity: 0.5");

// Note: CSS properties use hyphens (stroke-width), but object properties use camelCase (strokeWidth)

Demonstrating Style Override

Inline styles from setStyle() take precedence over attributes set with attr():

// Start with attributes
var rect = s.rect(50, 200, 100, 50).attr({
  fill: "#3498db",
  stroke: "#2c3e50",
  strokeWidth: 2
});

// Apply an inline style that overrides the fill
rect.setStyle("fill", "orange");

// Result: The rectangle appears orange, despite the earlier attribute fill.
Back to Blog

Related posts

Read more »