使用 @font-face 隔离样式组件

Isolated styled-components with @font-face

我正在使用 https://github.com/styled-components/styled-components

我正在尝试为需要 @font-face 的组件制定最佳策略。我想确保每个组件都独立于它的上下文,所以我在每个组件上定义 font-family 样式。但是,如果我在多个组件中使用 injectGlobal,我会为同一字体获得多个 @font-face 规则。

我是否应该只在我的 ThemeProvider 入口组件中定义 @font-face 规则并忍受浏览器可能无法加载所需字体的事实?

这正是我们制作 injectGlobal 的原因。如果你看看我们的 docs 他们会说:

We do not encourage the use of this. Use once per app at most, contained in a single file. This is an escape hatch. Only use it for the rare @font-face definition or body styling.

所以我要做的是创建一个名为 global-styles.js 的 JS 文件,其中包含以下代码:

// global-styles.js

import { injectGlobal } from 'styled-components';

injectGlobal`
  @font-face {
     font-family: 'My custom family';
     src: url('my-source.ttf');
  }
`

如您所见,我们在这里所做的只是注入一些全局样式 - 在本例中为 @font-face。完成这项工作的最后一件事是将此文件导入您的主入口点:

// index.js

import './global-styles.js'

// More stuff here like ReactDOM.render(...)

这意味着您的字体仅注入一次,但您的所有组件仍然可以通过 font-family: 'My custom family'!

访问它

这样做会给你一个不可见文本的闪光(FOIT),但这与 styled-components 无关 - 如果你使用香草 CSS。要摆脱 FOIT 需要更高级的字体加载策略,而不仅仅是 @font-faceing。

由于这与 styled-components 无关,我强烈建议您观看这两集前端中心以了解有关如何最好地执行此操作的更多信息:"Crafting Web Font Fallbacks" and "The Fastest Webfont Loader in the West"!

在Chrome中同一枚硬币的另一面:

不要在 injectGlobal 中使用 @font-face 如果使用例如反应路由器。 您将在每条新加载的路线上重新绘制所有应用程序。 这就是为什么:

在每条新路线上下载相同的字体文件。 只要您将 font-face 包含在单独的 .css 文件中 - 问题就会如 this github issue.

中最后一条评论所述解决

injectGlobal 已弃用。使用 createGlobalStyle

import { createGlobalStyle } from 'styled-components'

export const GlobalStyle = createGlobalStyle`  
  body {
    font-family: 'Muli', sans-serif;

    h1 {
      font-weight: 800;
      font-size: 36px;

    p {
      font-size: 18px;
    }
  }
`;

然后你可以在你的 App.js:

中使用它
import { GlobalStyle } from './styles/global'

class App extends Component {
  render() {

    return (
      <ThemeProvider theme={theme}>
        <>
          <GlobalStyle/>
          <Container/>
        </>
      </ThemeProvider>

    )
  }
}

我同意

我重新加载

import { createGlobalStyle } from 'styled-components';
import { silver } from 'shared-components/themes/colors';

export default createGlobalStyle`
    @font-face {
        font-family: "Proxima Nova";
        font-style: normal;
        font-weight: 300;
        font-display: swap;
        src: url("/static/media/fonts/proxima_nova/ProximaNova_300.otf");
    }

并反应创建应用程序