比较 Next.js 中的样式方法

已发表: 2022-03-10
快速总结 ↬其中,Next.js 将自己称为:静态网站的 React 框架。 但就像其他所有框架的目标是通过抽象常见的、冗余的任务来帮助你构建重要的东西一样,你经常需要学习一些新的和固执的东西。 使用 Next.js,您需要了解的一件事是如何将不同的 CSS 方法与其 API 集成,这也是本教程的重点。

您可能知道,关于 CSS-in-JS 有许多不同的观点,而且我们对这个主题的看法可能与框架作者的看法完全不同。

Next.js是创建新 React 应用程序时推荐的工具链之一。 像 Next 这样的工具有一个简单的目标,即在编写 React 应用程序时抽象出常见的冗余任务。 这有助于开发人员更多地专注于编写代码,而不是重新发明轮子。 虽然这通常是一件好事,但开始时也可能有点乏味。 一方面,学习抽象有一个障碍需要跨越,虽然 Next 中有一大堆(路由、数据获取……),但一个经常被忽视的是样式。

为了服务更广泛的受众,Next.js 支持多种方式来设置组件样式。 无论你是属于 Utility 优先还是 CSS-in-JS 党都不是 Next 关心的问题,它关心的是你如何将你的选择注入到它的 API 中。

本文的目的是帮助您了解如何在 Next 应用程序中设置样式。 我们将使用不同的方法来处理比较。 我们将在我设置的图书应用程序中实现不同类型的样式。 我们将要研究的样式方法包括:

  1. 全球 CSS,
  2. SASS/SCSS,
  3. 组件级 SASS/SCSS,
  4. 组件级 CSS(CSS 模块),
  5. 样式化组件,
  6. 样式化的 JSX,
  7. 情感。

先决条件

在我们开始我们的造型之旅之前,您需要了解一些 Next 细微差别。

  1. _app.js
    这是一个位于 pages 文件夹中的自定义组件。 Next.js 使用这个组件来初始化页面。
  2. _document.js
    _app.js一样, _document.js是 Next.js 用来增强应用程序<html><body>标记的自定义组件。 这是必要的,因为 Next.js 页面跳过了周围文档标记的定义。
  3. _.babelrc
    如果存在,Next.js 使用此文件作为某些内部配置的单一事实来源,并授予您扩展它的权限。

请记住,如果在添加_app.js文件之前您的服务器正在运行,那么您需要重新启动它。

跳跃后更多! 继续往下看↓

使用create-next-app

使用create-next-app创建 Next 应用程序非常简单,只需执行以下步骤:

  • 全局安装create-next-app
 yarn global add create-next-app // Installs create-next-app globally
  • 创建一个名为style-in-next的新 Next 应用。
 create-next-app styling-in-next // Creates a new Next app named styling-in-next
  • 将目录更改为新站点。
 cd styling-in-next // Switch directory into the new Next app
  • 运行站点。
 yarn dev -p 3000 // Instruct Next to run on port 3000

有关创建和运行 Next 应用程序的更多信息,请参阅文档。

该应用程序现在应该在https://localhost:3000上运行。

Next.js 默认起始索引页面的截图
Next.js 默认起始索引页面。 (大预览)

演示库

随着我们的进展,我们将通过对每本书应用不同的样式方法来构建一个人为的书架。 最终结果将如下所示:

最终演示样式书架的屏幕截图
最终风格的书架。 (大预览)

上图显示了 6 本书; 每本书都有自己的组件,然后我们将为每本特定的书应用特定的样式类型,即,书 1 将使用全局样式,而书 2 将使用另一个样式。 通过这种方式,我们将了解这些样式中的每一个如何工作以及如何使用它们。 这将帮助您更好地决定选择什么选项。

为简单起见,我搭建了一个 GitHub 存储库供您学习。 你可以在这里抓住它。

create-next-app生成的默认启动器也进行了一些更改。 诸如情感全局模块样式组件等文件夹已添加到styles文件夹中——及其相应的样式文件——以及包含多个组件的components目录。

对演示存储库样式和组件目录所做的初始更改的屏幕截图
对样式和组件文件夹的更改。 (大预览)

修改了index.js文件以importrender所需的components ,并且每个组件的结构都类似于下图所示。

