Font Complexity in Horizon Themes

Dear Experts,

It isn’t so easy to use custom fonts anymore. I’m using an app for custom fonts that worked fine on older themes. However, there seem to be so many subclasses specified throughout the Horizon themes, often with unique Block IDs, etc., that I keep finding the theme fault rendered instead of my custom font.

It seems best to approach the issue from a higher level. What is the best way to specify my fonts in these four categories so that everything rendered downstream is correct?

Thank you.

Proper way would be to use CSS variables.

Here is the theme code which defines the base font-related variables, there are more, but they are derived from those:

To override them you’d need to add a rule, say into “theme settings”=> “Custom CSS”
like this:

body {
  --font-body-family: monospace;
  --font-heading-family: "Your custom font", sans-serif;
  ... 
}

if my post is helpful, please like it ♡ and mark as a solution -- this will help others find it

Hello @C_Hoff

Best-Practice Strategy

  1. Load your custom font globally
    Add it in theme.liquid or via your app (Google Fonts or @font-face). Example:
<style>
  @font-face {
    font-family: 'MyCustomFont';
    src: url('{{ "mycustomfont.woff2" | asset_url }}') format("woff2");
    font-display: swap;
  }
</style>
  1. Set global defaults at the highest level
    Force Shopify to use your fonts by overriding defaults on html and body:
html, body {
  font-family: 'MyCustomFont', sans-serif !important;
}
  1. Target the 4 categories
h1, h2, h3, h4, h5, h6,
.heading, .title, .card__heading {
  font-family: 'MyHeadingFont', serif !important;
}
body, p, li, span, .rte, .text, .footer, .section {
  font-family: 'MyBodyFont', sans-serif !important;
}
.header__menu-item, .menu-drawer__menu-item,
.button, .btn, [type="submit"], label {
  font-family: 'MyNavFont', sans-serif !important;
}
.price, .badge, .quote, .highlight {
  font-family: 'MyAccentFont', monospace !important;
}
  1. Use !important sparingly but strategically
    Since Horizon applies unique selectors (like .h2.block-123abc), your global layer may still get overridden. Applying !important on your high-level rules ensures your font cascades everywhere.
  2. (Optional) Theme-wide reset
    If Horizon is very aggressive with subclassing, you can apply a “reset”:
* {
  font-family: inherit !important;
}

Then rely on the 4 category overrides above to “re-assign” fonts properly.

Thanks for the help! I ditched the app and went manual as instructed.

There is a lot of this type of class needed, which is new to me: .text-block.h4>*