比較 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