当前位置:

首页 > 编程开发 > 简单明了带你了解CSS Modules

简单明了带你了解CSS Modules

CSSModules通过动态生成唯一class名实现CSS局部作用域,避免样式冲突。需借助webpack及css-loader启用modules选项,支持自定义类名和样式复用(composes),可与普通CSS样式共存,提供灵活的样式隔离,显著提升代码可维护性和模块化程度。

本文目录

    层叠样式表,这个名字听起来挺学术的,但“层叠”到底在说什么?

    简单打个比方:你给一个元素写了第一条样式规则,选手1:.title { color: silver; }。然后又在后面写了第二条,选手2:.title { color: gold; }。名字一模一样,两位选手自然就干起来了。结果是选手2胜出,class名为title的元素最终颜色变成了gold。CSS里这种“一言不合就覆盖”的机制,就是“层叠”这个词最形象的写照。

    那么问题来了——为什么CSS里会频繁发生这种“战争”?

    CSS的作用域问题

    在Ja vaScript里,同样名字的变量可以通过函数作用域和平共处:

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

    但CSS就没这么幸运了。它没有自己的作用域概念,严格来说,只有一个全局作用域。不管你拆分多少个CSS文件,用什么方式引入,所有样式规则都挤在同一个空间里。只要选择符长得像,就可能发生意外覆盖。

    减少相互影响的策略

    为了避免这种“你覆盖我、我覆盖你”的尴尬,开发者们想了很多办法。

    比如接手一个旧项目,要新增一个标题元素,你肯定不会再用.title这种模糊的class名——太容易撞车了。最后你可能会用类似.module-sp-title这样的名字。如果你非要叫.title,也会加上包含选择符来限定:

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

    这里.module-1和.module-2的名字通常是唯一的,这种写法在组件化开发中很常见。除此之外,像SMACSS这样的方法论会建议你给布局样式统一加l-或layout-前缀。这些做法归结起来,都是在尝试建立一套合理的命名约定——这确实是组织CSS代码的有效手段。

    现在,我们有了新的选择:CSS Modules。

    技术流的模块化

    CSS Modules是一种通过技术手段来组织CSS代码的策略,它的核心目标是为CSS提供默认的局部作用域。怎么做到的呢?看一个简单的例子。

    有一个HTML元素:

    a title for CSS Modules

    普通CSS会这样写:

    .title { background-color: snow; }

    改用CSS Modules后,CSS代码保持不变,但HTML不再直接写在文件里,而是通过Ja vaScript动态生成(假设CSS文件名为main.css):

    var styles = require("./main.css");
    var el = document.getElementById("example_title");
    el.outerHTML = '

    a title for CSS Modules

    ';

    这里require了一个CSS文件,所以需要webpack来编译。编译之后,HTML和CSS会变成这样:

    简单明了带你了解CSS Modules

    看到这种不美观的class名,你大概就明白了:CSS Modules并没有改变CSS全局作用域的本质,它靠的是动态生成唯一class名来实现局部作用域。这样一来,不管原本的CSS代码写得多么随意,都能转成不冲突的代码。模拟的局部作用域,但这套机制是可靠的。

    例子讲完了,但一开始接触的时候,你肯定跟我当时一样,脑子里冒出一堆问题。

    CSS Modules的应用细节

    如何启用CSS Modules

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

    通常我们require一个CSS文件是这么写的:require("./main.css");。但上面的例子用了var styles = require("./main.css");,这相当于说:“我要这个CSS文件里的样式是局部的,然后按需取用。” 在项目里启用CSS Modules,目前比较常见的是用webpack的css-loader,在配置里加上css-loader?modules就行:

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

    是不是才发现一直用的css-loader还藏着这个功能?CSS Modules确实是后来才并入css-loader的新功能。

    自定义生成的class名

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

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

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

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

    简单明了带你了解CSS Modules

    这样是不是有意义多了?线上环境可以考虑用更短的名字来减小CSS文件大小。

    CSS Modules下的html

    看了前面el.outerHTML = ...的写法,你可能会说:“什么?outerHTML?class名还要拼接?你家html才这么写呢!”

    确实,CSS Modules官方的例子就是这个意思:要使用CSS Modules,必须想办法把变量风格的class名注入到HTML中。也就是说,HTML模板系统是必需的,这也意味着比普通CSS写起来更费劲。如果你搜一下CSS Modules的demo,会发现大部分都是基于React的——虚拟DOM风格的React搭配CSS Modules非常顺手:

    import styles from './ScopedSelectors.css';
    import React, { Component } from 'react';
    export default class ScopedSelectors extends Component {
        render() {
            return (
                

    Scoped Selectors

    ); } }

    如果不使用React,只要能把变量class名注入到HTML中,就可以用CSS Modules。原始的字符串拼接写法很糟糕,但可以借助模板引擎和编译工具来改进。下面看一个用Jade的参考示例。

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

    然后用Jade来写HTML(关联的CSS文件为module_sp.css):

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

    接下来在Ja vaScript里添加这段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,还有其他方案,推荐参考GitHub上的相关issue。目前CSS Modules还在发展中,团队也在考虑改进HTML写作体验,有一个叫“CSS Modules Injector”的未来规划项目,目的是让开发者不使用Ja vaScript也能使用CSS Modules——这就很接近原生HTML+CSS的组合了。

    CSS Modules下的样式复用

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

    前面说了很多普通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元素会变成这样:

    简单明了带你了解CSS Modules

    可以看到,composes的用法类似Sass的@extend,但不同之处在于,composes不增加CSS选择符的总量,而是采用组合多个class名的形式。原本只有一个class的div.btn-sp变成了两个class。因此,CSS Modules建议只用一个class定义元素所需的全部样式,再由CSS Modules转换成适当的class组合。

    CSS Modules团队成员认为composes是CSS Modules最强大的功能:“对我来说,CSS Modules最强大的理念就是组合。你可以把视觉元素拆解成原子类,然后在模块级别组合它们,既不会重复标记,也不会影响性能。”

    更详细的composes用法,推荐阅读《CSS Modules: Welcome to the Future》。

    其他可能有用的补充

    和已有的普通CSS共存

    很多项目会引入Bootstrap、Materialize等框架,它们是全局的普通CSS。如何共存?CSS Modules团队成员的建议是:“一个CSS Module应该只导入与它自身相关的信息。” 也就是说,把CSS Modules看作一种新的CSS,与普通CSS区分开来。比如在composes时,不要从那些普通CSS里取。在css-loader里通过指定test、include、exclude来区分它们,保持CSS Modules的纯净——只有想要应用CSS Modules的CSS文件才启用它。

    只转换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,后者用在Ja vaScript中,驼峰命名会更合适。如果像之前那样写.btn-sp,在Ja vaScript中需要写styles["btn-sp"]。也可以给css-loader增加camelCase参数来实现自动转换:

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

    这样即使写.btn-sp,也能在Ja vaScript里直接用styles.btnSp。

    结语

    无论是我们一直认真遵循的命名约定,还是这个新的CSS Modules,目的都一样:写出可维护的CSS代码。在我看来,CSS Modules基本还是在写CSS,这一点对开发者来说是很友好的。虽然本文为了严谨写了不少篇幅,但希望你读完后,还能觉得CSS Modules是简单易懂的——这样我就达成“扣题”的目的了。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 CSS
    相关文章 更多
    米侠浏览器打不开网页
    米侠浏览器打不开网页

    米侠浏览器页面打不开,或者干脆显示一片空白?问题根源大概率出在内核上。比如内核和当前网页的兼容性出了岔子、页面渲染模块意外损坏,再或者,内核版本实在太旧了。别急,沿着切换内核、清理缓存、关闭硬件加速、替换核心文件这四步走,通常都能解决。 用米侠浏览器上网,碰到页面死活刷不出来,或者只显示一个空白屏幕

    IE浏览器怀旧版在线网址
    IE浏览器怀旧版在线网址

    IE浏览器怀旧版在线网址:一次精准的技术时光回溯 最近,不少老用户和怀旧爱好者在反复搜索一个问题:那个经典的Internet Explorer,如今还能在哪里原汁原味地体验到?答案指向一个特定的地址:https://ie.microsoft.com/legacy/。 这个网站远不止是一个简单的“皮肤

    火狐浏览器有哪些设置功能
    火狐浏览器有哪些设置功能

    火狐浏览器五大核心设置功能:解锁高效、安全与个性化体验 火狐浏览器功能强大,但如果不仔细挖掘,很多能大幅提升效率和安全性的设置可能就“藏着掖着”了。这就好比拥有一台高性能设备,却只用了基础模式。那么,如何把它调整到最顺手、最安全的状态?接下来,我们就聚焦于当前版本(截至2025年末)最关键的五大设置

    chrome搜索免验证入口
    chrome搜索免验证入口

    Chrome官方免验证入口为https://www.google.cn/chrome/,提供全平台安装包、免登录即用、本地化安全机制及引擎级性能优化。 到底该去哪里找正版、免费且无需繁琐验证的Chrome浏览器入口?这个问题困扰了不少网友。今天,我们就来直通核心,为大家详细拆解Chrome引擎的官方

    HTML转PDF在线官网
    HTML转PDF在线官网

    HTML转PDF在线官网入口:网页内容一键生成PDF指南 HTML转PDF在线官网入口是https://htmltopdf.com,支持HTML5标签、CSS渲染、多语言字符、Web字体;操作免注册,可预览、自定义参数、批量导出;输出300DPI、保留超链接与矢量图;本地处理保障隐私;兼容主流浏览器

    关于CSS渲染:CSS是如何绘制颜色的
    关于CSS渲染:CSS是如何绘制颜色的

    CSS中颜色基于RGB、CMYK、HSL等模型,RGBA与HSLA支持透明度(alpha通道),另有140种命名颜色、十六进制及currentColor,以及HSL/HSLA写法。渐变分线性与径向两种,可设多个色标、角度、重复及渐变中心,方向可自定义。形状绘制建议优先使用SVG,而非依赖CSS奇技淫巧,因SVG矢量图精确、可缩放、语义清晰且易于维护。

    利用模糊实现视觉3D效果实例讲解
    利用模糊实现视觉3D效果实例讲解

    利用CSS模糊滤镜与清晰对比构建视差,可实现视觉3D效果。例如在文字3D旋转中,对字母单独应用模糊动画;落叶效果则通过不同模糊程度、缩放和速度,模拟近、中、远景层次,增强立体感和深度。

    详解CSS开发过程中的20个快速提升技巧
    详解CSS开发过程中的20个快速提升技巧

    使用CSS重置统一盒模型与边距,继承盒模型简化样式。Flexbox布局避免margin问题,:not()伪类精简边框样式。统一body行高,Flexbox实现垂直居中。SVG图标替代位图,OWL选择器控制垂直间距。box-decoration-break美化换行文本,table-layout实现等宽单元格。属性选择器处理空链接,rem与em配合全局局部缩放。

    css进阶学习 选择符
    css进阶学习 选择符

    CSS选择符的质量影响代码可维护性与性能。浏览器从右向左匹配样式,应使用具体的关键选择符如class,缩短选择符序列,避免链式选择符和多余标签限定,以减少匹配次数,提升渲染效率。

    css列表标签list与表格标签table详解
    css列表标签list与表格标签table详解

    CSS列表样式通过list-style-type属性控制标记类型,list-style-image属性控制标记图像,list-style-position属性控制标记位置,三者可合并简写为list-style属性;表格样式使用border属性设置边框,border-collapse属性合并相邻边框,并支持宽度、高度及文本对齐设置,从而使页面结构清晰美观。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。