327

我正在使用create-react-app并且不喜欢eject.

目前尚不清楚通过@font-face 导入并在本地加载的字体应该放在哪里。

即,我正在加载

@font-face {
  font-family: 'Myriad Pro Regular';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Regular'), url('MYRIADPRO-REGULAR.woff') format('woff');
}

有什么建议么?

- 编辑

包括丹在他的回答中提到的要点

➜  Client git:(feature/trivia-game-ui-2) ✗ ls -l public/static/fonts
total 1168
-rwxr-xr-x@ 1 maximveksler  staff  62676 Mar 17  2014 MYRIADPRO-BOLD.woff
-rwxr-xr-x@ 1 maximveksler  staff  61500 Mar 17  2014 MYRIADPRO-BOLDCOND.woff
-rwxr-xr-x@ 1 maximveksler  staff  66024 Mar 17  2014 MYRIADPRO-BOLDCONDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  66108 Mar 17  2014 MYRIADPRO-BOLDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  60044 Mar 17  2014 MYRIADPRO-COND.woff
-rwxr-xr-x@ 1 maximveksler  staff  64656 Mar 17  2014 MYRIADPRO-CONDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  61848 Mar 17  2014 MYRIADPRO-REGULAR.woff
-rwxr-xr-x@ 1 maximveksler  staff  62448 Mar 17  2014 MYRIADPRO-SEMIBOLD.woff
-rwxr-xr-x@ 1 maximveksler  staff  66232 Mar 17  2014 MYRIADPRO-SEMIBOLDIT.woff
➜  Client git:(feature/trivia-game-ui-2) ✗ cat src/containers/GameModule.css
.GameModule {
  padding: 15px;
}

@font-face {
  font-family: 'Myriad Pro Regular';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Regular'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-REGULAR.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Condensed';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Condensed'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-COND.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Semibold Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Semibold Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-SEMIBOLDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Semibold';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Semibold'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-SEMIBOLD.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Condensed Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Condensed Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-CONDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Condensed Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Condensed Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDCONDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Condensed';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Condensed'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDCOND.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLD.woff') format('woff');
}
4

11 回答 11

513

有两种选择:

使用导入

这是建议的选项。它确保您的字体通过构建管道,在编译期间获取哈希值,以便浏览器缓存正常工作,并且如果文件丢失,您会收到编译错误。

“添加图像、字体和文件”</a>所述,您需要从 JS 导入 CSS 文件。例如,默认情况下src/index.js导入src/index.css

import './index.css';

像这样的 CSS 文件会通过构建管道,并且可以引用字体和图像。例如,如果您将字体放入 中src/fonts/MyFont.woff,您index.css可能会包含以下内容:

@font-face {
  font-family: 'MyFont';
  src: local('MyFont'), url(./fonts/MyFont.woff) format('woff');
  /* other formats include: 'woff2', 'truetype, 'opentype',
                            'embedded-opentype', and 'svg' */
}

请注意我们如何使用以 . 开头的相对路径./。这是一个特殊的符号,可以帮助构建管道(由 Webpack 提供支持)发现这个文件。

通常这应该足够了。

使用public文件夹

如果由于某种原因您不想使用构建管道,而是使用“经典方式”,您可以使用该public文件夹并将您的字体放在那里。

这种方法的缺点是当您为生产编译时文件不会得到哈希值,因此您每次更改它们时都必须更新它们的名称,否则浏览器将缓存旧版本。

如果您想这样做,请将字体放在public文件夹中的某个位置,例如,放入public/fonts/MyFont.woff. 如果你遵循这种方法,你也应该将 CSS 文件放入public文件夹中,而不是从 JS 中导入它们,因为混合这些方法会很混乱。所以,如果你仍然想这样做,你会有一个像public/index.css. 您必须从以下位置手动添加<link>到此样式表public/index.html

<link rel="stylesheet" href="%PUBLIC_URL%/index.css">

在其中,您将使用常规的 CSS 表示法:

