Font Awesome 7 Text Layering: Using fa-layers-text for Counter Badges

Font Awesome 7 introduces the fa-layers-text class to overlay dynamic text and counters on icons without custom SVG manipulation.

Font Awesome 7 adds a powerful text-layer feature that lets developers overlay arbitrary text and numbers on top of icons using the CSS class fa-layers-text. This feature, implemented in the core JavaScript provider generateLayersText, eliminates the need for manual SVG manipulation when creating counter badges. By placing an element with the fa-layers-text class inside a fa-layers container, the library automatically converts the content into a properly positioned SVG text element.

How fa-layers-text Works

The text layering system combines CSS positioning with JavaScript mutation detection to render HTML text as SVG overlays.

CSS Foundation in svg.css

The core stylesheet defines the layout for both the icon layers and the text layers in css/svg.css.

/* css/svg.css – text-layer basics */
.fa-layers-counter, .fa-layers-text {
  display: inline-block;
  position: absolute;
  text-align: center;
}

Source: css/svg.css#L73-L77

The .fa-layers container establishes a relative positioning context, allowing the absolute-positioned text to be placed over the icon.

/* css/svg.css – the container */
.fa-layers {
  display: inline-block;
  height: 1em;
  position: relative;
  text-align: center;
  vertical-align: -0.125em;
  width: var(--fa-width, 1.25em);
}

Source: css/svg.css#L79-L86

JavaScript Detection and Routing

During the tree walk (onTree) the library builds a selector that includes the fa-layers-text class constant (LAYERS_TEXT_CLASSNAME).

// js/fontawesome.js – building the selector
var prefixesDomQuery = [
  `.${LAYERS_TEXT_CLASSNAME}:not([${DATA_FA_I2SVG}])`
].concat(prefixes.map(p => `.${p}:not([${DATA_FA_I2SVG}])`)).join(', ');

Source: js/fontawesome.js#L62-L66

If a node matches and its class list contains fa-layers-text, generateMutation delegates to generateLayersText.

// js/fontawesome.js – mutation routing
if (~nodeMeta.extra.classes.indexOf(LAYERS_TEXT_CLASSNAME)) {
  return callProvided('generateLayersText', node, nodeMeta);
}

Source: js/fontawesome.js#L39-L43

SVG Generation via generateLayersText

The provider builds an abstract representation of the text layer and resolves it to an SVG <text> element.

providers.generateLayersText = function (node, nodeMeta) {
  var transform = nodeMeta.transform,
      extra = nodeMeta.extra;
  // IE fallback calculations …
  return Promise.resolve([node, makeLayersTextAbstract({
    content: node.innerHTML,
    width: width,
    height: height,
    transform: transform,
    extra: extra,
    watchable: true
  })]);
};

Source: js/fontawesome.js#L72-L90

The makeLayersTextAbstract function translates the HTML text into an SVG <text> element, applying the computed transform, width/height, and any additional classes.

Implementing Counter Badges

Creating counter badges requires nesting the text layer inside a fa-layers container and applying positioning styles.

Basic HTML Structure

<span class="fa-layers fa-fw">
  <i class="fa-solid fa-bell"></i>
  <span class="fa-layers-text fa-2xs" style="bottom: 0.5em; right: 0.5em;">
    3
  </span>
</span>

The fa-layers class creates the relative positioning context. The icon renders at the base layer, while the inner fa-layers-text element positions absolutely over it using bottom and right offsets. The fa-2xs utility class scales the text size down.

Styling with CSS

You can customize the badge appearance using standard CSS properties:

<span class="fa-layers fa-fw">
  <i class="fa-solid fa-envelope"></i>
  <span class="fa-layers-text fa-xs"
        style="background:#d00;color:#fff;padding:0.1em 0.2em;border-radius:0.5em;bottom:0;right:0;">
    7
  </span>
</span>

This applies a red background, white text, rounded corners, and positions the badge in the lower-right corner of the envelope icon.

Dynamic Updates with JavaScript

Because the text layer is marked as watchable: true in the generateLayersText provider, you can update counters dynamically:

function setBadgeCount(containerSelector, count) {
  const container = document.querySelector(containerSelector);
  const badge = container.querySelector('.fa-layers-text');
  badge.textContent = count;
}

// Example usage:
setBadgeCount('.notification-icon', 12);

Font Awesome detects the DOM change and recomputes the SVG text positioning automatically.

Core Source Files and Implementation Details

File Purpose Location
css/svg.css Defines .fa-layers, .fa-layers-text, and absolute positioning rules. css/svg.css
js/fontawesome.js Core mutation engine, detection of .fa-layers-text, and the generateLayersText provider. js/fontawesome.js
scss/_stacked.scss SCSS mixins (fa-stack, fa-stack-text) that compile into the layered CSS rules. scss/_stacked.scss
js-packages/@fortawesome/fontawesome-svg-core/index.js NPM package implementation mirroring the core provider logic. js-packages/@fortawesome/fontawesome-svg-core/index.js

The LAYERS_TEXT_CLASSNAME constant is defined at line 1143 in js/fontawesome.js, ensuring the selector engine recognizes text layers during the DOM scan.

Summary

  • Font Awesome 7 text layering uses the fa-layers-text class to overlay text on icons without manual SVG coding.
  • The feature relies on CSS absolute positioning (css/svg.css) and JavaScript mutation detection (js/fontawesome.js) to render HTML content as SVG <text> elements.
  • The generateLayersText provider processes the layer content through makeLayersTextAbstract, applying transforms and watchable updates.
  • Counter badges require nesting fa-layers-text inside a fa-layers container and using inline styles or utility classes for positioning.
  • Dynamic updates are supported natively because the text layer is marked watchable: true, allowing JavaScript to change textContent and trigger automatic re-rendering.

Frequently Asked Questions

What is the difference between fa-layers-text and fa-layers-counter?

Both classes use the same underlying architecture in css/svg.css, but fa-layers-counter is typically pre-styled for badge aesthetics (background colors, borders), while fa-layers-text provides a blank canvas for custom text overlays. The JavaScript detection in js/fontawesome.js treats both identically through the LAYERS_TEXT_CLASSNAME constant, routing them to the generateLayersText provider.

How do I position a text layer precisely over an icon?

Positioning relies on CSS absolute positioning within the relative fa-layers container. In css/svg.css, the .fa-layers-text class inherits position: absolute. You can apply inline styles or custom CSS using top, bottom, left, right, or transform properties. For example, style="bottom: 0; right: 0;" anchors the badge to the lower-right corner of the base icon.

Can I update the counter value dynamically without re-rendering the entire icon?

Yes. The generateLayersText provider in js/fontawesome.js sets watchable: true when calling makeLayersTextAbstract. This registers the text node for mutation observation. When you update the textContent of the .fa-layers-text element via JavaScript, Font Awesome’s mutation scanner detects the change and recomputes the SVG <text> element automatically, preserving the base icon’s state.

Does fa-layers-text support all CSS font styling properties?

The SVG <text> element generated by makeLayersTextAbstract inherits font properties from the parent element, but because it renders inside an SVG context, some CSS properties behave differently than standard HTML text. Properties like font-size, font-weight, and color work as expected. However, layout properties like padding and border require special handling—typically by styling the HTML wrapper before SVG conversion or using fa-layers-counter which includes pre-defined badge styling in css/svg.css.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →