如何在 next.js 14 / tailwind 项目中正确导入和渲染本地字体(不是谷歌字体)?

问题描述 投票:0回答:1

我一直在尝试在 next.js 14 项目中使用一堆 .otf 字体文件,方法是在元素的类名中调用字体以符合顺风约定。

似乎无论我做什么(假设我不是专家并且肯定缺少信息),浏览器都会将字体系列呈现为默认的谷歌字体(字体系列:ui-sans-serif,system-ui 、无衬线、“Apple Color Emoji”、“Segoe UI Emoji”、“Segoe UI Symbol”、“Noto Color Emoji”;)。 font-gotham 的自定义 className 始终会被浏览器中的 ' html, :host ' css 规则覆盖。

我在页面上渲染 Gotham 字体的唯一方法是直接创建一个 css 规则,通过 id 设置字体系列,或者直接覆盖 ' html, :host ' 上的 css 规则。

但我希望能够使用 tailwinds className 或 next.js,这样我将来就不必返回 globals.css 文件。 我尝试在layout.jsx和tailwind.config.js文件中添加代码来尝试不同的方法,因此肯定有很多无关的代码,因为我不确定需要什么。如果我做错了什么和/或是否有办法做我想做的事情,请告诉我。蒂亚!

附注我的字体文件位于 public/fonts/

应用程序/layout.jsx:

import '@styles/globals.css';
import localFont from 'next/font/local'

import Nav from '@components/Nav';
import Provider from '@components/Provider';

export const metadata = {
    title: 'School',
    description: 'School Official Website'
}

const gotham = localFont({
  src: [
    {
      path: '../public/fonts/Gotham-Thin.otf',
      weight: '100',
      style: 'normal',
    },
    {
      path: '../public/fonts/Gotham-Extra-Light.otf',
      weight: '200',
      style: 'normal',
    },
    {
      path: '../public/fonts/Gotham-Light.otf',
      weight: '300',
      style: 'normal',
    },
    {
      path: '../public/fonts/Gotham-Book-Regular.otf',
      weight: '400',
      style: 'normal',
    },
    {
      path: '../public/fonts/Gotham-Medium.otf',
      weight: '500',
      style: 'normal',
    },
    {
      path: '../public/fonts/Gotham-Bold.otf',
      weight: '600',
      style: 'normal',
    },
    {
      path: '../public/fonts/Gotham-Black.otf',
      weight: '700',
      style: 'normal',
    },
    {
      path: '../public/fonts/Gotham-Regular.otf',
      weight: '800',
      style: 'normal',
    },
    {
      path: '../public/fonts/Gotham-Ultra.otf',
      weight: '900',
      style: 'normal',
    },
  ],
  variable: '--font-gotham'
})

const gothamFont = {
  fontFamily: `var(${gotham.variable})`
};

const RootLayout = ({ children }) => {
  return (
    <html lang='en' className={`${gotham.variable} font-gotham`}>
        <body>
            <div className='main'></div>

            <main className='app'>
                <Nav />
                { children }
            </main>
        </body>
    </html>
  )
}

export default RootLayout;

组件/Nav.jsx:

"use client";

import Link from 'next/link';
import Image from 'next/image';
import { useState, useEffect } from 'react';

