July 20, 2023
•Last updated November 5, 2023
How I use 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 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 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.
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 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:
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 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.
<%= 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.
<%= icon "eye-close", path: "/path/to/eye-close.svg", classes: "w-10 h-10 stroke-current text-pink-400" %>
Categories
Collection
Part of the Ruby on Rails collection
Products and courses
-
Hello Hotwire
A course on Hotwire + Ruby on Rails.
-
Hello Rails
A course for newcomers to Ruby on Rails.
-
Rails UI
UI templates and components for Rails.