DEV Community

Cover image for How to use Ionicons v5 with Vue.js
Andreas
Andreas

Posted on

How to use Ionicons v5 with Vue.js

There are a lot of awesome icon sets out there, but the set from the Ionic framework - Ionicons - is still one of my favorites. It surely is a matter of taste, but I love the icon style, their support of SVG and the fact that it's completely free and open source (MIT licensed).

A few days ago, a new major version of Ionicons was released (v5.0.0) introducing appearance variants (filled, outline and sharp) for each icon instead of platform specific variants. However You can still apply specific appearances to different platforms and you can not only customize size and color but even the stroke width. Nice! Here are some examples:

Appearance Variants

The appearance can be changed by using the corresponding icon name.

<!-- HTML -->
<ion-icon name="flash-outline"></ion-icon>
<ion-icon name="flash"></ion-icon>
<ion-icon name="flash-sharp"></ion-icon>
Enter fullscreen mode Exit fullscreen mode
// RESULT
Enter fullscreen mode Exit fullscreen mode

Size

Sizes can be adjusted by using the size property or defining a custom font-size in CSS.

<!-- HTML -->
<ion-icon name="bulb-outline" size="small"></ion-icon>
<ion-icon name="bulb-outline"></ion-icon>
<ion-icon name="bulb-outline" size="large"></ion-icon>
Enter fullscreen mode Exit fullscreen mode
// RESULT
Enter fullscreen mode Exit fullscreen mode

Color

The color can be changed by simply using the color property of CSS.

<!-- HTML -->
<ion-icon name="checkmark-circle-outline" class="success"></ion-icon>
<ion-icon name="add-circle-outline"></ion-icon>
<ion-icon name="close-circle-outline" class="error"></ion-icon>
Enter fullscreen mode Exit fullscreen mode
// CSS
.success {
  color: #20c933;
}
.error {
  color: #ec213b;
}
Enter fullscreen mode Exit fullscreen mode
// RESULT
Enter fullscreen mode Exit fullscreen mode

Stroke Width

The stroke width is change by the CSS custom property --ionicon-stroke-width.

<!-- HTML -->
<ion-icon name="cube-outline" class="thin"></ion-icon>
<ion-icon name="cube-outline"></ion-icon>
<ion-icon name="cube-outline" class="bold"></ion-icon>
Enter fullscreen mode Exit fullscreen mode
// CSS
.thin {
  --ionicon-stroke-width: 8px;
}
.bold {
  --ionicon-stroke-width: 64px;
}
Enter fullscreen mode Exit fullscreen mode
// RESULT
Enter fullscreen mode Exit fullscreen mode

If you'd like to play around with these examples you can use this CodePen.

As I build PWAs with Vue.js without using the Ionic Framework, I was facing the problem of properly adding the freshly-baked v5 Ionicons to Vue.

That's how it currently works for me in 2 simple steps.

1. Import the Ionicons ECMAScript Module

To make the Ionicons available, add the ECMAScript module version to the head of your public/index.html like this:

<script type="module" src="https://unpkg.com/ionicons@5.0.0/dist/ionicons/ionicons.esm.js"></script>
Enter fullscreen mode Exit fullscreen mode

2. Configure Vue.js

If you try to use the <ion-icon name="add"></ion-icon> element in your templates, it will properly render but you will get the following error in your console:

[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.

found in

---> at src/App.vue

This happens because the Vue instance doesn't know about the ion-icon component. To tell Vue that this is an external component, you can set the following in your src/main.js:

Vue.config.ignoredElements = [/^ion-/]
Enter fullscreen mode Exit fullscreen mode

Now you can use the ion-icon component in your templates without warnings.

Wrap it up

The above approach works, but it would have been much cleaner to properly register Ionicons as component in Vue itself. I didn't manage to do this (yet). Maybe you have an idea how it works with the latest Ionicons? Let's discuss it in the comments!

P.S. Maybe there's somebody who could make a PR adding the dev.to logo to the Ionicon logo selection 🤓


Published: 11th February 2020

Top comments (13)

Collapse
 
njt1982 profile image
Nicholas Thompson

If you're using interiajs or something else with vite, I had to do this:

export default defineConfig({
    plugins: [
        vue({
            template: {
              compilerOptions: {
                isCustomElement: (tag) => tag.startsWith('ion-')
              },
            },
        }),
    ],
});
Enter fullscreen mode Exit fullscreen mode

Hopefully useful for someone :)

Collapse
 
ryansmith profile image
Ryan Smith

I believe that is the current recommended approach, but I agree that it isn't as clean as it could be. A Vue component to wrap the Ionicons component might make it feel more integrated, but I have not done that before. This approach also works with any Web Component, not just Ionicons.

Ionic is working on a way to have Stencil output targets with framework bindings because including Web Components in frameworks can be awkward, so that will streamline the process a little more and make them seem more like they belong in the framework app. Unfortunately, the Vue version has not had progress on it compared to Angular and React, but it is on their list.

Collapse
 
devmount profile image
Andreas • Edited

Thank you very much for this detailed statement! Glad to know that I'm not doing something weird 😅 Let's hope that there will be some progress for Vue soon.

Collapse
 
zermattchris profile image
Chris Banford

Had to tweak the module import to:

<script src="https://unpkg.com/ionicons@5.0.0/dist/ionicons.js"></script>

As per the project's instructions:
github.com/ionic-team/ionicons

Hope this helps someone save a couple of minutes :-)

Collapse
 
carlflor profile image
Carl Flor

Doesn't this give you a deprecation warning?

github.com/ionic-team/ionicons/iss...

Collapse
 
maprangsoft profile image
Maprangsoft

thank you very much.

Collapse
 
devmount profile image
Andreas

You're welcome 😊

Collapse
 
abdusamikovna profile image
Durdona

vue-ionicons can be a solution to use it as a component. Please have a look github.com/mazipan/vue-ionicons

Collapse
 
devmount profile image
Andreas

Many thanks for this recommendation. As far as I see this isn't compatible with Ionicons v5.x, unfortunately.

Collapse
 
dasper profile image
Will Shaw

Would it be possible to get this updated for Vue3? I am trying to figure this out in using Vite and typescript and keep coming up at a loss.

Collapse
 
devmount profile image
Andreas

Should be similar in Vue3, except ignoredElements is now isCustomElement. Also you need to distiguish between on-the-fly compilation and pre-compilation. This page in the docs should help you.

On-the-fly example:

const app = Vue.createApp({});
app.config.isCustomElement = tag => tag.startsWith('ion-');
Enter fullscreen mode Exit fullscreen mode

Webpack example in vue.config.js:

module.exports = {
    chainWebpack: config => {
        config.module.rule('vue').use('vue-loader').loader('vue-loader').tap(options => {
            options.compilerOptions = {
                ...(options.compilerOptions || {}),
                isCustomElement: tag => /^ion-/.test(tag)
            };
            return options;
        });
    }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
k3nnie profile image
k3nnie

Thank You for this article - I really like how you can customize the new Ionicons.

Collapse
 
devmount profile image
Andreas

My pleasure! 😊