成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

組件級樣式方案 CSS Modules 的入門教程

開發 前端
CSS Modules 是一種 CSS 的模塊化方案,主要目的是解決 CSS 樣式的全局命名空間問題。它通過將 CSS 類名和選擇器局部化,讓每個模塊都有自己獨立的樣式作用域,就像在 JavaScript 中的模塊一樣,不同模塊中的同名變量不會相互干擾,也不會導致全局樣式的污染。

平時開發中我們應該沒少為給 DOM 元素取類名更頭疼的了。CSS 樣式是全局的, 為了避免某個部分的樣式被別處的意外覆蓋,我們就要在取類名上想辦法,流行的比如 OOCSS(Object Oriented CSS,.button.button-primary)、 BEM(.block_element--modifier);甚者更加細粒度的 Atomic CSS 方案,這里的代表是Tailwind CSS(.flex.justify-center.items-center.h-scree)。

背景介紹

當然,隨著前端模塊塊、組件化的發展,還有一種折中方案 CSS Modules。CSS Modules[1] 可以因為組件化的流行而聞名。

圖片圖片

CSS  Module 的核心概念就是確保樣式是組件級別的,它將 CSS 樣式文件導入成對象并通過屬性名方式在 DOM 元素上在 class attribute 上引入。

/* style.css */
.container {
  color: green;
}
import styles from './style.css';
element.innerHTML = '<div class="' + styles.container + '">';

當你導入 CSS Modules 文件時,類名實際上會被轉換為唯一的標識符。例如,styles.container 在最終生成的 HTML 和 CSS 中可能會變成類似于 styles_container__[hash] 的本地作用域的形式,其中 [hash] 是一個根據內容生成的哈希值,確保全局唯一性。這樣,我們就能很輕松的設置組件級別的樣式,而不會擔心會影響頁面其他部分的樣式。

由于 CSS Modules 太過好用,基本上現在每個前端項目腳手架工具都有提供支持。不管是 webpack、Vite 還是 Next.js,你都在對應的官方模板中取得 CSS Modules 的支持,在這些腳手架工具搭建的項目中,你通常只要將 CSS 文件以文件后綴改 .module.css(或是由 CSS 預處理器驅動的 .module.less、.module.scss 這些文件后綴)結尾,就會啟用 CSS Modules 模式。

而在組織方式上,.module.css通常與組件文件放一起(像下面這樣):

圖片圖片

如何使用

接下來我們來講解 CSS Modules 各個場景下的使用。

創建項目

我們以 Vite React 項目模板為例,首先創建項目。

npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install 
npm run dev

項目默認就支持 CSS  Modules 的使用。

簡單使用

先從最簡單的使用講起。刪除 src/App.jsx 文件,創建  src/App/index.jsx 以及 src/App/index.module.css 文件,填充以下內容。

// src/App/index.jsx
import styles from './index.module.css'

function App() {
  return (
    <div className={styles.container}>
      <h1>My First React App</h1>
      <p>This is a paragraph</p>
    </div>
  );
}

export default App;
/* src/App/index.module.css */
.container {
  color: red;
}

渲染效果如下:

圖片圖片

可以看到 styles.container 渲染成了 _container_2rp1n_1,如上所示,**雖然 CSS Modules 并沒有強制使用類名的格式,但還是首選采用駝峰命名[2](類似:styles.className)。

_container_2rp1n_1 是 Vite 的默認配置生成的結果,我們可以在 vite.config.js 中進行修改,讓樣式層級更加直觀。

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
+  css: {
+    modules: {
+      generateScopedName: '[name]__[local]___[hash:base64:5]'
+    }
+  }
})

修改后,效果如下:

圖片圖片

styles.container 渲染成了 index-module__container___KpZIM。更加配置可以參考 css.module 的配置說明[3]。

父子同名類名

接下來,我們在同級目錄下創建 components/Hello/ 組件。

// src/components/Hello/index.jsx
import styles from './index.module.css'

export function Hello() {
  return (
    <div className={styles.container}>
      <h1>Hello World</h1>
      <p>This is a React component</p>
    </div>
  )
}
/* src/components/Hello/index.module.css */
.container {
  color: blue;
}

src/App/index.jsx 中引入:

import styles from './index.module.css'
+ import { Hello } from '../components/Hello'

function App() {
  return (
    <div className={styles.container}>
      <h1>My First React App</h1>
      <p>This is a paragraph</p>
+     <Hello />
    </div>
  );
}

export default App;

效果如下:

圖片圖片

雖然 <App> 和 <Hello> 組件中都使用了一樣的類名,但最終生成出來是不一樣的,這就是作用域樣式了。

類名組合

除了提供 CSS 作用域類名的核心能力,CSS Modules 還有支持類名組合,說白了就是樣類名組合能力。

下面,我們修改 App 組件:

/* src/App/index.module.css */
.container {
  display: flex;
  gap: 16px;
}

.button {
  cursor: pointer;
  padding-block: 8px;
  padding-inline: 16px;
  font-size: inherit;
}

.buttonExtend {
  composes: button;
  color: blue;
}

注意看,在 .buttonExtend 中,我們使用了 composes: button。

/* src/App/index.jsx */
import styles from './index.module.css'

function App() {
  console.log('styles', styles)

  return (
    <div className={styles.container}>
      <button className={styles.button}>button</button>
      <button className={styles.buttonExtend}>extend button</button>
    </div>
  );
}

export default App;

查看效果:

圖片圖片

會發現,styles.buttonExtend 的值為 index-module__buttonExtend___vz-2k index-module__button___gnncC,組合了 styles.button 的值,composes 的作用有點類似 Bootstrap 中 **.button.button-primary** 的用法,不過對 CSS Modules 來說,這種關系是在 module.css 文件中聲明的,無需在 DOM 元素 class 上顯式書寫。

當然,你還可以在類名上直接應用偽類:

.button:hover {
  transform: scale(1.1);
  transition: transform 0.15s ease;
}

效果如下:

圖片圖片

如此,2 個按鈕就有了 hover 時的放大效果了。

比較厲害的是,composes 的類名來源還可以是來自外部文件的,類似下面的用法

.otherClassName {
  composes: className from './style.module.css';
}

我們創建一個 src/App/other.module.css 文件出來,將 .button 的類名導入進來:

/* src/App/other.module.css */
.button {
  cursor: pointer;
  padding-block: 8px;
  padding-inline: 16px;
  font-size: inherit;
}

.button:hover {
  transform: scale(1.1);
  transition: transform 0.15s ease;
}

修改 src/App/index.module.css:

.buttonExtend {
  composes: button from './other.module.css';
  color: blue;
}

查看效果:

圖片圖片

發現由 .button 產生的類名變成 other-module 下面的了。

局部類名下的全局樣式設置

現在,我們在 App.jsx 中將 Hello 組件重新引入,并且給 .container 類名一個 color 設置:

import styles from './index.module.css'
+ import { Hello } from '../components/Hello'

function App() {
  return (
    <div className={styles.container}>
      <button className={styles.button}>button</button>
      <button className={styles.buttonExtend}>extend button</button>
+      <Hello />
    </div>
  );
}

export default App;
.container {
  display: flex;
  gap: 16px;
+ color: coral;
}

查看效果:

圖片圖片

可以看到,雖然我們在 .container 上設置了 coral 的顏色,但不會覆蓋 Hello 上 .container 的顏色設置。

圖片圖片

這個時候,如果我們想覆蓋 Hello 下的 div 的顏色設置,就要用到 :global 了。:global 不是標準 CSS 的一部分,而是像 CSS Modules 這類 CSS-in-JS 庫擴展出來的,用來逃逸模塊作用域為其下的元素應用樣式。

修改 src/App/index.module.css,增加以下樣式:

.container :global div {
  color: yellowgreen;
}

:global div 也可以寫成 :global(div),效果是一樣的。

查看效果:

圖片圖片

發現樣式生效了,當然最好的方式還是直接使用類名。

修改 src/components/Hello/index.jsx 以及 src/App/index.module.css:

// src/components/Hello/index.jsx
import styles from './index.module.css'

export function Hello() {
  return (
-    <div className={styles.container}>
+    <div className={`helloWrapper ${styles.container}`}>
      <h1>Hello World</h1>
      <p>This is a React component</p>
    </div>
  )
}
/* src/App/index.module.css */
- .container :global div
+ .container :global .helloWrapper {
  color: yellowgreen;
}

:global .helloWrapper 也可以寫成 :global(.helloWrapper),效果是一樣的。

查看效果:

圖片圖片

這樣我們設置的樣式就更加有針對性了!

總結

CSS Modules 是一種 CSS 的模塊化方案,主要目的是解決 CSS 樣式的全局命名空間問題。它通過將 CSS 類名和選擇器局部化,讓每個模塊都有自己獨立的樣式作用域,就像在 JavaScript 中的模塊一樣,不同模塊中的同名變量不會相互干擾,也不會導致全局樣式的污染。

除此之外,CSS Modules 還提供了樣式組合、局部類名下的全局選擇器選擇,豐富了它的能力。

責任編輯:武曉燕 來源: 寫代碼的寶哥
相關推薦

2010-08-17 13:28:31

DIVCSS

2024-07-30 09:08:32

2024-11-12 15:46:37

2013-08-29 14:12:52

Storm分布式實時計算

2010-08-03 13:06:15

Flex Builde

2009-07-08 15:12:48

Java Servle

2014-05-26 15:35:55

Web組件Web Compone

2010-08-16 09:56:05

DivCSS

2010-03-12 14:04:32

Python入門教程

2022-07-21 11:58:12

Docker

2022-07-12 08:27:18

Zadig開源

2010-08-16 09:32:01

DivCSS

2010-08-16 10:10:11

DIV+CSS

2010-05-21 12:50:45

Subversion快

2010-06-13 09:45:35

Widget開發

2011-07-21 10:29:18

iPhone 開發

2012-05-10 08:29:46

XcodeiOSPhoneGap

2013-08-29 14:28:09

StormHadoop

2010-08-03 14:37:30

Flex入門教程

2010-07-27 15:53:15

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲一二三区不卡 | 欧美在线一区二区三区 | 日韩二区| 国产精品一区二区三区久久 | 国产在线一区二区 | 精久久久久 | 中文字幕亚洲一区二区三区 | 亚洲区一区二 | 先锋资源亚洲 | 亚洲欧美日韩久久久 | 亚洲精品国产综合区久久久久久久 | 日日操日日干 | 成人在线中文字幕 | 亚洲精品久久久蜜桃网站 | av中文字幕在线观看 | 精品欧美一区二区三区免费观看 | 天天综合永久入口 | 成人天堂噜噜噜 | 男女免费在线观看视频 | 日韩视频在线免费观看 | 日本aa毛片a级毛片免费观看 | 成人二区| 久久精品av麻豆的观看方式 | 视频在线一区 | 国产中文字幕在线 | 日本久草| 亚洲欧美日韩网站 | 亚洲午夜精品视频 | 中文字幕一区二区三 | 国产精品久久久久久av公交车 | 国产精品1区2区 | 午夜精品久久久久久 | 欧美日一区二区 | 国产免费一区二区三区 | 国产精品美女久久久久aⅴ国产馆 | 国产91亚洲精品 | 亚洲欧美日韩久久 | 99资源站| 日韩免费中文字幕 | 亚洲先锋影音 | 亚洲精品视频在线播放 |