@font-face {
  font-family: 'MyFont';
  src: local('MyFont'), url(fonts/MyFont.woff) format('woff');
}

注意我是如何fonts/MyFont.woff用作路径的。这是因为index.css它位于public文件夹中,因此它将从公共路径提供(通常是服务器根目录,但如果您部署到 GitHub Pages 并将您的homepage字段设置为http://myuser.github.io/myproject,它将从 提供/myproject)。但是fonts,它们也在public文件夹中,因此它们将从fonts相对(http://mywebsite.com/fontshttp://myuser.github.io/myproject/fonts)提供。因此我们使用相对路径。

请注意,由于我们在此示例中避免了构建管道,因此它不会验证文件是否确实存在。这就是我不推荐这种方法的原因。另一个问题是我们的index.css文件没有被缩小并且没有得到哈希值。因此,最终用户的速度会变慢,并且您会冒着浏览器缓存文件旧版本的风险。

 使用哪种方式?

使用第一种方法(“使用导入”)。我只描述了第二个,因为那是你试图做的(从你的评论来看),但它有很多问题,只有在你解决某些问题时才应该是最后的手段。

于 2017-01-16T14:12:05.317 回答
127

以下是一些执行此操作的方法:

1.导入字体

例如,对于使用 Roboto,安装包使用

yarn add typeface-roboto

或者

npm install typeface-roboto --save

在 index.js 中:

import "typeface-roboto";

许多开源字体和大多数 Google 字体都有 npm 包。你可以在这里看到所有的字体。所有的包都来自那个项目

2. 对于第三方托管的字体

例如 Google 字体,您可以访问fonts.google.com,在那里您可以找到可以放入您的public/index.html

fonts.google.com 的屏幕截图

它会像

<link href="https://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet">

或者

<style>
    @import url('https://fonts.googleapis.com/css?family=Montserrat');
</style>

3. 下载字体并将其添加到您的源代码中。

下载字体。例如,对于 google 字体,您可以访问fonts.google.com。点击下载按钮下载字体。

将字体移动到fonts目录中的src目录

src
|
`----fonts
|      |
|      `-Lato/Lato-Black.ttf
|       -Lato/Lato-BlackItalic.ttf
|       -Lato/Lato-Bold.ttf
|       -Lato/Lato-BoldItalic.ttf
|       -Lato/Lato-Italic.ttf
|       -Lato/Lato-Light.ttf
|       -Lato/Lato-LightItalic.ttf
|       -Lato/Lato-Regular.ttf
|       -Lato/Lato-Thin.ttf
|       -Lato/Lato-ThinItalic.ttf
|
`----App.css

现在,在 中App.css,添加这个

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

@font-face {
    font-family: 'Lato';
    font-weight: 900;
    src: local('Lato'), url(./fonts/Lato-Bold.otf) format('opentype');
}

@font-face {
    font-family: 'Lato';
    font-weight: 900;
    src: local('Lato'), url(./fonts/Lato-Black.otf) format('opentype');
}

对于ttf格式,您必须提及format('truetype'). 对于woff,format('woff')

现在您可以在类中使用该字体。

.modal-title {
    font-family: Lato, Arial, serif;
    font-weight: black;
}

4. 使用 web-font-loader 包

使用安装包

yarn add webfontloader

或者

npm install webfontloader --save

src/index.js中,您可以导入它并指定所需的字体

import WebFont from 'webfontloader';

WebFont.load({
   google: {
     families: ['Titillium Web:300,400,700', 'sans-serif']
   }
});
于 2018-09-18T18:39:01.757 回答
9
  1. 转到谷歌字体https://fonts.google.com/
  2. 选择您的字体,如下图所示:

在此处输入图像描述

  1. 复制然后将该 url 粘贴到新选项卡中,您将获得用于添加该字体的 css 代码。在这种情况下,如果你去

https://fonts.googleapis.com/css?family=Spicy+Rice

它将像这样打开:

在此处输入图像描述

4,将代码复制并粘贴到您的 style.css 中,然后开始使用该字体,如下所示:

      <Typography
          variant="h1"
          gutterBottom
          style={{ fontFamily: "Spicy Rice", color: "pink" }}
        >
          React Rock
        </Typography>

结果:

在此处输入图像描述

于 2018-11-09T16:24:44.080 回答
4

You can use the Web API FontFace constructor (also Typescript) without need of CSS:

export async function loadFont(fontFamily: string, url: string): Promise<void> {
    const font = new FontFace(fontFamily, `local(${fontFamily}), url(${url})`);
    // wait for font to be loaded
    await font.load();
    // add font to document
    document.fonts.add(font);
    // enable font with CSS class
    document.body.classList.add("fonts-loaded");
}
import ComicSans from "./assets/fonts/ComicSans.ttf";

loadFont("Comic Sans ", ComicSans).catch((e) => {
    console.log(e);
});

Declare a file font.ts with your modules (TS only):

declare module "*.ttf";
declare module "*.woff";
declare module "*.woff2";

If TS cannot find FontFace type as its still officially WIP, add this declaration to your project. It will work in your browser, except for IE.

于 2021-01-27T12:54:13.157 回答
4

链接到您的 react js 的本地字体可能会失败。所以,我更喜欢使用 google 的在线 css 文件来链接字体。参考以下代码,

<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">

或者

<style>
    @import url('https://fonts.googleapis.com/css?family=Roboto');
</style>
于 2020-08-16T15:16:11.490 回答
2

您可以使用WebFont模块,这大大简化了流程。

render(){
  webfont.load({
     custom: {
       families: ['MyFont'],
       urls: ['/fonts/MyFont.woff']
     }
  });
  return (
    <div style={your style} >
      your text!
    </div>
  );
}
于 2018-07-14T01:16:52.990 回答
2

当为普通/斜体使用不同的字体文件时,font-style您指定的方式@font-face可能需要根据入口点而有所不同。在这里查看我的答案

  1. 如果您选择将css文件直接链接到您的,public/index.html那么您可以font-face正常使用一个font-family名称和不同的名称font-style
@font-face {
  font-family: "FontName"; <---
  font-style: normal; <---
  font-weight: normal;
  src: url("path-to-assets/fonts/FontName.ttf") format("truetype");
}
@font-face {
  font-family: "FontName"; <---
  font-style: italic; <---
  font-weight: normal;
  src: url("path-to-assets/fonts/FontName-Italic.ttf") format("truetype");
}

/* Usage */
.text {
  font-family: FontName;
  font-style: normal;
}
.text-italic {
  font-family: FontName;
  font-style: italic;
}
  1. 如果你选择css通过 Js 链接文件进行捆绑,那么你需要为所有字体设置不同的font-family名称并使用normal.italicfont-style
@font-face {
  font-family: "FontName"; <---
  font-style: normal; <---
  font-weight: normal; /* normal | 300 | 400 | 600 | bold | etc */
  src: url("path-to-assets/fonts/FontName.ttf") format("truetype");
}
@font-face {
  font-family: "FontNameItalic";
  font-style: normal; <----
  font-weight: normal; /* normal | 300 | 400 | 600 | bold | etc */
  src: url("path-to-assets/fonts/FontName-Italic.ttf") format("truetype");
}

/* Usage */
.text {
  font-family: FontName;
}
.text-italic {
  font-family: FontNameItalic;
}
于 2021-05-25T08:55:13.290 回答
1

在遇到这个堆栈问题后,我整个上午都在解决类似的问题。我在上面的答案中使用了丹的第一个解决方案作为起点。

问题

我有一个开发(这是在我的本地机器上)、登台和生产环境。我的登台和生产环境位于同一台服务器上。

该应用程序被部署到登台acmeserver/~staging/note-taking-app,生产版本位于acmeserver/note-taking-app(责备 IT)。

所有媒体文件(例如字体)在开发(即,react-scripts start)上都可以正常加载。

但是,当我创建和上传暂存和生产版本时,虽然.css.js文件正确加载,但字体却没有。编译后的.css文件看起来有一个正确的路径,但是浏览器的 http 请求得到了一些非常错误的路径(如下所示)。

编译后的main.fc70b10f.chunk.css文件:

@font-face {
  font-family: SairaStencilOne-Regular;
  src: url(note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf) ("truetype");
}

浏览器 http 请求如下所示。/static/css/请注意当字体文件仅存在/static/media/以及复制目标文件夹时它是如何添加的。我排除了服务器配置是罪魁祸首。

也有Referer部分过错。

GET /~staging/note-taking-app/static/css/note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf HTTP/1.1
Host: acmeserver
Origin: http://acmeserver
Referer: http://acmeserver/~staging/note-taking-app/static/css/main.fc70b10f.chunk.css

package.json文件的homepage属性设置为./note-taking-app. 这是造成问题的原因。

{
  "name": "note-taking-app",
  "version": "0.1.0",
  "private": true,
  "homepage": "./note-taking-app",
  "scripts": {
    "start": "env-cmd -e development react-scripts start",
    "build": "react-scripts build",
    "build:staging": "env-cmd -e staging npm run build",
    "build:production": "env-cmd -e production npm run build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
  //...
}

解决方案

那是冗长的——但解决方案是:

  1. PUBLIC_URL根据环境更改env 变量
  2. 从文件中删除homepage属性package.json

下面是我的.env-cmdrc文件。我.env-cmdrc经常使用,.env因为它将所有内容放在一个文件中。

{
  "development": {
    "PUBLIC_URL": "",
    "REACT_APP_API": "http://acmeserver/~staging/note-taking-app/api"
  },
  "staging": {
    "PUBLIC_URL": "/~staging/note-taking-app",
    "REACT_APP_API": "http://acmeserver/~staging/note-taking-app/api"
  },
  "production": {
    "PUBLIC_URL": "/note-taking-app",
    "REACT_APP_API": "http://acmeserver/note-taking-app/api"
  }
}

通过路由也可以react-router-dom正常工作 - 只需使用PUBLIC_URLenv 变量作为basename属性。

import React from "react";
import { BrowserRouter } from "react-router-dom";

const createRouter = RootComponent => (
  <BrowserRouter basename={process.env.PUBLIC_URL}>
    <RootComponent />
  </BrowserRouter>
);

export { createRouter };

服务器配置设置为将所有请求路由到./index.html文件。

最后,这是main.fc70b10f.chunk.css实施了讨论的更改后编译文件的样子。

@font-face {
  font-family: SairaStencilOne-Regular;
  src: url(/~staging/note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf)
    format("truetype");
}

阅读材料

于 2019-09-18T16:42:18.273 回答
1

我犯了这样的错误。

@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i&amp;subset=cyrillic,cyrillic-ext,latin-ext";
@import "https://use.fontawesome.com/releases/v5.3.1/css/all.css";

它以这种方式正常工作

@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i&amp;subset=cyrillic,cyrillic-ext,latin-ext);
@import url(https://use.fontawesome.com/releases/v5.3.1/css/all.css);
于 2018-09-14T08:36:34.783 回答
1

我添加了

@font-face {
    font-family: 'Sanchez-Regular';
    src: local('Sanchez-Regular'),url(../assets/fonts/Sanchez/Sanchez-Regular.ttf) format('truetype');
}

并且在 index.css 中执行此操作后,它就像我们使用所有其他字体一样在稍后使用它时效果非常好

于 2021-09-09T15:43:32.067 回答
0

这适用于使用 NX(nwrl) monorepo 的人,我在那里使用它时已经测试过,可能适用于其他 CRA 应用程序。首先在 assets/fonts 文件夹中添加字体,如果不存在,则创建一个字体文件夹。

然后在您的主 app.js/tsx 中添加此代码,以及您现有的 jsx 代码

<style type="text/css">{`
    @font-face {
      font-family: 'MaterialIcons';
      src: url(${require('react-native-vector-icons/Fonts/MaterialIcons.ttf')}) format('truetype');
    }
    @font-face {
      font-family: 'MaterialCommunityIcons';
      src: url(${require('react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf')}) format('truetype');
    }
    @font-face {
      font-family: 'Mulish-Bold';
      src: url(${require('../assets/fonts/Mulish-Bold.ttf')}) format('truetype');
    }
    @font-face {
      font-family: 'Your Font Name';
      src: url(${require('../assets/fonts/font-file-name.otf')}) format('truetype');
    }
  `}</style>

它应该看起来像这样,用 Fragment 标签包装 -

 <>
<style type="text/css">{`
        @font-face {
          font-family: 'MaterialIcons';
          src: url(${require('react-native-vector-icons/Fonts/MaterialIcons.ttf')}) format('truetype');
        }
        @font-face {
          font-family: 'MaterialCommunityIcons';
          src: url(${require('react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf')}) format('truetype');
        }
        @font-face {
          font-family: 'Mulish-Bold';
          src: url(${require('../assets/fonts/Mulish-Bold.ttf')}) format('truetype');
        }
        @font-face {
          font-family: 'CircularStd-Book';
          src: url(${require('../assets/fonts/CircularStd-Book.otf')}) format('truetype');
        }
      `}</style>
   //Your JSX, or your main app level code
 </>

还有一步,在你的自定义 webpack 配置文件中,添加这些加载器,如果你没有,那么在你的父级创建一个 webpack.js 文件 -

你的 webpack js 应该看起来像这样 -

const getWebpackConfig = require('@nrwl/react/plugins/webpack');

function getCustomWebpackConfig(webpackConfig) {
  const config = getWebpackConfig(webpackConfig);
  const isProduction = webpackConfig.mode === 'production';

  if (!isProduction) {
    config.resolve.alias = {
      'react-native': 'react-native-web',
      'react-native-linear-gradient': 'react-native-web-linear-gradient',
      'react-native-localization': 'react-localization'
    };

    config.module.rules.push(
      {
        test: /\.ttf$/,
        loader: require.resolve('file-loader'),
        options: { esModule: false, name: 'static/media/[path][name].[ext]' },
      },
      {
        test: /\.otf$/,
        loader: require.resolve('file-loader'),
        options: { esModule: false, name: 'static/media/[path][name].[ext]' },
      },
      {
        test: /\.(js|jsx)$/,
        exclude: function (content) {
          return (
            /node_modules/.test(content) &&
            !/\/react-native-paper\//.test(content) &&
            !/\/react-native-vector-icons\//.test(content) &&
          
          );
        },
        use: {
          loader: require.resolve('@nrwl/web/src/utils/web-babel-loader.js'),
          options: {
            presets: [
              [
                '@nrwl/react/babel',
                {
                  runtime: 'automatic',
                  useBuiltIns: 'usage',
                },
              ],
            ],
            plugins: [
                ["module-resolver", {
                    "alias": {
                      "^react-native$": "react-native-web",
                      "react-native-linear-gradient": "react-native-web-linear-gradient",
                      "react-native-localization": "react-localization"
                    }
                  }]
            ],
          },
        },
      },
      
    );
  }

  return config;
}

module.exports = getCustomWebpackConfig;

您的 babel 加载器可能会有所不同,但添加 ttf 和 otf 规则很重要。我将它与 react native 一起用于 Web 功能。如果您的项目不需要别名,您可以删除别名。

感谢这个博客,它让我更好地理解了这个概念 - https://blog.nrwl.io/step-by-step-guide-on-creating-a-monorepo-for-react-native-apps-using-nx -704753b6c70e

于 2022-02-10T10:44:24.507 回答