찾다
웹 프론트엔드HTML 튜토리얼简单易懂的CSS Modules_html/css_WEB-ITnose

不要误会,CSS Modules可不是在说“css模块化”这个好像在某些地方见过的词,它其实是特指一种近期才出现的技术手段。

什么技术手段呢?请待后文说明。

层叠样式表

我们知道,css的全名叫做层叠样式表,这个“层叠”到底是什么意思呢?

有一种解释是,如果你先写了一条样式规则(选手1):

.title {    color: silver;}

然后又在后边写了一条类似的(选手2):

.title {    color: gold;}

因为名字相同,选手2就会和选手1打起来(让你丫冒充我!)。结果是选手2获胜,class名为 title 的元素,最终的 color 值为 gold 。

css里就像这样,随时可能一言不和就发生战争,结果输掉的一方就会被胜利的一方所覆盖。“层叠”一词可以说形象地描述了这个过程。

那么,为什么会有这样的层叠(zhàn zhēng )呢?

css的作用域问题

在javascript里,可以做到这样的搭配:

var title = "silver";(function(){    var title = "gold";    console.log(title); // gold}());console.log(title); // silver

利用javascript的函数作用域,两位同样名为 title 的选手可以友好相处。

但回到css里的样式规则,情况就完全不是这么回事了。

css不是程序语言,但如果说要给它加一个作用域的概念的话,那就是:只有全局作用域。

无论分拆为多少个css文件,无论用怎样的方式引入, 所有的样式规则都位于同一作用域,只要选择符近似,就有发生覆盖的可能 。

减少相互影响的策略

为减少相互影响,避免预料之外的样式覆盖,我们一直以来想过很多办法。

比如你接手一个别人留下来的旧项目,接下来要新增一个标题元素的时候,你会有意识地不去使用 .title 这样模糊的class名,因为它太容易重名了。最终,你用的名称可能是:

.module-sp-title {    color: deepskyblue;}

即使你决定要用 .title 这个名字,你也会加上包含选择符作为限定:

.module-1 .title {     font-size: 18px;}/* ... */.module-2 .title {    font-size: 14px;}

其中 .module-1 和 .module-2 的名字应该是唯一的,这样的代码在组件化(模块化)的开发风格里很常见。

此外,一些有名的css理论,如 SMACSS ,会建议你为所有布局样式使用 l- 或 layout- 的前缀,以示区分。

类似的做法还有很多,但归结起来,都是在尝试 提供一种合理的命名约定 。而合理的命名约定,的确是组织css代码的有效策略。

现在,我们有了新的可用策略,CSS Modules就是其中之一。

技术流的模块化

CSS Modules 是一种技术流的组织css代码的策略,它将为css提供默认的局部作用域。

CSS Modules是如何做到的呢?来看一个CSS Modules的简单例子吧。

有这样的一个html元素:

<h2 id="a-title-for-CSS-Modules">a title for CSS Modules</h2>

按照普通css的写法,我们可以这样为它添加样式:

.title {    background-color: snow;}

现在我们改用CSS Modules。首先,css保持不变。然后,修改html的写法。不再这样直接写html,而是改为在javascript文件里动态添加,这样做(css文件名为 main.css ):

var styles = require("./main.css");var el = document.getElementById("example_title");el.outerHTML = '<h2 id="a-title-for-CSS-Modules">a title for CSS Modules</h2>';

咦, require 了一个css文件?对的,所以要用到webpack。编译后,html和css会变成这样:

看到这样不太美观的class名你大概就明白了,CSS Modules无法改变css全局作用域的本性,它是依靠动态生成class名这一手段,来实现局部作用域的。显然,这样的class名就可以是唯一的,不管原本的css代码写得有多随便,都可以这样转换得到不冲突的css代码。

模拟的局部作用域也没有关系,它是可靠的。

这个CSS Modules的例子说完了,但你一定跟我最初看到的时候一样有很多问题。

CSS Modules的应用细节

如何启用CSS Modules

“webpack编译css我也用过,怎么我用的时候不长这样?”

一般来说, require 一个css文件的写法是:

require("./main.css");

但在前面的例子中,用了 var styles = require("./main.css"); 的写法。这就好像是在说,我要这个css文件里的样式是局部的,然后我根据需要自行取用。

在项目里应用CSS Modules有很多方法,目前比较常用的是使用webpack的 css-loader 。在webpack配置文件里写 css-loader?modules 就可以开启CSS Modules,例如前面的例子所用的:

module: {    loaders: [{        test: /\.css$/,        loader: 'style!css?modules'    }]}

才发现一直用着的css-loader原来有这功能?其实,CSS Modules确实是一个后来才并入css-loader的新功能。

自定义生成的class名

“名字都这样了,还怎么调试?”

为css-loader增加 localIdentName 参数,是可以指定生成的名字。 localIdentName 的默认值是 [hash:base64] ,一般开发环境建议用类似这样的配置:

{    test: /\.css$/,    loader: 'style!css?modules&localIdentName=[name]__[local]___[hash:base64:5]'}

同样应用到前面的例子里,这时候就会变成这样的结果:

这样是不是要有意义多了?

如果是线上环境,可以考虑用更短的名字进一步减小css文件大小。

CSS Modules下的html

(看了前面例子里的 el.outerHTML = ... 后)

“什么,outerHTML?class名还要拼接?你家html才这么写呢!”

很遗憾,CSS Modules官方的例子,也是这个意思: 要使用CSS Modules,必须想办法把变量风格的class名注入到html中 。也就是说,html模板系统是必需的,也正是如此,相比普通css的情况,CSS Modules的html写起来要更为费劲。

如果你搜一下CSS Modules的demo,可以发现大部分都是基于React的。显然,虚拟DOM风格的React,搭配CSS Modules会很容易(ES6):

import styles from './ScopedSelectors.css';import React, { Component } from 'react';export default class ScopedSelectors extends Component {  render() {    return (      <div className={ styles.root }>        <p className={ styles.text }>Scoped Selectors</p>      </div>    );  }};

如果不使用React,还是那句话,只要有办法把变量风格的class名注入到html中,就可以用CSS Modules。原始的字符串拼接的写法显然很糟糕,但我们可以借助各种模板引擎和编译工具做一些改进。下面请看一个用 Jade 的参考示例。

想象一下你有一个用普通css的页面,但你想在一小块区域使用CSS Modules。这一块区域在一个容器元素里:

<div id="module_sp_container"></div>

然后用jade来写html(关联的css文件为 module_sp.css ):

- styles = require("./module_sp.css");h2(class=styles.title) a title for CSS Modules

接下来,仍然是在javascript里添加这段jade生成的html:

var el = document.getElementById("module_sp_container");var template = require("./main.jade");el.innerHTML = template();

最后,记得在css-loader启用CSS Modules的同时,增加jade-loader:

{    test: /\.jade$/,    loader: 'jade'}

编译运行,就可以得到想要的结果。除Jade以外,还有些其他CSS Modules的html应用方案,推荐参考 github上的这篇issue 。

目前CSS Modules还在发展中,而且也在考虑改进CSS Modules下的html写作体验。CSS Modules团队成员有提到一个叫 CSS Modules Injector 的未来规划项目,目的是让开发者不用javascript也可以使用CSS Modules(这就很接近原生html + css的组合了)。

CSS Modules下的样式复用

“样式都是唯一的了,怎么复用?”

我们已经说了挺多普通css单个全局作用域的坏处。但对应的,这也有一个很大的好处,就是便于实现样式的复用。css理论 OOCSS 也是在追求这一点。

CSS Modules提供一个 composes 方法用于样式复用。例如,你有一个 btn.css 里有一条:

.btn{    display: inline-block;}

然后,你在另一个CSS Module的 module_sp.css 里可以这样引入它:

.btn-sp{    composes: btn from "./btn.css";    font-size: 16px;}

那么,这个 div.btn-sp 的DOM元素将会是:

可以看到, composes 的用法比较类似sass的 @extend ,但不同于 @extend 的是, composes 并不增加css里的选择符总量,而是采用组合多个class名的形式。在这个例子里,原本仅有1个class的 div.btn-sp ,变成了2个class。

因此,CSS Modules建议只使用1个class就定义好对应元素所需的全部样式。它们会再由CSS Modules转换为适当的class组合。

CSS Modules团队成员认为 composes 是CSS Modules里最强大的功能:

For me, the most powerful idea in CSS Modules is composition, where you can deconstruct your visual inventory into atomic classes, and assemble them at a module level, without duplicating markup or hindering performance.

更详细的 composes 的用法及其理解,推荐阅读 CSS Modules: Welcome to the Future 。

其他可能有用的补充

和已有的普通css共存

很多项目会引入Bootstrap、 Materialize 等框架,它们是普通的、全局的css。此外,你也可能自己会写一些普通css。如何共存呢?CSS Modules团队成员对此提到过:

a CSS Module should only import information relative to it

意思是,建议把CSS Modules看做一种新的css,和原来的普通css区分开来。比如, composes 的时候,不要从那些普通的css里去取。

在css-loader里通过指定 test 、 include 、 exclude 来区分它们。保持CSS Modules的纯净,只有想要应用CSS Modules的css文件,才启用CSS Modules。

只转换class和id

经过我自己的测试,CSS Modules只转换class和id,此外的标签选择符、伪类等都不会被转换。

建议只使用class。

一个CSS Module的输出

简单用 console.log() 就可以查看CSS Module的输出:

var styles = require("./main.css");console.log("styles = ", styles);

结果类似这样:

{    "btn-sp":  "_2SCQ7Kuv31NIIiVU-Q2ubA _2r6eZFEKnJgc7GLy11yRmV",    title: "_1m-KkPQynpIso3ofWhMVuK"}

这可以帮助理解CSS Modules是怎样工作的。

预编译器

sass等预编译器也可以用CSS Modules,对应的loader可能是这样:

{    test: /\.scss$/,    loader: 'style!css?modules!resolve-url!sass?sourceMap'}

注意不要因为是sass就习惯性地用嵌套写法,CSS Modules并不适合使用包含选择符。

建议的命名方式

CSS Modules会把 .title 转换为 styles.title ,由于后者是用在javascript中,因此驼峰命名会更适合。

如果像我之前那样写 .btn-sp ,需要注意在javascript中写为 styles["btn-sp"] 。

此外,你还可以为css-loader增加 camelCase 参数来实现自动转换:

{    test: /\.css$/,    loader: 'style!css?modules&camelCase',}

这样即便你写 .btn-sp ,你也可以直接在javascript里用 styles.btnSp 。

结语

无论是一直以来我们认真遵循的命名约定,还是这个新的CSS Modules,目的都是一样的:可维护的css代码。我觉得就CSS Modules基本还是在写css这一点来说,它还是很友好的。

虽然本文为了严谨,结果写了相当长的篇幅,但希望你读过之后,还能觉得CSS Modules是简单易懂的。因为这样,我就达成我的目的:扣题,了。

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
HTML 코드를 어떻게 검증 할 수 있습니까?HTML 코드를 어떻게 검증 할 수 있습니까?Apr 24, 2025 am 12:04 AM

HTML 코드는 온라인 유효성 검사기, 통합 도구 및 자동화 된 프로세스를 통해 깨끗할 수 있습니다. 1) w3cmarkupvalidationservice를 사용하여 온라인으로 HTML 코드를 확인하십시오. 2) 실시간 확인을 위해 VisualStudioCode에 HTMLHINT 확장을 설치하고 구성하십시오. 3) htmltidy를 사용하여 시공 프로세스에서 HTML 파일을 자동으로 확인하고 청소하십시오.