对 BookTwo.js、BookOne.js 和 index.js 所做的初始更改的屏幕截图
对单个组件和索引文件的更改。 (大预览)

如果您克隆并运行了演示存储库,您的页面应该如下所示:

演示存储库中默认索引页面的屏幕截图
来自演示仓库的默认索引页面。 (大预览)

把所有这些都排除在外,让我们开始造型吧。

全球风格

当你开始一个新的 web 项目时,你通常会做的一件常见的事情是重置或规范化你的 CSS,以便在浏览器之间有一个统一的起始位置。 这是一个使用全局 CSS 而不用担心范围的完美示例。

  • 使用扩展的 Minimal CSS Reset 更新styles/global/globals.css
 /* styles/global/globals.css */ html { box-sizing: border-box; font-size: 16px; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; } *, *:before, *:after { box-sizing: inherit; } body, h1, h2, h3, h4, h5, h6, p, ol, ul { margin: 0; padding: 0; font-weight: normal; } h1, h2, h3, h4, h5, h6 { font-weight: bold; } ol, ul { list-style: none; } img { max-width: 100%; height: auto; } a { color: inherit; text-decoration: none; }
  • pages/_app.js中导入 CSS 重置styles/global/globals.css /global/globals.css。
 // pages/_app.js import "../styles/global/globals.css"; function MyApp({Component, pageProps}) { return <Component {...pageProps} />; } export default MyApp;

全局样式只能在pages/_app.js中导入 这是直接合乎逻辑的,因为这些样式将应用于应用程序中的所有pagescomponents ——无论你在哪里导入它们——所以最好有一个单一的 [import] 事实来源,以保持事情简单明了,和/或如果出现问题错误的。

在这一点上,我们的书架没有太多的视觉变化,因为我们只进行了标准化更改。 您可能会注意到的一件事是字体和间距的变化。

添加 CSS 重置后演示书架更改的屏幕截图
添加 CSS 重置后对索引页面的更改。 (大预览)

SASS/SCSS

Next.js 还允许使用带有.sass.scss扩展名的 SASS 进行样式设置。 安装 Sass 是必需的。 就像全局样式一样,它们只能在pages/_app.js中导入。

  • 安装 Sass 包。
 yarn add sass
  • 更新styles/scss/bookshelf.scss
 // styles/scss/bookshelf.scss .the-bookshelf { width: 100vw; height: 100vh; background-color: #e3e3e3; display: flex; justify-content: center; align-items: center; .bookshelf-wrap { > .bookshelf { box-shadow: inset 0 -20px #7b5019; padding-bottom: 20px; display: flex; align-items: flex-end; } [class*="book"] { font-size: 32px; letter-spacing: -0.045em; display: flex; transition: 0.2s; &:hover { transform: none; } } .book-info { text-transform: uppercase; writing-mode: sideways-rl; display: flex; justify-content: space-around; flex: 1; align-items: center; font-weight: bold; padding: 16px 0; .title { font-weight: inherit; font-size: 20px; } .author { font-weight: inherit; font-size: 15px; } } } }
  • 同时更新styles/sass/bookone.sassstyles/sass/booktwo.sass ,如下所示:
 // styles/sass/bookone.sass .book-one color: #f00 width: 78px height: 350px transform: rotate(-4deg) margin-left: 16px margin-right: 23px background-color: black
 // styles/sass/booktwo.sass .book-two color: #781e0b width: 38px height: 448px margin-right: 23px background-color: #ffab44

SASS ( .sass ) 基于缩进。 为了使格式化更容易,您可以安装此 VSCode Extension for SASS 文件支持(格式化、语法高亮...)

  • pages/_app.js中导入三个样式文件styles/scss/bookshelf.scss bookshelf.scss、 styles/sass/bookone.sassstyles/sass/booktwo.sass booktwo.sass。
 // pages/_app.js import "../styles/globals.css"; import "../styles/scss/bookshelf.scss"; import "../styles/sass/bookone.sass"; import "../styles/sass/booktwo.sass"; function MyApp({Component, pageProps}) { return ; } export default MyApp; // pages/_app.js import "../styles/globals.css"; import "../styles/scss/bookshelf.scss"; import "../styles/sass/bookone.sass"; import "../styles/sass/booktwo.sass"; function MyApp({Component, pageProps}) { return ; } export default MyApp;