const Nav = () => {
    const [showSubmenu, setShowSubmenu] = useState(false);
    return (
        <nav id="nav" className="w-full break-words">

            <div id="upperNav" className="bg-silver w-full h-14 px-72 font-gotham text-sm text-black pt-5 flex justify-between">
                <div id="leftUpperNav" className="self-stretch gap-11 inline-flex">
                    <Link href="/">
                        <div className="font-gotham">Upper Left 1</div>
                    </Link>
                    <Link href="" className="">Upper Left 2</Link>
                    <Link href="" className="">Upper Left 3</Link>
                    {/* <Link href="" className="">Upper Left 4</Link> */}
                </div>
                <div id="rightUpperNav" className="self-stretch gap-11 inline-flex">
                    <Link href="" className="">Upper Right 1</Link>
                    <Link href="" className="">Upper Right 2</Link>
                </div>
            </div>

            <div id="lowerNav" className="pb-7 pt-[30px] self-stretch flex justify-around items-center bg-blue-default w-full h-[85px] px-[435px] justify-center font-gotham text-[22px] font-normal text-white group">
                <div className="relative flex-col justify-start items-center inline-flex text-white"
                    onMouseEnter={() => setShowSubmenu(true)}
                    onMouseLeave={() => setShowSubmenu(false)}>
                    <Link href="/about">
                        About
                    </Link>
                    <div className="w-full h-[3px] bg-transparent group-hover:bg-white transition-all duration-500 ease-in-out" />
                </div>

                <div>Academics</div>
                <div>Admissions</div>
                <div>News & Events</div>
                <div>Life</div>
            </div>

            {showSubmenu && (
                <div className="h-[143px] px-72 bg-white justify-end items-center inline-flex">
                    <div className="w-[1275px] self-stretch justify-between items-center inline-flex">
                        <Link href="/accreditation" className="text-black text-xl font-bold">
                            Accreditation
                        </Link>
                        {/* ...other submenu items... */}
                    </div>
                </div>
            )}


        </nav>
)}

export default Nav

tailwind.config.js :

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./components/**/*.{js,ts,jsx,tsx,mdx}",
    "./app/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  darkMode: "class",
  important: true,
  theme: {
    extend: {
      fontFamily: {
        'gotham': ['Gotham Regular'],
        'gotham-black': ['Gotham Black'],
        'gotham-medium': ['Gotham Medium'],
        'gotham-light': ['Gotham Light'],
        'gotham-extra-light': ['Gotham Extra Light'],
        'gotham-thin': ['Gotham Thin'],
        'gotham-book': ['Gotham Book'],
        'gotham-bold': ['Gotham Bold'],
        'gotham-ultra': ['Gotham Ultra'],
        gotham: ['var(--font-gotham)']
      },
    },
    screens: {
      xs: "540px",
      sm: "640px",
      md: "768px",
      lg: "1024px",
      xl: "1280px",
      "2xl": "1536px",
      lg_992: "992px",
    },
    container: {
      center: true,
      padding: {
        DEFAULT: "12px",
        sm: "1rem",
        lg: "45px",
        xl: "5rem",
        "2xl": "13rem",
      },
    },
    extend: {
      fontFamily: {
        gotham: ['var(--font-gotham)'],
      },
      fontSize: {
        'sm': '14px',
      },
      fontWeight: {
        'bold': 700,
      },
      textColor: {
        'white': '#FFFFFF',
      },
      colors: {
        colors: {
          'black': '#000000',
          'blue-850': "012f87",
          'blue-default': '#012F87', 
          'blue-950': '#0A1F4E',
          'neutral-950': '#090909',
          'blue-700': '#103CCC',
          'blue-600': '#1A73E8',
          'green-600': '#34A853',
          'blue-500': '#4285F4',
          'zinc-600': '#5B5B5B',
          'stone-500': '#666666',
          'red-900': '#7E2528',
          'zinc-500': '#808080',
          'stone-200': '#E5E3DF',
          'neutral-200': '#E6E6E6',
          'red-500': '#E94235',
          'zinc-100': '#F2F2F2',
          'neutral-100': '#F5F5F5',
          'yellow-500': '#FABB05',
          'yellow-400': '#FFC600',
          'white': '#FFFFFF',
        },
        
      },
    },
  },
  theme: {
    backgroundColor: theme => ({
      ...theme('colors'),
      'blue-default': '#012F87',
      'silver': '#F2F2F2',
    })
  },
  plugins: [require("tailwindcss"), require("autoprefixer")],
};

样式/globals.css:

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

