How I use SVG icons with Ruby on Rails
Tags: rails, ruby, tailwindcss
Published: 2023-07-22 16:37:03

---
title: How I use SVG icons with Ruby on Rails
published: true
date: 2023-07-20 19:32:16 UTC
tags: rails, ruby, tailwind
canonical_url: https://web-crunch.com/posts/svg-icons-with-ruby-on-rails
---

As a designer who stumbled into Ruby on Rails, I always look for more opportunities to simplify, bringing better design to the framework. I’m working on a new project called [Rails UI](https://railsui.com) that focuses on this to a vast degree, but a small component of that project involves SVG icons.

Icons make it easier to understand UI and UX patterns. Often paired with text, SVG icons give more context to a user's action, thus making conviction strong from their point of view to know what to do with the software presented to them.

### Why I prefer SVG icons

I prefer SVG icons to images or font icons for scalability and accessibility. SVGs are simply code at the end of the day. They are scalable, and you can easily manipulate colors, animation, and size with CSS. They have embedded title elements that you can prefill with a title to help it be more accessible.

In nearly every project, I reach for icons, so over time, I’ve naturally built out an approach to using them with Ruby on Rails and a gem called inline\_svg.

### My custom icon helper

The [inline\_svg](https://github.com/jamesmartin/inline_svg) gem does most of the work when rendering the SVG inline. You can pass several attributes: title, aria attributes, classes, path, and more. I’ve taken the gem and built my own Rails helper to make it adapt more to my flow.

```ruby
def icon(name, options={})
  options[:title] ||= name.underscore.humanize
  options[:aria] = true
  options[:nocomment] = true
  options[:variant] ||= :outline
  options[:class] = options.fetch(:classes, nil)
  path = options.fetch(:path, "icons/#{options[:variant]}/#{name}.svg")
  icon = path
  inline_svg_tag(icon, options)
end

```

The default use case for this helper comes from my Rails UI project. Currently, I’m leveraging the solid and outline variants of icons from [heroicons](https://heroicons.com/) with a specific folder structure.

The default variant that gets rendered is `:outline`, but you can pass an option to the helper to use `:solid` all the same.

The folder structure in a given rails app might look like this for your icons:

```bash
app/
├─ assets/
│ ├─ images/
│ │ ├─ icons/
│ │ │ ├─ outline/
│ │ │ ├─ solid/

```

Here are the helper options:

- `:title` — Add a node inside the top level of the SVG document (Enabled by default).
- `:aria` — Adds common accessibility attributes to the SVG (Enabled by default).
- `:nocomment` — Remove comment tags from the SVG document (Enabled by default).
- `:variant` — Pass a style of icon you would like to render. (Defaults to :outline. Options include :outline or :solid).
- `:classes` — class is reserved for the [inline\_svg](https://github.com/jamesmartin/inline_svg) gem so we used classes an an alternate way to pass additional HTML classes to style the icon. stroke-current and stroke-fill are appended by default based on the :variant option.
- `:path` — Pass a custom path to an icon.

### Usage

Using and rendering a new icon is simple and doesn't pollute your markup. Below I’m using it with Tailwind CSS classes.

```erb
<%= icon "academic-cap", classes: "w-5 h-5 text-indigo-600" %>

```

### Customization

Suppose you wanted to add one-off custom icons outside the typical folders shared above. You can pass a custom path along with the icon's name to achieve the same results.

```erb
<%= icon "eye-close", path: "/path/to/eye-close.svg", classes: "w-10 h-10 stroke-current text-pink-400" %>

```