I'm using
@plugin "@iconify/tailwind4";
in my Vue.js project. This works fine using "static" class names like:
<span
:class="`icon-[tabler--carrot]`"
class="text-base-content/80"
></span>
However, it does not work with dynamic class names:
const iconClass = computed(() => {
return `icon-[tabler--${iconName}]`;
});
<span
v-if="iconName"
:class="iconClass"
class="text-base-content/80"
></span>
It looks like the plugin cannot scan the code looking for dynamic class names; is there a way to include for example all the tabler
icon set so that this can work?
Yes. The TailwindCSS engine scans your files for used class names and generates the CSS based on that. Because of this, it will never be able to handle dynamic class names, as there are infinite possible outcomes for dynamic values.
This is also highlighted in the documentation:
Tailwind treats all of your source files as plain text, and doesn't attempt to actually parse your files as code in any way.
When working with dynamic class names, such as
icon-[mdi-light--home]
, Tailwind CSS finds all such class names and passes them to a plugin to generate CSS. That means plugin knows which icons are used and loads only required icons.However, when using plain class names, such as
mdi-light--home
, Tailwind CSS requires a plugin to generate CSS for all possible class names first, before finding class names in your project, then it removes unused class names. That means plugin must generate CSS for every single icon that might exist.Generating CSS for every single icon is not a fast process. With over 200,000 icons available, it might take a lot of time. Then Tailwind CSS keeps it all in memory, which might cause Tailwind CSS to run out of memory. To avoid that, you must specify list of icon sets you want to use.
I recommend declaring in advance which icons you need and building your component accordingly.
const icons = {
carrot: 'icon-[tabler--carrot]',
foo: 'icon-[tabler--foo]',
bar: 'icon-[tabler--bar]',
// Add more here as needed
} as const;
type IconName = keyof typeof icons;
const iconClass = computed(() => {
return iconName.value ? icons[iconName.value as IconName] : '';
});
This also results in more consistent and predictable code, similar to Robin's observation here:
Alternatively, you can place the icons in the safelist, but keep in mind that including unused icons in production will lead to unnecessary energy and bandwidth waste in the future.
@import "tailwindcss";
@plugin "@iconify/tailwind4";
@source inline("icon-[tabler--{carrot,foo,bar}]");
Use the original Iconify classes instead of the icon-[...]
utility, and add the iconify class using @apply
:
@import "tailwindcss";
@plugin "@iconify/tailwind4";
[class*="tabler--"]:not([class*="iconify-color"]) {
@apply iconify;
}
const iconClass = computed(() => {
return `tabler--${iconName}`;
});
Or manually:
@import "tailwindcss";
@plugin "@iconify/tailwind4";
const iconClass = computed(() => {
return `iconify tabler--${iconName}`;
});
In these two examples, .iconify
provides the necessary settings for the font, while the .tabler--*
class name defines the specific character to be displayed.
Make sure that the .iconify
class and the icon classes are always included in the production build, independently of TailwindCSS. Note that with this approach, you also won't be able to purge unused icon CSS from the final build.