Introduction

Style in SVG is a little more complicated than CSS in a vanilla HTML document.

Consider an SVG image embedded in an HTML document. The style for a particular SVG element is influenced by:

  1. The browser default styling (also known as User Agent Styling)
  2. The <style> block in the HTML document (including any referenced CSS file)
  3. The <style> block in the SVG document
  4. The inline style = ... attribute on the element
  5. Presentation attributes on the SVG element e.g. <rect fill='red' ...>

The style cascade in SVG

The image below shows the process of style cascade for an SVG image and how it is handled within svgparser.

Example SVG

svg_text <- '
<svg viewBox="0 0 200 100">
  <rect x="20" y="20" width="30" height="30" style="fill: blue" class="stroked" id = "rect1"/>
  <circle cx="50" cy="50" r="20" class="stroked"/>
</svg>
'
svg <- svgparser::read_svg(svg_text)

grid::grid.newpage()
grid::grid.draw(svg)

Injecting custom default styling

The SVG specification suggests that by default shapes are filled with black.

The default style specification can be overridded in svgparser using the style_default argument. This takes a named list of values which will override the initial style.

Note that in this example, the new default fill colour is only applied to the circle as this shape did not define any particular fill colour and hence derives its value from the default style.

svg <- svgparser::read_svg(svg_text, style_default = list(fill = 'skyblue'))

grid::grid.newpage()
grid::grid.draw(svg)

Injecting a supplemental style sheet

A user supplied style can be inserted into an SVG using the user_css argument.

This user-supplied style sheet is inserted into the cascade as if it appeared last out of all the <style> blocks present in the SVG.

Note that this user-supplied CSS takes part in the usual cascade of styles, and thus you may need to use !important if you really want to override an existing style which might have higher specificity/priority.

my_css = '
#rect1 { 
  fill: green !important; 
}

.stroked {
  stroke: black;
  stroke-width: 3;
}

circle {
  fill: pink;
  fill-opacity: 50%;
}
'


svg <- svgparser::read_svg(svg_text, user_css = my_css)

grid::grid.newpage()
grid::grid.draw(svg)