HTML vs. CSS 및 JavaScript : 웹 기술 비교HTML vs. CSS 및 JavaScript : 웹 기술 비교Apr 23, 2025 am 12:05 AM

HTML, CSS 및 JavaScript는 최신 웹 페이지를 구축하기위한 핵심 기술입니다. 1. HTML 웹 페이지 구조를 정의합니다. 2. CSS는 웹 페이지의 모양을 담당합니다.

마크 업 언어로서의 HTML : 기능과 목적마크 업 언어로서의 HTML : 기능과 목적Apr 22, 2025 am 12:02 AM

HTML의 기능은 웹 페이지의 구조와 내용을 정의하는 것이며, 그 목적은 정보를 표시하는 표준화 된 방법을 제공하는 것입니다. 1) HTML은 타이틀 및 단락과 같은 태그 및 속성을 통해 웹 페이지의 다양한 부분을 구성합니다. 2) 콘텐츠 및 성능 분리를 지원하고 유지 보수 효율성을 향상시킵니다. 3) HTML은 확장 가능하므로 사용자 정의 태그가 SEO를 향상시킬 수 있습니다.

HTML, CSS 및 JavaScript의 미래 : 웹 개발 동향HTML, CSS 및 JavaScript의 미래 : 웹 개발 동향Apr 19, 2025 am 12:02 AM

