Skip to content

[Bug]: Invalid class names for variable fonts with weight property (next/font/local) #32992

@Chiman2937

Description

@Chiman2937

Describe the bug

Problem

When using next/font/local with the weight property for variable fonts, Storybook generates invalid CSS class names containing spaces:

<style id="classnames-font-e25342">
  .font-e25342-45 920 {  /* ❌ Invalid: contains space */
    font-family: font-e25342;
    font-weight: 45 920; {  /* ❌ Invalid: contains space */
  }
  .__variable_font-e25342-45 920 {  /* ❌ Invalid: contains space */
    --font-primary: 'font-e25342';
  }
</style>

These invalid class names prevent the font from being applied.

Workaround

Removing the weight property fixes the issue:

export const primary = localFont({
  src: '../assets/fonts/PretendardVariable.woff2',
  variable: '--font-primary',
  display: 'swap',
  // weight: '45 920'  // ❌ Removed to make it work
});

This allows the font to load correctly in Storybook, but it's not ideal because:

  • WebKit-based browsers may render incorrect font weights
  • The variable font weight range information is lost
  • The Next.js documentation specifies that variable fonts use weight as a string range (e.g., '100 900')

The same configuration with weight property works correctly in Next.js production builds

Questions

Is there a valid solution other than removing the weight property?

Reproduction link

N/A

Reproduction steps

  1. Create a local font with weight property for variable font:
import localFont from 'next/font/local';

export const primary = localFont({
  src: '../assets/fonts/PretendardVariable.woff2',
  variable: '--font-primary',
  display: 'swap',
  weight: '45 920'  // Variable font weight range
});
  1. Apply the font in Storybook preview.tsx(for test)
const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
  decorators: (Story) => (
    <div className={primary.className}>
      <Story />
    </div>
  ),
};
  1. Inspect the generated CSS in browser DevTools
Image
<style id="font-face-font-e25342">
  @font-face {
    font-family: font-e25342;
    src: url(./src/assets/fonts/PretendardVariable.woff2);
  }
</style>

<style id="classnames-font-e25342">
  .font-e25342-45 920 {  /* ❌ Invalid: contains space */
    font-family: font-e25342;
    font-weight: 45 920;
  }
  .__variable_font-e25342-45 920 {  /* ❌ Invalid: contains space */
    --font-primary: 'font-e25342';
  }
</style>

Please let me know if you need any additional information.

System

Storybook Environment Info:

  System:
    OS: Windows 11 10.0.26100
    CPU: (12) x64 12th Gen Intel(R) Core(TM) i5-12400F
  Binaries:
    Node: 22.14.0 - C:\Program Files\nodejs\node.EXE
    npm: 10.9.2 - C:\Program Files\nodejs\npm.CMD <----- active
  Browsers:
    Edge: Chromium (140.0.3485.54)
  npmPackages:
    @storybook/addon-a11y: ^10.0.5 => 10.0.5
    @storybook/addon-docs: ^10.0.5 => 10.0.5
    @storybook/nextjs: ^10.0.5 => 10.0.5
    eslint-plugin-storybook: ^10.0.5 => 10.0.5
    storybook: ^10.0.5 => 10.0.6

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions