电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

簡單明了帶你了解CSS Modules

瀏覽:139日期:2022-06-02 17:47:54

層疊樣式表

我們知道,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="example_title">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>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是簡單易懂的。因為這樣,我就達成我的目的:扣題,了。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持。

標簽: CSS HTML
相關文章:
主站蜘蛛池模板: 扬尘在线监测系统_工地噪声扬尘检测仪_扬尘监测系统_贝塔射线扬尘监测设备「风途物联网科技」 | 污水提升器,污水提升泵,地下室排水,增压泵,雨水泵,智能供排水控制器-上海智流泵业有限公司 | 电表箱-浙江迈峰电力设备有限公司-电表箱专业制造商 | 桁架机器人_桁架机械手_上下料机械手_数控车床机械手-苏州清智科技装备制造有限公司 | 右手官网|右手工业设计|外观设计公司|工业设计公司|产品创新设计|医疗产品结构设计|EMC产品结构设计 | 洁净棚-洁净工作棚-无菌室-净化工程公司_北京卫护科技有限公司 | 蚂蚁分类信息系统 - PHP同城分类信息系统 - MayiCMS | 长信科技产业园官网_西安厂房_陕西标准工业厂房 | 紧急切断阀_气动切断阀_不锈钢阀门_截止阀_球阀_蝶阀_闸阀-上海上兆阀门制造有限公司 | 四川职高信息网-初高中、大专、职业技术学校招生信息网 | 破碎机_上海破碎机_破碎机设备_破碎机厂家-上海山卓重工机械有限公司 | 课件导航网_ppt课件_课件模板_课件下载_最新课件资源分享发布平台 | 煤矿人员精确定位系统_矿用无线通信系统_煤矿广播系统 | 新型锤式破碎机_新型圆锥式_新型颚式破碎机_反击式打沙机_锤式制砂机_青州建源机械 | 河南档案架,档案密集架,手动密集架,河南密集架批发/报价 | 钢结构-钢结构厂房-钢结构工程[江苏海逵钢构厂] | 学习安徽网| 动库网动库商城-体育用品专卖店:羽毛球,乒乓球拍,网球,户外装备,运动鞋,运动包,运动服饰专卖店-正品运动品网上商城动库商城网 - 动库商城 | 衢州装饰公司|装潢公司|办公楼装修|排屋装修|别墅装修-衢州佳盛装饰 | 北京森语科技有限公司-模型制作专家-展览展示-沙盘模型设计制作-多媒体模型软硬件开发-三维地理信息交互沙盘 | 上海电子秤厂家,电子秤厂家价格,上海吊秤厂家,吊秤供应价格-上海佳宜电子科技有限公司 | 钢格栅板_钢格板网_格栅板-做专业的热镀锌钢格栅板厂家-安平县迎瑞丝网制造有限公司 | 污水处理设备,一体化泵站,一体化净水设备-「梦之洁环保设备厂家」 | 网带通过式抛丸机,,网带式打砂机,吊钩式,抛丸机,中山抛丸机生产厂家,江门抛丸机,佛山吊钩式,东莞抛丸机,中山市泰达自动化设备有限公司 | 环氧铁红防锈漆_环氧漆_无溶剂环氧涂料_环氧防腐漆-华川涂料 | 植筋胶-粘钢胶-碳纤维布-碳纤维板-环氧砂浆-加固材料生产厂家-上海巧力建筑科技有限公司 | 捷码低代码平台 - 3D数字孪生_大数据可视化开发平台「免费体验」 | 户外环保不锈钢垃圾桶_标识标牌制作_园林公园椅厂家_花箱定制-北京汇众环艺 | 拉伸膜,PE缠绕膜,打包带,封箱胶带,包装膜厂家-东莞宏展包装 | 头条搜索极速版下载安装免费新版,头条搜索极速版邀请码怎么填写? - 欧远全 | PVC地板|PVC塑胶地板|PVC地板厂家|地板胶|防静电地板-无锡腾方装饰材料有限公司-咨询热线:4008-798-128 | 铸铁平台,大理石平台专业生产厂家_河北-北重机械 | 车件|铜件|车削件|车床加工|五金冲压件-PIN针,精密车件定制专业厂商【东莞品晔】 | 奥运星-汽车性能网评-提供个性化汽车资讯| 陕西安玻璃自动感应门-自动重叠门-磁悬浮平开门厂家【捷申达门业】 | 石膏基自流平砂浆厂家-高强石膏基保温隔声自流平-轻质抹灰石膏粉砂浆批发-永康市汇利建设有限公司 | 电动卫生级调节阀,电动防爆球阀,电动软密封蝶阀,气动高压球阀,气动对夹蝶阀,气动V型调节球阀-上海川沪阀门有限公司 | 申江储气罐厂家,储气罐批发价格,储气罐规格-上海申江压力容器有限公司(厂) | 合肥钣金加工-安徽激光切割加工-机箱机柜加工厂家-合肥通快 | 二手Sciex液质联用仪-岛津气质联用仪-二手安捷伦气质联用仪-上海隐智科学仪器有限公司 | 多米诺-多米诺世界纪录团队-多米诺世界-多米诺团队培训-多米诺公关活动-多米诺创意广告-多米诺大型表演-多米诺专业赛事 |