HTML의 미래 트렌드는 의미론 및 웹 구성 요소이며 CSS의 미래 트렌드는 CSS-In-JS 및 CSShoudini이며, JavaScript의 미래 트렌드는 WebAssembly 및 서버리스입니다. 1. HTML 시맨틱은 접근성과 SEO 효과를 향상시키고 웹 구성 요소는 개발 효율성을 향상 시키지만 브라우저 호환성에주의를 기울여야합니다. 2. CSS-in-JS는 스타일 관리 유연성을 향상 시키지만 파일 크기를 증가시킬 수 있습니다. CSShoudini는 CSS 렌더링의 직접 작동을 허용합니다. 3. Webosembly는 브라우저 애플리케이션 성능을 최적화하지만 가파른 학습 곡선을 가지고 있으며 서버리스는 개발을 단순화하지만 콜드 스타트 ​​문제의 최적화가 필요합니다.

HTML : 구조, CSS : 스타일, 자바 스크립트 : 동작HTML : 구조, CSS : 스타일, 자바 스크립트 : 동작Apr 18, 2025 am 12:09 AM

웹 개발에서 HTML, CSS 및 JavaScript의 역할은 다음과 같습니다. 1. HTML은 웹 페이지 구조를 정의하고, 2. CSS는 웹 페이지 스타일을 제어하고 3. JavaScript는 동적 동작을 추가합니다. 그들은 함께 현대 웹 사이트의 프레임 워크, 미학 및 상호 작용을 구축합니다.

