How to Render SVG Icons in Rails

How to Render SVG Icons in Ruby on Rails

This post shows how I render SVG icons in my Ruby on Rails applications. Instead of littering your HTML with complicated SVG tags, keep them tucked away in a folder as an ERB partial, and use a Rails helper to insert it in your views. Result: reusable, customizable icons and readable HTML.

1 min read

One of the first things I do whenever I start a new Rails project is create a helper method to render SVG icons.

module ApplicationHelper
  def render_icon(icon, classes: nil)
    classes ||= ""
    render "icons/#{icon}", classes: classes
  end
end

Then, whenever I want to add a new SVG icon to my application, I add it as an ERB partial under the views/icons directory. I also give it a class attribute that will be inserted dynamically via the partial parameter.

<%# views/icons/_register.html.erb %>

<svg xmlns="http://www.w3.org/2000/svg" fill="none" class="<%= classes %>" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
  <path ... />
  <path ... />
</svg>

Finally, I use the above helper in my ERB view templates as follows:

<%= render_icon 'register', classes: 'h-24 w-24' %>

I stumbled on this solution a few months ago, and have been using ever since. The nice benefit of this approach is that it doesn't litter your HTML views with complex SVG code and keeps them readable. You can also easily re-use these icons elsewhere, customizing them by passing classes as needed.

Thought I'd share this with y'all as I haven't seen this approach mentioned online that much. Most of the articles and videos mention creating the SVG filetype in asset compilation, using external gems, rendering SVGs as images, or building custom ERB helpers to read and insert the SVG files, etc. which all seem too complicated to me.

What do you think?

Update: On Reddit, one commenter mentioned that using the inline_svg gem would allow me to keep the icons as SVG images (instead of ERB partials), what's the benefit, you ask? You can see them in your IDE!

Personally, I haven't had the need to see them so far (you can still see them in browser, if you need to), but it's a good point, still. Make sure you think about this trade-off before picking a solution.