前言
这是Glen Maddern发布于2015年8月19日的一篇文章,主要是之前翻译的文章《理解CSS模块方法》里提到这篇文章,现在算是顺藤摸瓜跟进来看看。
这里的翻译都是根据我自己的理解进行的,所以不是一句一句的来的,有哪些不对的也在所难免,水平有限,希望大家指出。
正文
如果想在最近CSS开发思想上找到一个转变点,最好去找Christopher Chedeau 2014年11月在NationJS上发表的“css in js”演讲。这是一个分界线,各种不同的思想,就像高速粒子似的在自己的方向上快速发展。例如:在React及一些依赖React的项目中写样式, React Style,jsxstyle和Radium是其中三个,最新的,最巧妙的,和最可行的方法。如果发明是在一种探索的情况下相邻的可能(adjacent possible),那么christopher是创造了很多接近相邻(adjacent)可能性。
这些问题,以不同的形式存在于大的CSS代码库中。christopher指出,这些问题都可能通过在js中写代码来解决。但这种解决方案引入了其自身的复杂性和特性。只要看一下,在之前提到的项目中(React Style,jsxstyle和Radium),处理在:hover状态下range的方法。这个问题,在浏览器端css中已经早被解决了。
CSS Modules team找到问题的关键--保持和CSS一致,使用styles-in-js的方式编写。虽然我们还是坚持看好使用了CSS的形式,但还有要感谢对我们提供很多建议的朋友。
我们一直在绞尽脑汁地思考CSS,怎样去编写更好。
第1步:默认局部作用域
在css模块中,每一个文件都是独立编译的,因此你可以使用一些CSS短命名-不用担心命名冲突。下面看一下,提交按钮的4种状态的例
常规的CSS书写方法
用Suit或BEM命名、一些CSS样式、一段html。代码如下:
css代码段:
/* components/submit-button.css */
.Button { /* all styles for Normal */ }
.Button--disabled { /* overrides for Disabled */ }
.Button--error { /* overrides for Error */ }
.Button--in-progress { /* overrides for In Progress */
html代码段:
上面代码运行不错,我们有4种状态的类名,BEM命名,避免了使用嵌套选择器。使用大写字母开头的单词Button作为选择器,避免与之前或引用样式的类名冲突。并且我们使用--modifier语法来消除基础样式。
到现在为止,这都是一段不错的可维护的代码。但也引入了严格的命名规范。但这也是能用标准CSS,做到的最好的方式了。
CSS模块书写方法
使用CSS模块,你不用担心使用一些短命名了。可以像下面这样。
/* components/submit-button.css */
.normal { /* all styles for Normal */ }
.disabled { /* all styles for Disabled */ }
.error { /* all styles for Error */ }
.inProgress { /* all styles for In Progress */
看,你不用在任何地方再去加长长的前缀。为什么可以这样做,我们可以像其它语言一样,不用在本地变量前加长长的前缀,只要把CSS对应的文件名改成submit-botton.css。
这可以让在JS中使用require或import加载的CSS模块文件,可以被编译出来。
/* components/submit-button.js */
import styles from './submit-button.css';
buttonElem.outerHTML = ``
真正在页面使用的样式名,是动态生成的唯一标识。CSS模块把文件编译成ICSS格式的文件,这种格式文件可以方便CSS和JS进行通信。当你运行程序,会得到类似下面的代码
得到类似结果,说明运行成功~
命名约定
还是拿按钮的例子来说
/* components/submit-button.css */
.normal { /* all styles for Normal */ }
.disabled { /* all styles for Disabled */ }
.error { /* all styles for Error */ }
.inProgress { /* all styles for In Progress */
所有类名都是独立的,不是一个是基类名,其它的用来修改。在CSS模块中,所有类必须包括所有的属性和样式。这让你在JS中使用类名时有很大的不同。
/* 不要像这样 */
`class=${[styles.normal, styles['in-progress']].join(" ")}`
/* 不同之处是使用单独的类名 */
`class=${styles['in-progress']}`
/* 最好使用驼峰式 */
`class=${styles.inProgress}`
当然,如果你是按照代码量来收钱的,你可以按照你的方式继续。
一个React例子
这里不是关于React特有的CSS模块。但React提供了,在使用CSS模块时,特别优秀的体验。下面做一个复杂点的例子。
/* components/submit-button.jsx */
import { Component } from 'react';
import styles from './submit-button.css';
export default class SubmitButton extends Component {
render() {
let className, text = "Submit"
if (this.props.store.submissionInProgress) {
className = styles.inProgress text = "Processing..."
} else if (this.props.store.errorOccurred) {
className = styles.error
} else if (!this.props.form.valid) {
className = styles.disabled
} else {
className = styles.normal
}
return
}
}
你可以使用你的样式,不用再担心全局冲突,让你可以专注于组件开发,而不是在写样式上。一旦离开之前的频繁在CSS,js之间切换方式,你就再也不想回去了。
但这只是开始,当你考虑样式合并时,CSS模块又没法使用了。
第2步 一切皆为组件
前面提到CSS模块需要每种状态都包含所有所需的样式。
这里假设你需要多个状态,我们对比一下CSS模块和BEM命名。
/* BEM Style */
innerHTML = `
/* CSS Modules */
innerHTML = `
等一下,如何在所有状态共享样式呢?答案是CSS模块的最有力工具-组件。
.common { /* all the common styles you want */ }
.normal { composes: common; /* anything that only applies to Normal */ }
.disabled { composes: common; /* anything that only applies to Disabled */ }
.error { composes: common; /* anything that only applies to Error */ }
.inProgress { composes: common; /* anything that only applies to In Progress */ }
关键词composes指出.normal包含.common中的样式,就像sass里的@extend关键词一样。sass是通过重写css选择器来实现的。css模块则是通过改变js中使用的类名来实现。
SASS:
使用前面的BEM例子,使用一些SASS的@extend
.Button--common { /* font-sizes, padding, border-radius */ }
.Button--normal { @extends .Button--common; /* blue color, light blue background */}
.Button--error { @extends .Button--common; /* red color, light red background */}
这将编译为
.Button--common, .Button--normal, .Button--error { /* font-sizes, padding, border-radius */ }
.Button--normal { /* blue color, light blue background */ }
.Button--error { /* red color, light red background */ }
你只需要在你的标签上引用一个类名,可以得到通用的和独有的样式。功能很强大,但你必须知道,这也存在着特殊情况和陷阱。Hugo Giraudel 汇总了一些问题,想了解更多,请点击《为什么你应该避免使用SASS的@extend》
使用CSS模块
composes关键词和@extend使用方法类似,但工作方式是不同的。看个例子
.common { /* font-sizes, padding, border-radius */ }
.normal { composes: common; /* blue color, light blue background */ }
.error { composes: common; /* red color, light red background */ }
在浏览器中将会被编译为
.components_submit_button__common__abc5436 { /* font-sizes, padding, border-radius */ }
.components_submit_button__normal__def6547 { /* blue color, light blue background */ }
.components_submit_button__error__1638bcd { /* red color, light red background */ }
在js代码中,import styles from "./submit-button.css"将得到
styles: {
common: "components_submit_button__common__abc5436",
normal: "components_submit_button__common__abc5436 components_submit_button__normal__def6547", error: "components_submit_button__common__abc5436 components_submit_button__error__1638bcd"
}
还是使用styles.normal或stryles.error,在DOM中将被渲染为多个类名
这就是composes的功能,你可以合并多个样式,但不用去修改你的JS代码,也不会重写你的CSS选择器。
第3步.文件间共享代码
使用SASS或LESS工作,通过@import来引用同一个工作空间的文件。你可以声明变量,函数,并在其它文件中使用。很不错的方法,但在各个不同的项目中,变量命名有可能冲突。那么你就得重构你的代码,编写如variables.scss和settings.scss,你也不清楚哪些组件依赖于哪些个变量了。你的settings文件会变得很大。
也有更好的解决方案(《使用Webpack构建更小巧的CSS》),但由于SASS的全局属性,还是有很大的限制。
CSS模块一次只运行一个单独的文件,因此不会污染全局作用域。js代码用使用import或require来引用依赖,CSS模块使用compose从另一个文件引用样式。
/* colors.css */
.primary { color: #720; }
.secondary { color: #777; }/* other helper classes... */
/* submit-button.css */
.common { /* font-sizes, padding, border-radius */ }
.normal { composes: common; composes: primary from "../shared/colors.css"; }
使用组件,我们可以像引用本地类名一样,引用colors.css文件的类。而且,组件变化的类名在输出时会被改变,但CSS文件本身并不变化,composes块也会在生成浏览器端CSS之前被去除。
/* colors.css */
.shared_colors__primary__fca929 { color: #720; }
.shared_colors__secondary__acf292 { color: #777; }
/* submit-button.css */
.components_submit_button__common__abc5436 { /* font-sizes, padding, border-radius */ }
.components_submit_button__normal__def6547 {}
实际上,在浏览器端,normal没有自身的样式。这是好事情,你可以添加新的语义化的对象,但不用去添加CSS样式。我们还可以做得更多一点,
在全站开发中增加类名和视觉的一致性,在浏览器端减少样式代码的大小。
旁注:可以使用csso检测并移除空类。
第4步:单一职责模块
组件的强大之处在于描述一个元素是什么,而不修饰它的样式。它以一种不同的方式来映射页面实体(元素)和样式实体(样式规则)。
看一个旧的CSS例子
.some_element { font-size: 1.5rem; color: rgba(0,0,0,0); padding: 0.5rem; box-shadow: 0 0 4px -2px; }
一个元素,一些样式,很简单。尽管这样,还是存在一些问题:color,font-size,box-shadow,padding,这些都在这里指定了,但无法在其它地方使用。
我们用SASS重构一下。
$large-font-size: 1.5rem;
$dark-text: rgba(0,0,0,0);
$padding-normal: 0.5rem;
@mixin subtle-shadow { box-shadow: 0 0 4px -2px; }
.some_element {
@include subtle-shadow;
font-size: $large-font-size;
color: $dark-text;
padding: $padding-normal;
}
比旧的CSS样式有很大的改进,我们只是定义了很少的一部分。事实上像$large-font-size是排版,$padding-normal是布局,这些都仅仅用名字表达含义,不会在任何地方运行。如果要声明一个box-shadow变量,但它并不能表达自身含义,这时就必须使用@mixin或@extend了。
使用CSS模块
通过使用组件,我们可以在组件中,注释写明哪些可以重复使用的类名。
.element {
composes: large from "./typography.css";
composes: dark-text from "./colors.css";
composes: padding-all-medium from "./layout.css";
composes: subtle-shadow from "./effect.css";
}
使用文件系统,而不是命名空间,来划分不同用途的样式。自然会出现引用多个单一用途的文件。
如果你想从一个文件中引用多个类,这里有一个简便的方法:
/* this short hand: */
.element {
composes: padding-large margin-small from "./layout.css";
}
/* is equivalent to: */
.element {
composes: padding-large from "./layout.css";
composes: margin-small from "./layout.css";
}
使你在网站开发上,每一种视觉对应一个类名。用上面的方式,来开发你的网站,变为一种可能。
.article {
composes: flex vertical centered from "./layout.css";
}
.masthead {
composes: serif bold 48pt centered from "./typography.css";
composes: paragraph-margin-below from "./layout.css";
}
.body {
composes: max720 paragraph-margin-below from "layout.css";
composes: sans light paragraph-line-height from "./typography.css";
}
这是一种我有兴趣进一步探索的技术。在我看来,它结合了像Tachyons的原子CSS技术,像Semantic UI样式类名的可读性,单一职责等优势。
但CSS模块的故事才刚刚开始,希望你能去在现在或将来使用它,并传播它。
上手
通过使用CSS模块,希望能帮助你和你的团队,即可以交流当前的CSS知识和产品,又可以更舒服,更高效地完成工作。我们已经尽可能保持语法的简单,并写了一些例子,当你可以使用这些例子里的代码时,你就可以使用它进行工作了。这里有一些关于Webpack,JSPM和Browseriry项目的DEMO,希望对你有所帮助。我们一直看有哪些新的环境可以运行CSS模块:正在适配服务器端NODEJS和Rails。
为了使事情更简单,这里做了一个Plunkr,可以直接动手,不用安装。开始吧
如果你准备使用了,可以看一看CSS模块源码,如果有什么问题,可以在issue里进行讨论。CSS模块组,规模小,无法涵盖所有的应用场景。
期待你们的讨论。
祝:写样式开心。

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

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

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

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

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

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

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

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


핫 AI 도구

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

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

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

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

인기 기사

뜨거운 도구

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

SublimeText3 영어 버전
권장 사항: Win 버전, 코드 프롬프트 지원!

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