@font-face {
    font-family: 'Gotham Thin';
    src: url('../public/fonts/Gotham-Thin.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Regular';
    src: url('../public/fonts/Gotham-Regular.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Black';
    src: url('../public/fonts/Gotham-Black.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Ultra';
    src: url('../public/fonts/Gotham-Ultra.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Bold';
    src: url('../public/fonts/Gotham-Bold.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Book';
    src: url('../public/fonts/Gotham-Book.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Extra Light';
    src: url('../public/fonts/Gotham-Extra-Light.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Light';
    src: url('../public/fonts/Gotham-Light.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Medium';
    src: url('../public/fonts/Gotham-Medium.otf') format('opentype');
}

@layer utilities {
    .text-balance {
        text-wrap: balance;
    }
} 

/* WORKS */
#lowerNav {
    font-family: 'Gotham Medium';
} 

/* #upperNav {
    font-family: 'Gotham Medium';
}

*/
/* 
html, :host {
    font-family: 'Gotham Bold';
} */
reactjs fonts tailwind-css jsx next.js14
1个回答
0
投票

出于某种原因,默认的顺风字体优先于我的自定义字体。为了解决这个问题,我可以通过使用一层 :not() 伪类来增加 Tailwind 类的特异性。

我创建了一个 style/fonts.css 文件,将所有 @font-face 规则从 styles/globals.css 文件移过来,并添加了 :not(.not) 规则:

:not(.not) .font-gotham-thin {
    font-family: 'Gotham Thin', sans-serif !important;
}

:not(.not) .font-gotham-extra-light {
    font-family: 'Gotham Extra Light', sans-serif !important;
}

:not(.not) .font-gotham-light {
    font-family: 'Gotham Light', sans-serif !important;
}

:not(.not) .font-gotham-book-regular {
    font-family: 'Gotham Book Regular', sans-serif !important;
}

:not(.not) .font-gotham-medium {
    font-family: 'Gotham Medium', sans-serif !important;
}

:not(.not) .font-gotham-bold {
    font-family: 'Gotham Bold', sans-serif !important;
}

:not(.not) .font-gotham-black {
    font-family: 'Gotham Black', sans-serif !important;
}

:not(.not) .font-gotham {
    font-family: 'Gotham Regular', sans-serif !important;
  }
  
:not(.not) .font-gotham-ultra {
    font-family: 'Gotham Ultra', sans-serif !important;
}

@font-face {
    font-family: 'Gotham Thin';
    src: url('../public/fonts/Gotham-Thin.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Regular';
    src: url('../public/fonts/Gotham-Regular.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Black';
    src: url('../public/fonts/Gotham-Black.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Ultra';
    src: url('../public/fonts/Gotham-Ultra.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Bold';
    src: url('../public/fonts/Gotham-Bold.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Book';
    src: url('../public/fonts/Gotham-Book.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Extra Light';
    src: url('../public/fonts/Gotham-Extra-Light.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Light';
    src: url('../public/fonts/Gotham-Light.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Medium';
    src: url('../public/fonts/Gotham-Medium.otf') format('opentype');
}

@font-face {
    font-family: 'Gotham Book Regular';
    src: url('../public/fonts/Gotham-Book-Regular.otf') format('opentype');
}

我从 styles/globals.css 文件中完全删除了所有字体系列规则。 然后我在 app/layout.jsx 文件中的 styles/globals.css 文件下导入了 styles/fonts.css 文件,并删除了所有额外的字体系列导入:

import '@styles/globals.css';
import '@styles/fonts.css';
import localFont from 'next/font/local'

import Nav from '@components/Nav';
import Provider from '@components/Provider';

export const metadata = {
    title: 'School',
    description: 'School Official Website'
}

const RootLayout = ({ children }) => {
  return ( 
    <html lang='en' > 
        <body>
            <div className='main'></div>

            <main className='app'>
                <Nav />
                { children }
            </main>
        </body>
    </html>
  )
}

export default RootLayout;

我从 tailwind.config.js 中删除了所有字体系列规则:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./components/**/*.{js,ts,jsx,tsx,mdx}",
    "./app/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  darkMode: "class",
  important: true,
  theme: {
    screens: {
      xs: "540px",
      sm: "640px",
      md: "768px",
      lg: "1024px",
      xl: "1280px",
      "2xl": "1536px",
      lg_992: "992px",
    },
    container: {
      center: true,
      padding: {
        DEFAULT: "12px",
        sm: "1rem",
        lg: "45px",
        xl: "5rem",
        "2xl": "13rem",
      },
    },
    extend: {
      fontSize: {
        'sm': '14px',
      },
      fontWeight: {
        'bold': 700,
      },
      textColor: {
        'white': '#FFFFFF',
      },
      colors: {
        colors: {
          'black': '#000000',
          'blue-850': "012f87",
          'blue-default': '#012F87', 
          'blue-950': '#0A1F4E',
          'neutral-950': '#090909',
          'blue-700': '#103CCC',
          'blue-600': '#1A73E8',
          'green-600': '#34A853',
          'blue-500': '#4285F4',
          'zinc-600': '#5B5B5B',
          'stone-500': '#666666',
          'red-900': '#7E2528',
          'zinc-500': '#808080',
          'stone-200': '#E5E3DF',
          'neutral-200': '#E6E6E6',
          'red-500': '#E94235',
          'zinc-100': '#F2F2F2',
          'neutral-100': '#F5F5F5',
          'yellow-500': '#FABB05',
          'yellow-400': '#FFC600',
          'white': '#FFFFFF',
        },
        
      },
    },
  },
  theme: {
    backgroundColor: theme => ({
      ...theme('colors'),
      'blue-default': '#012F87',
      'silver': '#F2F2F2',
    })
  },
  plugins: [require("tailwindcss"), require("autoprefixer")],
};

这是我当前的组件/Nav.jsx,具有可工作的渲染字体:


import Link from 'next/link';
import Image from 'next/image';
import { useState, useEffect } from 'react';

const Nav = () => {
    const [showSubmenu, setShowSubmenu] = useState(false);
    return (
        <nav id="nav" className="w-full break-words">

            <div id="upperNav" className="bg-silver w-full h-14 px-72 font-gotham-medium text-sm text-black pt-5 flex justify-between">
                <div id="leftUpperNav" className="self-stretch gap-11 inline-flex">
                    <Link href="/" className="">Upper Left 1</Link>
                    <Link href="" className="">Upper Left 2</Link>
                    <Link href="" className="">Upper Left 3</Link>
                    {/* <Link href="" className="">Upper Left 4</Link> */}
                </div>
                <div id="rightUpperNav" className="self-stretch gap-11 inline-flex">
                    <Link href="" className="">Upper Right 1</Link>
                    <Link href="" className="">Upper Right 2</Link>
                </div>
            </div>

            <div id="lowerNav" className="pb-7 pt-[30px] self-stretch flex justify-around items-center bg-blue-default w-full h-[85px] px-[435px] justify-center font-gotham-bold text-[22px] text-white group">
                <div className="relative flex-col justify-start items-center inline-flex text-white"
                    onMouseEnter={() => setShowSubmenu(true)}
                    onMouseLeave={() => setShowSubmenu(false)}>
                    <Link href="/about">
                        About
                    </Link>
                    <div className="w-full h-[3px] bg-transparent group-hover:bg-white transition-all duration-500 ease-in-out" />
                </div>

                <div>Academics</div>
                <div>Admissions</div>
                <div>News & Events</div>
                <div>Life at School</div>
            </div>

            {showSubmenu && (
                <div id="lowerSubNav1" className="h-[143px] px-72 bg-white justify-end items-center inline-flex font-gotham-medium">
                    <div className="w-[1275px] self-stretch justify-between items-center inline-flex">
                        <Link href="/accreditation" className="text-black text-xl font-bold">
                            Accreditation
                        </Link>
                        {/* ...other submenu items... */}
                    </div>
                </div>
            )}


        </nav>
    )
}

export default Nav
© www.soinside.com 2019 - 2024. All rights reserved.