How to dynamically insert Font Awesome icons using JavaScript?

I’m having trouble creating Font Awesome icons with JavaScript. When I try to generate an <i> element and add it to my HTML, the icon doesn’t appear properly.

I have Font Awesome loaded in my HTML head section already. Here’s what I’m trying to do:

// Navigation menu data
let menuItems = [
    {
        label: "Dashboard",
        iconClass: "fas fa-home",
    },
    {
        label: "Calendar",
        iconClass: "far fa-calendar",
    },
    {
        label: "Tasks",
        iconClass: "fas fa-tasks",
    }
];

let container = document.querySelector(".menu-container");
let wrapper = document.createElement('div');
wrapper.className = "menu-item active";

let iconElement = document.createElement('i');
iconElement.className = menuItems[0].iconClass;

wrapper.appendChild(iconElement);
wrapper.innerText = menuItems[0].label;
container.appendChild(wrapper);
<div class="menu-container"></div>

The problem is that when I set innerText after appending the icon, it seems to overwrite everything. How can I properly combine the Font Awesome icon with text content?

The issue you’re encountering happens because innerText replaces all content inside the element, including your icon. I ran into this exact problem when building a sidebar navigation last year. Instead of using innerText, you need to create a separate text node or span element for your label.

Here’s the corrected approach:

let iconElement = document.createElement('i');
iconElement.className = menuItems[0].iconClass;

let textNode = document.createTextNode(' ' + menuItems[0].label);

wrapper.appendChild(iconElement);
wrapper.appendChild(textNode);

Alternatively, you can use innerHTML but be cautious with user-generated content:

wrapper.innerHTML = `<i class="${menuItems[0].iconClass}"></i> ${menuItems[0].label}`;

The first approach is safer and gives you more control over the DOM structure. Make sure Font Awesome CSS is fully loaded before your script runs, otherwise icons might not render immediately.

You’re dealing with a classic DOM manipulation issue. When you call innerText on the wrapper element, it completely replaces all child nodes including your icon element. I’ve faced this same frustration multiple times when working with dynamic menus. The solution is to create a span element specifically for the text content instead of using innerText on the parent: javascript let iconElement = document.createElement('i'); iconElement.className = menuItems[0].iconClass; let textSpan = document.createElement('span'); textSpan.textContent = ' ' + menuItems[0].label; wrapper.appendChild(iconElement); wrapper.appendChild(textSpan); This approach keeps your icon and text as separate DOM elements, preventing the overwriting issue. You can also add CSS classes to the span if you need specific styling for the text portion. The space before the label text ensures proper spacing between icon and text without relying on CSS margins.

yeah thats a common mistake with innerText - it wipes out everything including your icon. quick fix is to use insertAdjacentText instead: iconElement = document.createElement('i'); iconElement.className = menuItems[0].iconClass; wrapper.appendChild(iconElement); wrapper.insertAdjacentText('beforeend', ' ' + menuItems[0].label); this way the icon stays put and text gets added after it.