Upgrading from Font Awesome 5 and 6 to 7

The breaking changes that matter, the class and family renames to search for, and a migration order that keeps the icons visible throughout.

The breaking changes

AreaFont Awesome 6Font Awesome 7Action
Fixed widthOpt-in with fa-fwOn by defaultRemove fa-fw; check any layout depending on variable widths
Decorative iconsAnnouncedHidden from screen readers by defaultRemove aria-hidden="true"; add a label where the icon carries meaning
sr-onlyAvailableRemovedUse visually-hidden or a <span class="fa-sr-only"> pattern
Sass buildLibSass and Dart SassDart Sass onlyMigrate the build tooling first
CSS custom propertiesLimitedUsed throughoutReplace hard-coded overrides with --fa-* properties
Font family namesFont Awesome 6 FreeFont Awesome 7 FreeUpdate any hand-written @font-face or font-family
BrandsFont Awesome 6 BrandsFont Awesome 7 BrandsSame
Dynamic icon lookup (JS)SupportedRemovedRegister icons with the library, or import definitions
fa-sharp namingFont Awesome 6 SharpFont Awesome 7 SharpSame
Icon renamesSome v5 names aliasedAliases removedUpdate to the current canonical names
fa-v4compatibilityAvailableRemovedFix the class names instead
Integration packagesContrib ecosystemSome droppedMove to the official packages
⚠️
The decorative-icons change is the one that silently alters behaviour. In v6 a bare icon with no label was announced by its ligature or code point, which sounded like gibberish but at least indicated something was there. In v7 it is hidden by default, so a button whose only content is an icon becomes an unnamed button — a real accessibility regression unless you add a label.

Finding what needs changing

# 1. Version and family names in your own CSS
grep -rn "Font Awesome 5\|Font Awesome 6" src/ --include="*.css" --include="*.scss"

# 2. A hand-written @font-face block: it needs the new family name and files
grep -rn "@font-face" src/ -A 5 | grep -i "awesome"

# 3. The classes that changed behaviour or vanished
grep -rno "fa-fw\|fa-sr-only\|fa-v4compatibility" src/

# 4. Bare icons with no adjacent text, which v7 will hide
grep -rnE "<i class=\"[^\"]*fa-[a-z-]+[^\"]*\"></i>" src/ | head -50

# 5. Hand-written aria-hidden on icons, now redundant or harmful
grep -rn "aria-hidden" src/ | grep -i "fa-"

# 6. Deprecated icon names that were aliased in v6
grep -rn "fa-arrow-alt\|fa-sign-in-alt\|fa-trash-alt\|fa-comment-alt" src/
// A script that reports every icon class in a directory and flags the ones
// that need attention, so the migration is a list rather than a scavenger hunt.
import { readdir, readFile } from 'node:fs/promises';
import { join } from 'node:path';

const FLAGGED = /\b(fa-fw|fa-sr-only|fa-v4compatibility|fa-arrow-alt-|fa-trash-alt|fa-sign-in-alt|fa-comment-alt)\b/g;
const ICON = /\bfa-[a-z0-9-]+\b/g;

async function scan(dir) {
  const found = new Map();

  async function walk(current) {
    for (const entry of await readdir(current, { withFileTypes: true })) {
      const path = join(current, entry.name);
      if (entry.isDirectory()) { await walk(path); continue; }
      if (!/\.(html|jsx|tsx|vue|svelte|ts|js|mdx)$/.test(entry.name)) continue;

      const source = await readFile(path, 'utf8');
      for (const match of source.match(FLAGGED) ?? []) {
        if (!found.has(match)) found.set(match, []);
        found.get(match).push(path);
      }
      for (const match of source.match(ICON) ?? []) {
        if (!found.has(match)) found.set(match, []);
        if (found.get(match).length < 3) found.get(match).push(path);
      }
    }
  }

  await walk(dir);
  return found;
}

const report = await scan('src');
for (const [name, files] of [...report].sort()) {
  console.log(name.padEnd(28), files.slice(0, 3).join(', '));
}
  • Search the compiled CSS too, if any of it is checked in. A stale ../webfonts/fa-solid-900.woff2 reference from v6 is a 404 that shows as boxes.
  • Check the fixture files and the tests as well. An icon asserted by class name in a test will pass while the page renders nothing.
  • Grep for the Sass mixins you use, not just the classes: the Dart Sass-only change breaks a LibSass build before any icon appears.

A migration order that keeps working

  1. Copy the v7 files or update the package, and update the font-family names in any hand-written CSS. Run the build and confirm the icons still render — both versions use the same class names for the majority of the set.
  2. Load the v7 stylesheet alongside the v6 one only if you cannot switch at once. Duplicate @font-face rules with different family names coexist harmlessly; the same family name with two different files does not.
  3. Remove fa-fw and verify the alignment of any column that relied on it. The default width is now the icon's natural width, which is usually what the design wants.
  4. Add accessible names to every icon-only control before removing the old aria-hidden attributes. This is the change most likely to cause a regression, so do it deliberately rather than as a search and replace.
  5. Rename deprecated icon names to their canonical v7 equivalents, guided by the report script.
  6. Update the framework component packages to their v7 releases and re-check tree-shaking, since the dynamic lookup removal changes how icons resolve.
  7. Remove any fa-v4compatibility or sr-only usage, then delete the v6 stylesheet and the old font files.
  8. Re-run a visual check on every page: the icon metrics changed slightly, so a badge that sat perfectly may now be one pixel off.
<!-- Before: v6, icon announced by its code point -->
<button type="button" class="icon-btn"><i class="fa-solid fa-bell"></i></button>

<!-- After: v7, decorative and hidden, with the name on the control -->
<button type="button" class="icon-btn" aria-label="Notifications">
  <i class="fa-solid fa-bell"></i>
</button>

<!-- A meaningful icon next to text: hidden, and the text carries the meaning -->
<button type="button" class="btn">
  <i class="fa-solid fa-trash" aria-hidden="true"></i> Delete project
</button>

<!-- A standalone icon that must be announced: give it a real accessible name -->
<span class="status">
  <i class="fa-solid fa-circle-check" role="img" aria-label="Healthy"></i>
  API
</span>
Icon roleMarkupWhy
Decorative, next to textaria-hidden="true" on the iconThe text already names the action
The only content of a controlNothing on the icon; aria-label on the controlThe control is what receives focus
Meaningful inline in proserole="img" plus aria-labelOtherwise it is invisible and its meaning is lost
A status indicatorrole="img" and a label, or text beside itColour and shape alone are not enough
A decorative flourisharia-hidden="true"Nothing to announce

The migration is mostly mechanical except for the accessibility change, which is a genuine improvement that requires a decision per icon. Budget for it: it is the part that reviewers and auditors will look at, and the part that a v6 codebase is least likely to have documented.

FAQ

Is there a compatibility stylesheet for v6 classes?
No. The fa-v4compatibility stylesheet that bridged v4 to v5 was removed, and v7 does not ship a shim. The class names that changed are few, so a search-and-replace plus the report script above is faster than maintaining a shim.
Why are my icons invisible after upgrading, with no console error?
The most likely cause in v7 is that the icon is now hidden from assistive tech and you were relying on the old announcement for a visible width or layout. Check the font-family names in your CSS first, then check whether an icon-only control lost its accessible name.

Installing Font Awesome Accessibility and performance trade-offs

Last refreshed 2026-09-18.