作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
当你建立较小的网站时,如何组织你的风格通常不是一个大问题. 您创建了常用的文件,编写了所有需要的CSS,这就是全部. 然而,当涉及到更大、更复杂的项目时,如何组织代码就变得非常重要 crucial. 如果您在一个由多个前端和后端开发人员组成的团队中工作,那么代码的结构就更加重要了.
Today, 有很多方法的目的是减少CSS代码,使您的CSS代码更易于维护. 在本文中,我将解释并提供其中一个的几个例子: BEM. BEM代表 Block Element Modifier. 它背后的主要想法是加快开发过程, 并通过将CSS类安排到独立的模块中来简化开发人员的团队工作. 如果你见过这样的类名 header__form——搜索
,这就是BEM的实际应用. 是的,类的命名可以很长,但它们都是可读和可理解的.
注意,最佳实践是只对类使用BEM, 而不是id,因为类允许您在必要时重复名称并创建更一致的编码结构. Also, 如果你想把你的网站分成有组织的模块, 它应该由相同的结构组成:block, element, 和修饰符. 每个块可以有多个元素,并且块和元素都可以有多个修饰符. 但是,让我们首先从基本BEM结构开始,并通过示例来解释它.
块表示网站中的一个对象. 把它想象成更大的代码结构块. 如今每个网站上最常见的块是标题、内容、侧边栏、页脚和搜索. BEM中的块总是链接CSS类的起点. 让我们来看几个block的例子:
.content{/*样式*/}
.菜单{/*样式*/}
.搜索{/*样式*/}
元素是块中执行特定功能的组件. 它应该只在其块的上下文中有意义:
.content__article{/*样式*/}
.menu__item{/*样式*/}
.search__input{/*样式*/}
修饰符是我们如何表示块的变化. 如果你曾经使用过Bootstrap,那么最好的例子就是按钮大小. 按钮大小只是按钮本身的大小变化,这使得它成为修饰符:
.content__article——featured {/*样式*/}
.menu__item——link{/*样式*/}
.search__input——icon{/*样式*/}
BEM方法的主要目的是使CSS选择器的名称尽可能具有信息性和透明性. 原始BEM样式是这样定义的:
Block 名字通常是一个单字 .header
,但如果有较长的块定义,则用单个连字符分隔 -
:
.lang-switcher{/*样式*/}
Element 名称以双下划线开头 __
:
.lang-switcher__flag{/*样式*/}
Modifier 名称以单个下划线开头 _
:
.lang-switcher__flag_basic{/*样式*/}
BEM方法中只有一条非常关键的规则——修饰符不能在其所有者的上下文中使用.
Example:
.btn_big{/*样式*/}
你可以用 btn_big
仅当header也被定义时.
不好的例子:
...
很好的例子:
...
除了这些原始的BEM风格, 还有其他的命名方案,比如Harry Roberts和CamelCase.
哈里·罗伯茨风格的例子:
.block-name__element-name——modifier-name{/*样式*/}
CamelCase风格的例子:
.BlockName__ElementName_ModifierName{/*样式*/}
还有一些其他的,但这两个是最常见的. 就我个人而言, 我是哈里斯·罗伯茨提出的命名惯例的粉丝, 它有以下规则:
-
__
--
这种命名约定之所以比其他命名约定好得多,是因为您可以轻松地将修饰符元素与其他元素区分开来. 在最初的命名约定中,修饰符是这样定义的:
.block__element_modifier{/*样式*/}
但是正如您所看到的,单下划线和双下划线之间没有太大的区别. 另一方面,双连字符提供了清晰的分隔,你可以立即看到修饰语:
.block__element——修饰符{/*样式*/}
请注意,除了CSS, BEM在组织JSON时也非常有用, XML, 树文件, 或者任何支持嵌套的格式. 将BEM方法视为构建UI的好方法.
让我们考虑以下以BEM格式结构的HTML:
使用JSON和XML格式也可以实现相同的功能.
XML:
JSON:
{
布洛克:“头”,
内容:(
{block: ' logo '},
{
布洛克:检索表单,
内容:(
{block: ' input '},
{block: ' button '}
]
},
{block: ' lang-switcher '}
]
}
在BEM中,以正确的方式组织文件至关重要. BEM不仅为您提供了一个很好的CSS类组织,并使它们完全可以理解, 还提供了一个非常可维护的文件结构. 让我们以一个项目为例,在SASS文件中使用BEM文件组织技术:
blocks/
input/
__box/
--big/
input__box——大.scss
input__box.scss
button/
--big/
按钮,大.scss
正如你在上面看到的, 只需查看主文件夹中的子文件夹结构即可, 一切都清晰有序. 以这种方式, 谁在你后面工作,或者你在别人后面工作,都没有区别, 因为遵循同样的模式是非常容易的.
除了使用BEM方法技术组织文件之外, 你也可以研究更具体的东西. 例如, 如果你正在构建一个web项目,这将是完全响应, 并且客户指定移动设备上的一些块与桌面设备上的完全不同, 最好将BEM文件夹结构划分为不同的平台. 在各种平台上组织按钮的示例:
common.blocks/
button/
button.scss
desktop.blocks/
button/
buttons.scss
mobile.blocks/
button/
button.scss
请注意,如果您希望使用BEM方法组织整个项目,这只是一个示例. 具有BEM结构的文件树不是正确使用BEM所必需的, 您可以在项目的某些部分使用BEM. 到目前为止,我还没有使用这种严格的BEM文件结构组织,其中每个元素和修饰符都创建了自己的文件. Instead, 我只是创建一个文件结构的块,它有一个声明的元素和修饰符.
既然您现在已经熟悉了命名约定,我将在实践中演示BEM方法. 假设我们有这样的HTML代码:
$3.99
Product
使用以下CSS标记:
.btn__price{/*样式*/}
.btn__text{/*样式*/}
.btn——big{/*样式*/}
.btn——primary-color{/*样式*/}
现在,不要被误导. 在我们目前的例子中,我们几乎总是有一个block, element, 和修饰符, 事实并非总是如此.
例如,我们有一个block person. 一个人有腿和手,也可以是女性或男性. 如果我们想要定义一个有右手的男性是这样的:
.person——male——right {/*样式*/}
现在你可以看到边界元的真正含义了. 我们定义了一个人,修饰语是性别. 因为不管一个人是男是女,他都有一只手,而手是一个元素. 同样,每个人都可以有右手或左手这也是一个修饰语.
在另一种情况下,如果我们想定义一般人只有一只手,我们会这样做:
.person__hand{/*样式*/}
大家可以看到, 一旦熟悉了BEM,用它来构建CSS和HTML结构就很容易了.
就我个人而言,我无法想象在不使用CSS预处理器的情况下启动任何新项目. 大家都知道, 预处理器是一个伟大的东西,它们为我们提供了很多好处, 最重要的是,它们与BEM方法完美匹配.
在下面的示例中,您可以看到BEM与SASS结合使用的最典型示例:
.person {
&__hand{/*样式*/}
&__leg{/*样式*/}
&--male {
/*样式*/
&__hand {
/*样式*/
&——left{/*样式*/}
&——右{/*样式*/}
}
&__leg {
/*样式*/
&——left{/*样式*/}
&——右{/*样式*/}
}
}
&——女性{
/*样式*/
&__hand {
/*样式*/
&——left{/*样式*/}
&——右{/*样式*/}
}
&__leg {
/*样式*/
&——left{/*样式*/}
&——右{/*样式*/}
}
}
}
SASS代码将编译成以下CSS:
.person__hand{/*样式*/}
.person__leg{/*样式*/}
.person—male {/*样式*/}
.person—male__hand{/*样式*/}
.person——male__hand——left {/*样式*/}
.person——male——right {/*样式*/}
.person—male__leg{/*样式*/}
.person——male__leg——left {/*样式*/}
.person——male__leg——right {/*样式*/}
.person—female {/*样式*/}
.person——female__hand{/*样式*/}
.person——female__hand——left {/*样式*/}
.person——female__hand——right {/*样式*/}
.person——female__leg{/*样式*/}
.person——female__leg——left {/*样式*/}
.person——female__leg——right {/*样式*/}
如果你想更进一步,你可以为BEM使用一个方便的SASS mixins:
///块元素
/// @param {String} $element -元素名称
@mixin element($element) {
&__ #{$元素}{
@content;
}
}
///块修饰符
/// @param {String} $modifier -修饰符的名称
@mixin modifier($modifier) {
&——#{$修饰符}{
@content;
}
}
你可以这样使用它:
.person {
@include element('hand') {/*人手*/}
@include element('leg'){/*人的腿*/}
@include modifier('male') {
/*男性*/
@include element('hand') {
/*人男手*/
@include modifier('left') {
/*男性左手*/
}
@include modifier('right') {
/*男性右手*/
}
}
}
}
这将产生以下CSS输出:
.person__hand {
/*人手*/
}
.person__leg {
/*人腿*/
}
.人——男性{
/*男性*/
}
.人——male__hand {
/*人男手*/
}
.人——male__hand离开{
/*男性左手*/
}
.人——male__hand对{
/*男性右手*/
}
我知道您很可能不会有这么长的用例, 但这是一个很好的例子,说明了BEM是如何使用的,以及为什么它如此强大, 无论是在小型还是大型项目中.
正如在 BEM官方文档,启动自己的新BEM项目的最简单方法是使用现有的 GIT存储库. 只需使用Git clone命令:
$ git clone http://github.com/bem/project-stub.git
接下来,进入新创建的目录并安装所有依赖项:
$ NPM install
将安装所有必需的依赖项:
使用以下命令构建项目 ENB:
node_modules美元/.bin / enb使
运行服务器模式进行开发:
node_modules美元/.bin / enb服务器
结果,出现以下消息:
服务器从0开始.0.0.0:8080
现在,这意味着服务器已经启动并运行. 您现在可以在此地址查看结果:
http://localhost:8080/desktop.包/索引/索引.html
正如您所看到的,已经创建了许多在内部定义的元素 bemjson
文件,位于这里:
project-stub /桌面.包/索引/索引.bemjson.js
您可以查看并探索生成所有HTML的文件的当前结构, 在本地主机上看到的 index.html
file. 我们将修改该文件以获得我们在前一章中解释过的“Person”BEM项目. 您可以删除(或注释)整个代码 index.bemjson.js
文件,并将其替换为以下文件:
module.出口= {
布洛克:“页面”,
标题:“Person BEM”,
Favicon: '/ Favicon.ico',
head : [
{元素:'meta',属性:{name: 'description',内容:"}},
{元素:'meta',属性:{name: 'viewport',内容:'width=device-width, initial-scale=1'}},
{元素:'css', url: '索引'.min.css' }
],
脚本:[{elem: 'js', url: 'index . '.min.js' }],
内容:(
{
布洛克:“人”,
内容:(
{
elem:“男”,
内容:(
{
elem:“腿”,
mod: {side: 'left'},
内容:“男性腿——左”
},
{
elem:“腿”,
mod: {side: 'right'},
内容:“男性腿——右”
},
{
elem:“手”,
mod: {side: 'left'},
内容:“男性左手”
},
{
elem:“手”,
mod: {side: 'right'},
内容:“男性右手”
}
]
},
{
elem:“女性”,
内容:(
{
elem:“腿”,
mod: {side: 'left'},
内容:“女性人腿——左”
},
{
elem:“腿”,
mod: {side: 'right'},
内容:“女性腿——右”
},
{
elem:“手”,
mod: {side: 'left'},
内容:“女性左手”
},
{
elem:“手”,
mod: {side: 'right'},
内容:“女性右手”
}
]
},
]
}
]
};
现在,将生成以下HTML:
男性的腿——左边
男性的腿——右
男性的手——左边
男性的手——右
女性的腿——左边
女性的腿——右
女性左手——左
女性的手——右
从上面的代码中可以看到, 在这个场景中使用了默认的BEM编码方案,因为我们只是使用BEM提供给我们的默认设置. 还有很多命令和选项可供您探索和使用, 比如创建新页面, blocks, 或修改BEM HTML. 我就不深究了,大家都可以在 BEM官方文档.
通过不在Sass中将类“捆绑”在一起,您可以在视图中创建更多的组合. HTML的书面记录要好得多,因为您可以看到每个类都作用于一块DOM. 你的CSS保持得更简洁,因为你不需要每次创建一个新的UI时都创建新的占位符类(或者组合它们的manifest类).
当我第一次看到BEM编码方案时,我的第一个想法是:
这些类太长,无法编写和读取.
但是在尝试之后,现在我无法想象不使用它就开始一个新项目. For me, BEM极大地提高了我的代码可维护性, 我可以肯定地说,每个被“扔”到基于bem的项目中的开发人员都将很快赶上整个代码结构.
尽管如此,社交网络上仍有很多关于BEM的讨论. 有人说BEM不好, 想知道为什么他们要写这么长的名字类,而不是使用默认的HTML嵌套元素. Well, 没人说你一定要喜欢BEM, 但事实是,大多数前端开发人员都接受它,并发现它非常有用.
Tomislav是一位精通前端技术的软件工程师, 特别是在JavaScript和React中.js.
世界级的文章,每周发一次.
世界级的文章,每周发一次.