#26 No-code 之旅 — 实作 Dark Mode 和加入 Google Fonts ft. Chakra UI

连假结束了Q 今天来讲怎麽实作 dark mode 还有怎麽使用 Google Fonts 让网站看起来更好看!我们会用 Chakra UI 去实作 dark mode 功能,所以还不知道 Chakra UI 的大家可以看这两篇简介文客制化篇

Fonts

Font Optimization

Next.js 有提供内建的字体效能优化,不过目前只支援 Google Fonts 和 Typekit,当然还是可以用其他的字体库,只是不会被优化喔~ Next.js 在 build 过程中会自动把字体的 <link> 转成 inline font CSS。这麽做会减少 First Contentful Paint (FCP)Largest Contentful Paint (LCP) 的时间,让使用者可以比较快看到网页。

<!-- 前 -->
<link
  href="https://fonts.googleapis.com/css2?family=Poppins"
  rel="stylesheet"
/>

<!-- 後 -->
<style data-href="https://fonts.googleapis.com/css2?family=Poppins">
  @font-face{font-family:'Poppins';font-style:normal...
</style>

加入 Google Fonts

那怎麽把 Google Fonts 加入到专案里呢?有两种方式,第一是如果字体只会用在单一页面,那可以放在该 page 的 <Head> 里:

<!-- pages/index.js -->
<Head>
  <link
    href="https://fonts.googleapis.com/css2?family=Poppins&display=optional"
    rel="stylesheet"
  />
</Head>

可是如果想要在整个专案里用字体,可以加在我们做的 Custom Document

// pages/_document.js
import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
  render() {
    return (
      <Html>
        <Head>
          <link
            href="https://fonts.googleapis.com/css2?family=Poppins&display=optional"
            rel="stylesheet"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument

不想要用字体优化的话,可以在 next.config.js 里设定喔:

module.exports = {
  optimizeFonts: false,
}

使用 Google Fonts

把字体加入到专案之後,该怎麽使用呢?因为这专案采用 Chakra UI,所以我们可以延伸 Chakra UI 的 theme

// config/theme.js
import { extendTheme } from "@chakra-ui/react";

// 延伸 Chakra UI 的 global styles
const styles = {
  global: {
    body: {
      // 设定整个 body 的 fontFamily
      fontFamily: "'Poppins', sans-serif",
    },
  },
};

const theme = extendTheme({ styles });

export default theme;

那现在我们要把新的 theme 塞给 ChakraProvider,让所有 components 可以吃到最新的 custom global styles:

import { ChakraProvider } from "@chakra-ui/react"
import theme from "config/theme"

function MyApp({ Component, pageProps }) {
  return (
    // 提供 custom theme 给 ChakraProvider
    <ChakraProvider theme={theme}>
      <Component {...pageProps} />
    </ChakraProvider>
  )
}

export default MyApp

Dark Mode

在之前的客制化篇提过怎麽使用 Chakra UI 的 color mode,今天快速复习一下,在 config/theme.js 加:

// config/theme.js
import { extendTheme } from "@chakra-ui/react";

const styles = {...};

const config = {
  initialColorMode: "light", // 设定预设的模式
  useSystemColorMode: false, // 要不要跟着使用者系统的 color mode
}

// 把 config 加进 theme 里
const theme = extendTheme({ config, styles });

export default theme;

然後我们要加 ColorModeScript 到 Next.js 的 custom document (pages/_document.js) 里:

// pages/_document.js

import { ColorModeScript } from "@chakra-ui/react"
import NextDocument, { Html, Head, Main, NextScript } from "next/document"
import theme from "./theme"

export default class Document extends NextDocument {
  render() {
    return (
      <Html lang="en">
        <Head>...字体!...</Head>
        <body>
          // body 里的第一个~
          <ColorModeScript initialColorMode={theme.config.initialColorMode} />
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

最後我们要加一个按钮让使用者切换模式,我们可以使用 Chakra UI 提供的其中一个 hook,useColorMode

import { Button } from "@chakra-ui/button";
import { useColorMode } from "@chakra-ui/color-mode";
import { Container } from "@chakra-ui/layout";
import React from "react";

function AppFrame({ children }) {
  // 使用 Chakra UI 提供的 useColorMode
  // colorMode:现在的模式
  // toggleColorMode:切换模式的 function
  const { colorMode, toggleColorMode } = useColorMode();

  return (
    <Container p="6">
      <Button mb="4" onClick={toggleColorMode}>
        Toggle {colorMode === "light" ? "Dark" : "Light"}
      </Button>
      {children} // 网页内容~
    </Container>
  );
}
export default AppFrame;

耶~ 做完了,可以看下面的图!

Dark mode

小结

越来越多网站有提供 dark mode 了,尤其是这种部落格网站很需要长时间阅读的,加了 dark mode 功能应该会让使用者开心 (吧?XD) 而且用 Chakra UI 真的很方便~ 也使用了比较可爱的字体 (Poppins),现在剩下整个网站的样式设计。设计好难Q

大家想要看看之前的网站可以看这里,或是直接到首页~ 有任何问题可以问我,或是也可以讨论未来要开发的 No-code 专案喔。

祝大家上班上课愉快!

晚安 <3

看更多


<<:  [Day 26] - React 前端串後端 - 串接登入

>>:  Day26 - this&Object Prototypes Ch3 Objects - Review

[Re:PixiJS - Day42] dat.gui 小技巧 .name() / .listen() / .remember(obj)

先前有介绍过 dat.GUI,这篇补充一些先前没提过的部分: [PixiJS - Day-16] 使...

Day1-台湾菜鸟工程师再度挑战之序

大家好!! 我又来了 这次要来分享上次还没被虐完的部分哈哈 续上次yahoo的案件落选之後 已经十月...

Angular Stock上市个股日成交(三)(Day29)

今天我们要来使用zingChart的套件产出视觉化的图表 首先我们先在daily-tranction...

愿财力与你同在

不知不觉已经来到最後一天了, 写这系列是临时决定的,每天的库存量都是0,所以有很多文章,我都只挑重点...

[Day5] HTTP Header Injection - HTTP Header 注入

前言 在上一篇的HTTP请求走私之後,已经知道HTTP Header也可以被拿来利用,这篇会更直接的...