我们的书架开始成型。 应用样式后,第一本书和第二本书应按预期设置样式和显示。

使用 SASS 设计第一本书和第二本书后对演示书架的更改的屏幕截图
BookOne 和 BookTwo 采用 SASS 样式。 (大预览)

CSS 模块

CSS Modules 是一个组件级的 CSS,它内置在 Next 中,可以通过使用.module.css扩展名命名样式文件来激活。 也可以使用带有.module.sass.module.scss扩展名的 SASS/SCSS 的 CSS 模块。

让我们用它来设置components/BookThree.js组件的样式。

  • 更新styles/modules/BookThree.module.css
 /* styles/modules/BookThree.module.css */ .book-three { color: #df66c3; width: 106px; height: 448px; margin-right: 23px; background-color: #153086; transform: rotate(-4deg); }
  • components/BookThree.js中导入styles/modules/BookThree.module.css BookThree.module.css,并应用.book-three类。
 // components/BookThree.js import BookThreeStyles from "../styles/modules/BookThree.module.css"; export default function BookThree() { return ( <div className={BookThreeStyles["book-three"]}> <div className="book-info"> <p className="title">the revolt of the public</p> <p className="author">Martin Gurri</p> </div> </div> ); }

在 CSS 模块中访问类名类似于 JavaScript 中的属性访问器——使用点或括号表示法。 这里我们导入BookThreeStyles ,然后使用括号符号来应用我们在styles/modules/BookThree.module.css文件中的样式。

如果选择器(在本例中为类名)被正确访问,那么现在应该设置第三本书的样式。

使用 CSS 模块为第三本书设置样式后对演示书架的更改的屏幕截图
BookThree 样式与 CSS 模块。 (大预览)

情感

Emotion 是一个 CSS-in-JS 库,与任何其他 CSS-in-JS 一样,允许您使用 JavaScript 编写 CSS 样式。

让我们用它来设置components/BookFour.js组件的样式。

  • 安装包: @emotion/core@emotion/styledemotionemotion-server
 yarn add @emotion/core @emotion/styled emotion emotion-server
  • 更新styles/emotion/StyledBookFour.js
 // styles/emotion/StyledBookFour.js import styled from "@emotion/styled"; export const StyledBookFour = styled.div` color: white; width: 38px; height: 400px; margin-left: 20px; margin-right: 10px; background-color: #2faad2; transform: rotate(4deg); `;

@emotion/styled导入styled后,我们导出StyledBookFour样式组件——不要与其他 CSS-in-JS 样式组件混淆——使用styled.div中的styled情感方法增强。 然后我们可以在下面的下一步中使用<StyledBookFour/>

了解有关情感样式化功能的更多信息。

  • 使用<StyledBookFour/>类似于使用任何其他 React 组件。 在components/BookFour.js中导入styles/emotion/StyledBookFour.js StyledBookFour.js,并应用StyledBookFour组件。
 // components/BookFour.js import {StyledBookFour} from "../styles/emotion/StyledBookFour"; export default function BookFour() { return ( <StyledBookFour className="book-four"> <div className="book-info"> <p className="title">the man died</p> <p className="author">wole soyinka</p> </div> </StyledBookFour> ); }

有了足够的情感,第四本书应该是这样的风格。

使用 Emotion 设计第四本书后对演示书架的更改的屏幕截图
BookFour 带有情感风格。 (大预览)

样式化的 JSX

与 Global CSS 和 CSS-Modules 一样,Styled-JSX 无需任何额外设置即可与 Next.js 一起使用。 如果有帮助,Styled-JSX 也是 Vercel 提供的基于组件的 CSS,Next.js 的创建者也是如此。

让我们用它来设置components/BookFive.js组件的样式。

为了简单起见,我们在这里使用 styled-jsx 的内部模式。 通过将jsx传递给<style/>组件,我们可以像使用.book-five一样编写尽可能多的 CSS,并且样式被本地化到<BookFive/>组件的额外好处。

 // components/BookFive.js export default function BookFive() { return ( <div className="book-five"> <div className="book-info"> <p className="title">there was a country</p> <p className="author">Chinua Achebe</p> </div> <style jsx>{` .book-five { color: #fff; width: 106px; height: 448px; margin-right: 23px; background-color: #000; transform: rotate(4deg); } `}</style> </div> ); }

就这样,第五本书采用了它的样式。

使用 Styled JSX 为第五本书设置样式后对演示书架的更改的屏幕截图
BookFive 使用 Styled JSX 风格。 (大预览)

样式化的组件

Styled-Component 和 Emotion 一样,也是一个 CSS-in-JS 库,允许您使用 JavaScript 编写 CSS 样式。 设置它有点复杂。

  • 首先,安装babel-plugin-styled-componentsstyled-components
 yarn add babel-plugin-styled-components styled-components
  • 在应用的根目录下创建一个.babelrc文件,以及一个pages/_document.js文件,如下图之前(左)和之后(右)所示。
添加两个新文件 - <code>_.document.js</code> 和 <code>.babelrc</code> 后演示 Bookshelf 更改的屏幕截图
添加了新文件: _document.js.babelrc 。 (大预览)
  • 更新.babelrc文件以包含next/babel预设并包含styled-components插件,并启用服务器端渲染(ssr)。
 // .babelrc { "presets": ["next/babel"], "plugins": [ [ "styled-components", { "ssr": true } ] ] }
  • 通过将服务器端呈现的样式注入<head>更新pages/_document.js

请记住,下面的代码片段 ( pages/_document.js ) 是 styled-components 与 Next.js 一起使用的必需逻辑。 您几乎无需执行任何操作,只需复制 styled-components 文档中指出的逻辑即可。

 // pages/_document.js import Document from "next/document"; import {ServerStyleSheet} from "styled-components"; export default class MyDocument extends Document { static async getInitialProps(ctx) { const sheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; try { ctx.renderPage = () => originalRenderPage({ enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />), }); const initialProps = await Document.getInitialProps(ctx); return { ...initialProps, styles: ( <> {initialProps.styles} {sheet.getStyleElement()} </> ), }; } finally { sheet.seal(); } } }

在更新.babelrcpages/_document.js ,我们现在可以开始使用 styled-components。

  • 更新styles/styled-components/StyledBookSix.js

styled是一种内部实用方法,可将样式从 JavaScript 转换为实际的 CSS。 <StyledBookSix/>可以用作任何其他 React 组件。

 // styles/StyledBookSix.js import styled from "styled-components"; const StyledBookSix = styled.div` color: #fff; width: 106px; height: 448px; margin-right: 23px; background-color: rebeccapurple; `; export default StyledBookSix;

了解有关如何在 React 中使用样式化组件的更多信息。

  • 在 components/BookSix.js 中导入styles/styled-components/StyledBookSix.js components/BookSix.js ,使用导入的 styled-components <StyledBookSix/>
 // components/BookSix.js import StyledBookSix from "../styles/styled-components/StyledBookSix"; export default function BookSix() { return ( <StyledBookSix className="book-six"> <div className="book-info"> <p className="title">purple hibiscus</p> <p className="author">chimamanda ngozi adichie</p> </div> </StyledBookSix> ); }

第一步到第六步完成后,第六步应该样式化,书架完成:

使用 Styled Components 为第六本书设置样式后对演示书架的更改的屏幕截图
BookSix 使用样式化组件进行样式化。 (大预览)

而已。

如果一切顺利,那么您应该拥有完整的书架,其中包含等待阅读的书籍。

  • 您可以在 GitHub 上获取完整代码 →

结论

在我自己使用 Next.js 时,全局样式和样式组件通常就足够了。 但毫无疑问,所有这些方法都有其优点和缺点。 当你决定使用什么方法时,请记住:最后,它都是 CSS。 在这一点上,我相信您可以确定在您的下一个项目中哪种模式最适合您。

资源

我发现要学习使用 Next.js 设置样式方法,没有比它的官方文档更好的地方了。

但也有各种样式方法的特定存储库。 您可以通过各种存储库了解更多信息,或检查更新,因为事情可能会隐身更改。

  1. 顺风 CSS
  2. CSS 模块
  3. 较少的
  4. 手写笔
  5. 带有情感的 Tailwind CSS
  6. Styletron
  7. 魅力
  8. CXS
  9. 阿芙罗狄蒂
  10. 费拉
  11. 样式化的 JSX