HTML의 미래 : 웹 디자인의 진화 및 트렌드HTML의 미래 : 웹 디자인의 진화 및 트렌드Apr 17, 2025 am 12:12 AM

HTML의 미래는 무한한 가능성으로 가득합니다. 1) 새로운 기능과 표준에는 더 많은 의미 론적 태그와 WebComponents의 인기가 포함됩니다. 2) 웹 디자인 트렌드는 반응적이고 접근 가능한 디자인을 향해 계속 발전 할 것입니다. 3) 성능 최적화는 반응 형 이미지 로딩 및 게으른로드 기술을 통해 사용자 경험을 향상시킬 것입니다.

HTML vs. CSS vs. JavaScript : 비교 개요HTML vs. CSS vs. JavaScript : 비교 개요Apr 16, 2025 am 12:04 AM

웹 개발에서 HTML, CSS 및 JavaScript의 역할은 다음과 같습니다. HTML은 컨텐츠 구조를 담당하고 CSS는 스타일을 담당하며 JavaScript는 동적 동작을 담당합니다. 1. HTML은 태그를 통해 웹 페이지 구조와 컨텐츠를 정의하여 의미를 보장합니다. 2. CSS는 선택기와 속성을 통해 웹 페이지 스타일을 제어하여 아름답고 읽기 쉽게 만듭니다. 3. JavaScript는 스크립트를 통해 웹 페이지 동작을 제어하여 동적 및 대화식 기능을 달성합니다.

HTML : 프로그래밍 언어입니까 아니면 다른 것입니까?HTML : 프로그래밍 언어입니까 아니면 다른 것입니까?Apr 15, 2025 am 12:13 AM

Htmlisnotaprogramminglanguage; itisamarkuplanguage.1) htmlstructuresandformatswebcontentusingtags.2) itworksporstylingandjavaScriptOfforIncincivity, WebDevelopment 향상.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기