CSS命名规范--BEM_bem规范命名样式_咦_我是长颈鹿的博客-程序员秘密

技术标签: 代码规范  

BEM

基于组件方式的web开发方法,基本思想是将用户界面分成独立的模块。

Block(块)

(通常指模块,组件)

Block 是一个逻辑上和功能上独立的页面组件,等同于网页组件中的部件(等同于网页中的组件)。Block 封装了行为(Javascript)、模板、样式(CSS)和其他实现技术。独立状态的 Block 可供复用,并且促进项目开发和维护。

内容

  • 模块名称:描述了它的目的(“它是什么?” —— 菜单或者按钮),而不是它的状态(“它看起来是什么样子?” —— 红色或者大的)。
  • 模块不应该影响它所在的环境,这意味着你不应该为模块设置会影响到外部的形状(影响大小的 padding 或边框)和定位
  • 你也不应该在使用 BEM 的时候使用 CSS 标签选择器和 ID 选择器
  • 名称可以包含拉丁字母、数字、短划线

使用

嵌套关系

  • 模块与模块之间可以彼此嵌套
  • 你可以有任意级别的嵌套层次
    在这里插入图片描述
<!-- 'head' 模块 -->
<header class="header">
    <!-- 嵌套 'logo' 模块 -->
    <div class="logo"></div>

    <!-- 嵌套 'search-form' 模块 -->
    <form class="search-form"></form>

	<!-- 嵌套 'nav' 模块 -->
    <div class="nav"></form>
</header>

###特点
1、嵌套式的构造

Block 可以被嵌套到任何其他 block 里面去。例如,一个头部 block 可以包含一个 logo、一个搜索表单和一个登录 block。

2、随意放置

Block 可以在一个页面内任意移动,也可以在页面之间或项目之间移动。Block 作为独立的实体来实现,这使得在页面上改变 block 的位置 并确保其功能和外观一切正常 成为可能。

3、可复用

一个界面可以包含同一个 block 的几个实例。

Element(元素)

内容

元素(Element)是一个模块(block)的组成部分,且不能脱离模块单独地被使用。例如,一个菜单项(a menu item )不会在一个菜单块(a menu block )范围之外使用,因此它是一个元素(element)。

  • 元素名称:描述了它的目的(用处)(“这是什么?” —— item,text,等等。),而不是它的状态(“什么类型的,或者它看起来是什么样的?” —— 红色,大的,等等。)
  • 完整的元素名的结构是 block-name__element-name。元素的名字与模块的名字使用双下划线分隔(__)
  • 元素名称可以包含拉丁字母、数字、短划线、下划线

使用

1、嵌套关系

  • 元素之间可以彼此嵌套
  • 你可以拥有任意层次的嵌套级别
  • 一个元素总是一个模块的一部分,而不是另一个元素的一部分,这意味着元素的名称不能被定义为 block__elem1__elem2 这样的层次结构。
    在这里插入图片描述
<!--
     正确的。完整的元素名的结构符合如下模式:
     'block-name__element-name'
 -->
<form class="search-form">
    <div class="search-form__content">
        <input class="search-form__input"/>
        <button class="search-form__button"></button>
    </div>
    <div class="search-form__hot">
        <a class="search-form__hot-word"></a>
        <a class="search-form__hot-word"></a>
    </div>
</form>

 <!--
     不正确的。完整的元素名的结构不符合如下模式:
     'block-name__element-name'
 -->
<form class="search-form">
    <div class="search-form__content">
        <!-- 推荐:'search-form__input' 或者 'search-form__content-input' -->
        <input class="search-form__content__input"/>
        <!-- 推荐:'search-form__button' 或者 'search-form__content-button' -->
        <button class="search-form__content__button"></button>
    </div>
</form>

如果在模块名称上定义了命名空间,也要保证元素名称是依赖于模块的(block_elem)。
在 DOM 树中,一个模块可以有元素嵌套结构:

<div class="block">
    <div class="block_elem1">
        <div class="block_elem2">
            <div class="block_elem3"></div>
        </div>
    </div>
</div>

在 BEM 的方法论中,这样的模块结构通常表示为一个并列的元素列表:

.block {
    }
.block_elem1 {
    }
.block_elem2 {
    }
.block_elem3 {
    }

你可以在不改变每个单独的元素的情况下改变一个模块的 DOM 结构:

<div class="block">
    <div class="block_elem1">
        <div class="block_elem1"></div>
    </div>
    <div class="block_elem3"></div>
</div>

2、组成部分
一个元素总是一个模块的一部分,不可以单独使用

<!-- 正确的。元素都位于 'search-form' 模块内 -->
<!-- 'search-form' 模块 -->
<form class="search-form">
    <!-- 在 'search-form' 模块内的 'input' 元素 -->
    <input class="search-form__input" />
    <!-- 在 'search-form' 模块内的 'button' 元素 -->
    <button class="search-form__button"></button>
</form>

<!-- 不正确的。元素位于 'search-form' 模块的上下文之外 -->
<!-- 'search-form' 模块 -->
<form class="search-block">
</form>

<!-- 在 'search-form' 模块内的 'input' 元素 -->
<input class="search-form__input"/>

<!-- 在 'search-form' 模块内的 'button' 元素 -->
<button class="search-form__button"></button>

3、可选性
一个元素是一个可选的模块组件。并不是所有的模块都必须有元素。

<!-- 'search-form' 模块 -->
<div class="search-form">
    <!-- 'input' 模块 -->
    <input class="input"/>

    <!-- 'button' 模块 -->
    <button class="button"></button>
</div>

①如果这段代码可能被重用,并且它不依赖于页面上的其他组件,那你应该创建一个模块。

②如果这段代码在没有父实体(模块)的情况下不能使用,那你应该创建一个元素。

③为了简化开发,元素应该被分割成一小部分-子元素。在 BEM 方法论中,你不能创建元素的元素,在这种情况下,你需要创建一个服务模块,而不是创建一个元素。

Modifier(修饰符)

Modifier 是一个 BEM 实体,它定义了一个 block 或 element 的外观和行为。
Modifier 可用也可不用(即不一定要用到 modifier)。
Modifier 本质上与 HTML 的属性很相似。同一个 block 会因为 modifier 的使用而 看起来与之前有所不同。
例如,菜单块(the menu block )的外观可能会因为在它身上用了一个 modifier 而改变。

内容

一种用于定义模块和元素的外观,状态和行为的实体。

  • 修饰符的名称:描述了它的外观(“多大?”或者“它的主题是什么?”等等—— size-s 或者 theme-islands),它的状态(“它与其他有什么不同?” —— disabledfocused,等等)以及他的行为(“它的行为什么?”或者“它如何响应用户?”——比如 directions-left-top)。
  • 修饰符的名字与模块或者元素的名字使用双连字符(--)
  • 修饰符名称可以包含拉丁字母、数字短划线、下划线

修饰符的类型

1、Boolean

  • 当修饰符的存在或不存在是重要的,与它的值无关时使用这种类型的修饰符。比如:disabled。如果一个布尔类型的修饰符是可见的,它的值被假定为 true。
  • 修饰符的全名的结构遵循如下模式:
  • Modifier(修饰符 )

block-name–modifier-name

block-name__element-name–modifier-name

<!-- 'search-form' 模块有一个 ‘focused’ 的布尔类型的修饰符 -->
<form class="search-form search-form--focused">
    <input class="search-form__input"/>

    <!-- 'button' 元素有一个 'disabled' 的布尔类型修饰符 -->
    <button class="search-form__button search-form__button--disabled">Search</button>
</form>

2、键-值

  • 当修饰符的值是重要的使用键值对类型。

“一个 islands 设计主题的按钮”:menu--theme-islands

  • 这种类型的修饰符的全名的结构遵循如下模式:

block-name–modifier-name-modifier-value

block-name__element-name_modifier-name_modifier-value

<!-- The `search-form` 模块有值为 'islands' 的 `theme` 修饰 -->
<form class="search-form search-form--theme-islands">
    <input class="search-form__input">

    <!-- The `button` 元素有值为 'm' 的 `size` 修饰 -->
    <button class="search-form__button search-form__button--size-m">Search</button>
</form>

<!-- 你不能同时使用两个具有不同值的的相同修饰符 -->
<form class="search-form
             search-form--theme-islands
             search-form--theme-lite">

    <input class="search-form__input">

    <button class="search-form__button
                   search-form__button--size-s
                   search-form__button--size-m">
        Search
    </button>
</form>

使用

一个修饰符不能被单独使用。

  • 从 BEM 的角度,一个修饰符不能脱离模块或元素而被使用。一个修饰符应该改变实体的外观,行为或者状态,而不是替换它。
<!-- 正确的。'search-form' 模块有值为 'islands' 的 'theme' 修饰符 -->
<form class="search-form search-form--theme-islands">
    <input class="search-form__input">

    <button class="search-form__button">Search</button>
</form>

<!-- 不正确的。'search-form' 丢失了 -->
<form class="search-form--theme-islands">
    <input class="search-form__input">

    <button class="search-form__button">Search</button>
</form>

混合模式:一种在单一的 DOM 节点上使用不同 BEM 实体的技术

混合模式允许

  • 结合多个实体的行为和样式,而不是重复编写代码
  • 在现有代码的基础上创建具有新语义的UI组件
<!-- 'header' 模块 -->
<div class="header">
    <!--
        将 'header' 模块的 'search-form' 元素与 'search-form' 模块混合在一起使用
    -->
    <div class="search-form header__search-form"></div>
</div>

在这个例子中,我们将 header 模块的 search-form 元素与 search-form 模块的行为和样式结合在一起。这种方式允许我们在 header__search-form 元素上设置额外的形状和定位,而 search-form 模块仍然是通用的。因此,我们可以在任何环境中使用模块,因为模块没有指定任何填充。这正是我们可以独立调用模块的原因。

文件系统:在 BEM 方法论中采用的组件概念同样适用于项目的文件结构中。模块、元素和修饰符的实现可以被分在独立的文件中,这意味着,我们单独地使用它们。

  • 一个单独的模块对应一个单独的目录
  • 模块和其对应的目录拥有相同的名字。比如, header 模块放置在 header/ 目录中,menu 模块放置在 menu/ 目录中。
  • 一个模块的实现分为单独的文件。比如, header.cssheader.js
  • 模块目录是其元素和修饰所在目录的根目录。
  • 元素目录的名称以双下划线(__)开始。比如,header/__logo/menu/__item
  • 修饰目录的名称以单下划线(_)开始。比如,header_fixedmenu/_theme_islands/
  • 元素和修饰的实现分为不同的文件。比如,header__input.jsheader_theme_islands.css
search-form/                           # Directory of the search-form

    __input/                           # Subdirectory of the search-form__input
        search-form__input.css         # CSS implementation of the
                                       # search-form__input element
        search-form__input.js          # JavaScript implementation of the
                                       # search-form__input element

    __button/                          # Subdirectory of the search-form__button element
        search-form__button.css
        search-form__button.js

    _theme/                            # Subdirectory of the search-form_theme modifier
        search-form_theme_islands.css  # CSS implementation of the search-form block
                                       # that has the theme modifier with the value
                                       # islands
        search-form_theme_lite.css     # CSS implementation of the search-form block
                                       # that has the theme modifier with the value
                                       # lite

search-form.css                        # CSS implementation of the search-form block
search-form.js                         # JavaScript implementation of the
                                       # search-form block

这样的文件结构可以很好地支持我们重用代码。

BEM entity(BEM 实体)

Block,element 和 modifier 合起来就被成为 BEM entity。它是一个 既可以用来指代单独的 BEM 实体又可以作为 block、element 和 modifier 的总称的 概念。

Mix(混合体)

Mix 是被托管在(being hosted on)一个单独的 DOM 节点上的 不同 BEM 实体(混合而成)的一个实例。

Mix允许我们

  • 把几个 BEM 实体的功能(behavior)和样式 组合在一起,同时避免重复代码
  • 在现有的 BEM 实体的基础上 创建语义上的新界面组件。让我们想一下这种 mix 情形:把一个 block 与 另一个 block 的一个 element 组合在一起。

我们假设,项目里的链接(links)通过一个链接块(a link block)来实现。我们需要把菜单项(menu items )格式化成链接(links)。这里有几种实现方法:

  • 创建一个 可以把菜单项(item)转变成链接(link)的 modifier。实现这样一个 modifier 即必然牵涉到 复制链接块的功能和样式。这样一来就会导致代码重复。
  • 取一个 把一个通用的链接块(link block )与一个菜单块的一个链接元素(a link element ) 组合在一起的 mix。两个 BEM 实体的混合体(mix)可以让我们不用复制代码,就可以使用链接块的基本链接功能 和 菜单块的 CSS 规则。

BEM tree(BEM 树 )

BEM tree 是网页结构在 block、element 和 modifier 方面的表示(representation)。这是一个在 DOM 树之上的抽象概念,它描述了 BEM 实体的名称、它们的状态、顺序、嵌套和辅助数据。在现实生活中的项目,BEM tree可以呈现在任何支持树结构的形式(format)中。

一个DOM树

<header class="header">
<img class="logo">
<form class="search-form">
<input type="input">
<button type="button"></button>
</form>
<div class="lang-switcher"></div>
</header>

BEM tree

header
    ├──logo
    └──search-form
        ├──input
        └──button
    └──lang-switcher

在 XML 和 BEMJSON 格式中,该 BEM tree 则是这样的
XML

<block:header>
    <block:logo/>
    <block:search-form>
        <block:input/>
        <block:button/>
    </block:search-form>
    <block:lang-switcher/>
</block:header>

BEMJSON

{
    block: 'header',
    content : [
        { block : 'logo' },
        {
            block : 'search-form',
            content : [
                { block : 'input' },
                { block : 'button' }
            ]
        },
        { block : 'lang-switcher' }
    ]
}

Block implementation(BEM实现 )

Block implementation 是指一组各不相同的 技术,这些技术决定着 BEM 实体以下几方面:

  • 行为/功能(behavior)
  • 外观
  • 测试
  • 模板
  • 文档(documentation)
  • 依赖描述
  • 附加数据(例如:图片)

Implementation technology(实现技术)

Implementation technology 是一种用于实现一个 block 的技术。Block 可以用一种或多种技术来实现,例如:

  • 行为/功能(behavior)-- JavaScript, CoffeeScript
  • 外观-- CSS, Stylus, Sass
  • 模板-- BEMHTML, BH, Jade, Handlebars, XSL
  • 文档(documentation)-- Markdown, Wiki, XML

例如,如果一个 block 的外观是用 CSS 来定义的,这意味着 block 是用 CSS 技术实现的。同样地,如果一个 block 的文档是用 Markdown 格式写的,block 就是用 Markdown 技术来实现的。

Block redefinition(块重定义)

Block implementation 是指通过在不同的层级上增加新的功能到 block 来修改 block。

Redifinition level(重定义等级)

Redefinition level 是指一组 BEM 实体和它们的部分实现。

一个 block 的最终实现 可以被分成 不同的重定义层级。每一个新的层级都会扩展或覆盖原始的 block implementation。最终的结果由 来自所有按照预设的连续的顺序排列的重定义层级的独立的 block implementation technologies 组合而成。
任何 BEM 的实现技术都可以被重新定义。

例如,有一个连接到项目的第三方库。这个库包含现成的 block implementation。该项目指定的 block 保存在一个另一个重定义层级。比方说,我们需要修改这个库里的某一个 block 的外观。这并不需要在库的源代码里修改 block 的 CSS 规则 或者 在项目里复制代码。我们只需在项目里为 那一个 block 创建额外的 CSS 规则。在生成过程中,最终实现将会结合库级别的原有规则和项目级别中新的样式规则。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/love_lovelove/article/details/79462952

智能推荐

一些nginx生产配置示例_Mumunu-的博客-程序员秘密

location 转发设置跨域。用nginx设置简单账密校验。普通location转发。不能配置到http模块下。我比较爱用的日志格式。

windows性能检测器参数项详解_资源检测器参数_jjiss318的博客-程序员秘密

性能测试之内存篇(windows)要监视内存不足的状况,请从以下的对象计数器开始:·    Memory\ Available Bytes·    Memory\ Pages/secAvailable Bytes剩余的可用物理内存,单位是兆字节(参考值:>=10%)。表明进程当前可使用的内存字节数。Pages/sec 表明由于硬件页面错误而从磁盘取出的页面数,或由于页面错误而写入磁

华南理工大学计算机考研资料汇总_华南理工大学计算机专硕考研科目_N诺计算机考研的博客-程序员秘密

华南理工大学计算机科学与工程学院 华南理工大学软件学院华南理工大学(South China University of Technology),简称华南理工,位于广东省广州市,创建于1934年。初复试信息【2022年最新报考信息】计算机相关专业:计算机科学与工程学院(广州大学城校区)软件学院(广州大学城校区)往年学制、学费、奖学金情况学制学费奖学金22华南理工大学计算机相关初试科目:计算机科学与工程学院081200 计算机科学与技术 63本专业所列招生计划包含推免生。含与法国南特大学联培计划5。0854

STM32CubeMX和STM32CubeIDE组合,定义STM32开发新方式_cubemxide_HongAndYi的博客-程序员秘密

在2018年3月份,本人写下了一篇博文《几种STM32开发IDE的比较与选择》,当时ST公司已经收购了Atollic公司,TrueSTUDIO 9.0变成一个免费的STM32开发IDE工具。当时本人就预见TrueSTUDIO +STM32CubeMX必将是ST公司大力推广的开发工具组合。在后面为一门课程备课时,本人也使用了STM32CubeMX+TrueSTUDIO 9.0,发现这套工具非常好用,...

mysql数据库回滚日志_彻底搞懂 MySQL 事务的隔离级别_weixin_39797912的博客-程序员秘密

事前准备数据mysql&gt; create table city( -&gt; id int(10) auto_increment, -&gt; name varchar(30), -&gt; primary key (id) -&gt; )engine=innodb charset=utf8mb4;insert into city(name) values('武汉市')...

度度熊与邪恶大魔王——dp__zhj的博客-程序员秘密

度度熊与邪恶大魔王  Accepts: 2481  Submissions: 15467 Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 32768/32768 K (Java/Others)Problem Description度度熊为了拯救可爱的公主,于是与邪恶大魔王战斗

随便推点

Python os库_辰 的博客-程序员秘密

os库1. os.sep 当前操作系统的目录分隔符2.os.name 获得当前操作系统3.os.linesep 获得行终止符4.os.getcwd(path) 获得当前工作目录5.os.getenv() 获得环境变量6. os.environ 可以获取并修改环境变量7. os.listdir(path) 列出某目录下所有的目录和文件8. os.remove(path) 删除文件9. os.removedirs(path) 递归删除目录10. os.re

servlet web.xml 配置 (未完成待续)_xml参数配置未完成_通幽通明的博客-程序员秘密

URL映射到本地文件在&amp;lt;web-app&amp;gt;&amp;lt;/web-app&amp;gt;添加&amp;lt;web-app&amp;gt; &amp;lt;servlet&amp;gt; &amp;lt;servlet-name&amp;gt;在servlet中起一个名字&amp;lt;/servlet-name&amp;gt; &amp;lt;servlet-class&amp;gt;项目包名.路径.类名&amp;lt;/servlet-

MySQL导入导出数据时遇到Tab符号和换行符号怎么办?_蚂蚁学Python的博客-程序员秘密

在做ETL(下载、转换、导入)开发的时候,经常会遇到从MySQL中导出数据,经过计算后再导入到MySQL的场景。那么有一个很难绕过的问题,如果源MySQL的字段中,包含了\t、\n特殊字符,该怎么办?因为导出文件时,默认是按照\t分割字段、\n分割行,现在字段中出现了\t和\n,这不是乱了吗?同时导入文件时,load data可以指定fields和lines的分隔符,默认情况都是\t和\...

Unity UDP广播 接收端实现_野兽派艺术家!魔界大王橘子!的博客-程序员秘密

public class Lighthouse : MonoBehaviour{ private byte[] data; private string Error_Message; private Thread thread; private EndPoint ep; private bool IsStop = false; private ...

libevent 上传文件_dddddppppp123的博客-程序员秘密

print_log("evhttp_connection_get_bufferevent() ok\n");// Fire off the requestreq = evhttp_request_new(http_post_done, bev);if (req == NULL) {fprintf(stderr, "evhttp_request_new() failed\n"

气动爬行机器人设计_(DᴗD)B的博客-程序员秘密

气动爬行机器人设计简介项目规则简介最近在学校做一个气动的爬行机器人,算是一个二级项目,虽然名义上有分组,但是基本上是我自己在做,觉得有些东西值得记录和分享,所以把一些东西写下来,留作以后参考。项目规则机器人驱动系统为气动控制系统,将采用气源、电源拖线运行方式。气源压力5bar,电源电压24V。手机+蓝牙+单片机控制,实现转向、前进、后退、行走、循迹、运载功能。要求机器人能自动实现循迹(...

推荐文章

热门文章

相关标签