美文网首页
对Bootstrap 4 CSS组件架构和命名规则的学习

对Bootstrap 4 CSS组件架构和命名规则的学习

作者: microkof | 来源:发表于2017-12-08 11:02 被阅读444次

    一、组件最高类名

    1个单词的类名

    BS4的组件,以组件名单词作为最高的类名,比如警告条,最高的类名是alert,又比如徽章,最高类名就是badge

    也就是说,组件与布局是解耦的,不管你把这个组件用在什么地方,这个组件的基本形态首先就是这个样子,之后你想为项目进行个性化定制,那么你可以给最高层追加定制类。

    2个单词的类名

    下面的btn-toolbar就是两个单词组成最高组件类名,反而子元素的类名有1个单词的btn,这其中的奥妙,就看你怎么看待你的组件了。如果你的组件里面的主要元素是子元素,整个组件就是这些子元素的集合,那么就像btn-toolbar一样就好了,如果是警告条这种肯定是单个使用的组件,那么最高类名就用一个单词就OK。

    <div class="btn-toolbar mb-3" role="toolbar" aria-label="Toolbar with button groups">
      <div class="btn-group mr-2" role="group" aria-label="First group">
        <button type="button" class="btn btn-secondary">1</button>
        <button type="button" class="btn btn-secondary">2</button>
        <button type="button" class="btn btn-secondary">3</button>
        <button type="button" class="btn btn-secondary">4</button>
      </div>
      <div class="input-group">
        <span class="input-group-addon" id="btnGroupAddon">@</span>
        <input type="text" class="form-control" placeholder="Input group example" aria-label="Input group example" aria-describedby="btnGroupAddon">
      </div>
    </div>
    

    二、对最高层的外观附加类、功能附加类、工具类

    外观附加类

    比如警告条,BS4的做法是,最高层除了alert,还会紧跟着一个alert-primary或者其他类,也就是对alert进行外观定制化,一个基本的alert可以拓展出无数的附加类。这种类的写法是,把主类放前面,附加词放后面,用短横线链接。

    alert-primary强调的是语境,分为了主要的、次要的、危险的、成功的等等这些词,如果还要给一个“可收起的”属性,怎么办?BS4给出的方案是再加一个alert-dismissible,这就是功能附加类。

    再比如,徽章可以这么写<span class="badge badge-pill badge-primary">Primary</span>,有2个附加类,badge-pill表示像胶囊一样的形状,跟后面的语境外观不是一回事,所以要另外摘出来定义。

    再说一个特殊的栗子<button type="button" class="btn btn-outline-primary">Primary</button>,这是包边的按钮,有带色边线,里面是白色背景填充。为什么不写成<button type="button" class="btn btn-outline btn-primary">Primary</button>呢?因为btn-primary主要特征是填充带色的背景,跟包边是冲突的两套东西,所以没办法配合,只能是另外单独定义一套btn-outline-xxx系列。

    还有一个特殊的栗子是active类,它并不是独立的工具类,而是外观附加类,因为它都是用于.btn.active {...}这样的形式,所以没必要写成btn-active了。同理的还有disabled等。

    功能附加类

    在最高层div身上,为了实现不同的目的,可以施加多个类,比如alert-warning负责外观表现,alert-dismissible负责功能(可收起的),还有其他功能的话,可以继续加。

    <div class="alert alert-warning alert-dismissible fade show" role="alert">
      <strong>Holy guacamole!</strong> You should check in on some of those fields below.
      <button type="button" class="close" data-dismiss="alert" aria-label="Close">
        <span aria-hidden="true">&times;</span>
      </button>
    </div>
    

    工具类

    最后我们还可以看到fade show,这是2个工具类,可以对任何元素起作用,效果一致,fade是渐变动效果,show表示当前是显示的状态。如果你能做出跟具体组件无关的通用的工具类,也可以继续追加到后面。

    又如mb-0类,它表示margin-bottom:0;,这个类的意义是什么呢?因为BS的原则是,上下两个模块拉开间距,一律采用margin-bottom,不要写任何的margin-top,原因是间距折叠效应,所以比如一系列<p>,都统一只设置margin-bottom的值就可以了。于是有一个问题就是,最后一个<p>可能不需要margin-bottom,怎么办?给最后的<p>加个mb-0类就好了。

    三、使用者自己对最高层的外观附加类、功能附加类、工具类

    自定义外观附加类

    使用者使用BS4的时候,可以给最高层再加一个外观附加类,比如alert-xxx,这个类的作用应该是,在alertalert-primary基础上,再做外观修改,比如改一改字体大小,改一改行高,等等。这个xxx可以是更高级的概念,比如模块名、页面名,甚至网站名:

    • 如果利用模块名,比如新闻列表,那可以叫alert-newslist,意思是新闻列表里的警告条,就应该是这样子的。
    • 如果利用页面名,比如页面是投票页,那就可以是alert-poll,意思是,用在投票页的警告条就得是我写的这样的长相。
    • 如果利用网站名,比如你这是新浪的页面,可以干脆叫做alert-sina,也就是说,我们新浪的警告条,就应该是这个标准。

    自定义功能附加类

    写到这里的时候还没想出好的例子,先不写了。

    自定义工具类

    也没想出好的栗子,先不写了。

    最终,最高层的类的样子应当是:“主类 外观类 自定义外观类 功能类 自定义功能类 工具类 自定义工具类”这样的顺序,就对了。

    四、上下级类怎么写

    下级专门定义一个类的情况

    从BS4来看,比如警告条,警告条里面有能点击的链接,这样形成了上下级类,BS4的方案是:

    <div class="alert alert-primary" role="alert">
      This is a primary alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.
    </div>
    

    就是说警告条里的链接,它的类的写法就应该是alert-link。前面还是主类,后面加功能名称。

    BS的原则是:能不级联就不级联,尽量只给最顶级标签加各种类,这样方便管理,而且,这些类定义的样式尽量是能继承的样式。所以,BS直接给alert-link设样式,不写成级联形式。这样,alert-link继承了祖先元素的一部分样式,自己又定义了一部分样式,这差不多就够用了,没必要写成.alert .alert-link这样的声明。

    下级不专门定义类的情况

    看一个栗子:

    <div class="alert alert-success" role="alert">
      <h4 class="alert-heading">Well done!</h4>
      <p>Aww yeah, you successfully read this important alert message. This example text is going to run a bit longer so that you can see how spacing within an alert works with this kind of content.</p>
      <hr>
      <p class="mb-0">Whenever you need to, be sure to use margin utilities to keep things nice and tidy.</p>
    </div>
    

    <p>标签没有加任何样式,原因是BS4给全局<p>设置了统一的样式,从实践中,很可能你的组件需要跟全局不一样的行高,怎么办呢?应当定义一个类似于这样一个样式:

    .alert-sina p {
        line-height: 1.8;
    }
    

    这时候问题来了,为什么不给<p>加上alert-p类?因为首先这个类好像BS官方类一样,容易混淆视听,其次,你这个组件的<p>的样式,虽然可能跟全局<p>的样式不一致,但总不至于同一个组件内的<p>与<p>互相样式都不一致吧?所以只要统一给组件内设置一个样式就够了。设置类的原则就是一定要尽量精简,也要尽量降低耦合。

    接上面问题,为什么组件里面的<a>就得加上alert-link呢?因为<p>的用途比<a>窄,<p>除了表示一段话,通常没别的作用,<a>就难讲了,有各种用途,所以<a>不可能统一样式,不可以写成.alert a的样子。

    三层及以上结构

    Card确实是BS4里面比较复杂的一个组件了,我们看一下:

    <div class="card" style="width: 20rem;">
      <img class="card-img-top" src="..." alt="Card image cap">
      <div class="card-body">
        <h4 class="card-title">Card title</h4>
        <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
        <a href="#" class="btn btn-primary">Go somewhere</a>
      </div>
    </div>
    

    主类是card没悬念。

    顶部的图片是card-img-top,为啥有个top呢?因为还有一个类是card-img

    card-body可以看出,如果你的一个组件有上中下三部分,你就可以用-top、-body、-bottom,也可以用-header、-body、-footer。这个元素一般是做容器用,设置简单的样式即可,一般不作为级联样式表的父元素。

    card-titlecard-text单词都是表意的,很好理解不解释。除非为了避免歧义,否则card-title不要写成card-body-title,一共就2个单词连起来就完事。这就好比,你说“她的眼睛是蓝色的”,没有哪个神经病会说“她的脑袋上的眼睛是蓝色的”,因为眼睛只有一对,一定在她的脑袋上,所以不需要特意写出来。

    类名用词的惯例:

    • 一条一条的项目,通常就是-item了;

    • 上中下结构,上面提过,就是用-top-body-bottom,也可以用-header-body-footer

    • 若没有上中下结构,而是分为主体和主体旁边的一些零碎,那么主体可以用-inner,旁边的零碎可以另外设定具体名字。

    • 如果语义是菜单,通常用-menu包裹一系列的-item

    五、3个单词组成的类名

    第3个单词作为修饰词的情况

    看个栗子:

    <div class="btn-group">
      <button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        This dropdown's menu is right-aligned
      </button>
      <div class="dropdown-menu dropdown-menu-right">
        <button class="dropdown-item" type="button">Action</button>
        <button class="dropdown-item" type="button">Another action</button>
        <button class="dropdown-item" type="button">Something else here</button>
      </div>
    </div>
    

    dropdown-menu-right是3个单词的类名,第三个单词right是修饰词。这跟BEM命名法是一致的。

    3个单词连起来才描述清楚一个类的情况

    看个栗子:

    <form class="dropdown-menu p-4">
      <div class="form-group">
        <label for="exampleDropdownFormEmail2">Email address</label>
        <input type="email" class="form-control" id="exampleDropdownFormEmail2" placeholder="email@example.com">
      </div>
      <div class="form-group">
        <label for="exampleDropdownFormPassword2">Password</label>
        <input type="password" class="form-control" id="exampleDropdownFormPassword2" placeholder="Password">
      </div>
      <div class="form-check">
        <label class="form-check-label">
          <input type="checkbox" class="form-check-input">
          Remember me
        </label>
      </div>
      <button type="submit" class="btn btn-primary">Sign in</button>
    </form>
    

    form-check-label是3个单词组成的类,它的意思是form中的check容器中的label标签。通常有一个父元素叫form-check

    form-check-input也是3个单词组成的类,它的意思是form中的check容器中的input标签。通常有一个父元素叫form-check

    总结

    • 可以把组件当做一个人体来看。比如眼睛,它虽然属于头部,但你并不用强调眼睛是“头部的眼睛”。虽然不用强调,但是眼睛还是会继承头部的特性,比如头部的海拔高,所以你眼睛的海拔也高。这就算是继承。栗子可能不太恰当,理解意思即可。

    • 如果用sass来写css,不要沉迷于sass的级联写法,因为组件化的特征就是尽量不级联。sass里的级联,最多是2级连一起就够了。所以,请努力让级联扁平起来。

    • 想给一个组件加样式,应当尽量放在最顶级类里,然后多利用CSS的继承,能在最高级类里面定义的,一定要在最高级类里定义,遇到不能继承的,再在下级类里另写样式。

    • <p>这种标签,属于用的场合多,但意义简单,所以,要修改<p>的样式,不要给<p>身上放类,应该用.xxx p {}这种级联形式。反之,<a>就最好在它身上放类。

    • 从dropdown的栗子可以看出,一个组件可以包含其他组件,这是允许的,其他组件的类名不要写成dropdown-xxx-xxx,这样等于你把好容易解耦的样式又耦合起来了,应当直接定义一个xxx-xxx类,然后用.dropdown .xxx-xxx {}来定义样式。

    • 容器名字一般就是header/body/footer这种。

    • 即使是很底层的标签,类名也不要繁复,除非有必要,否则应当尽量短。form-check-input之所以长,是因为它专门用于<input type="checkbox">,实在没办法简写成form-input

    • 注意区分两个概念“模块”和“组件”。模块是什么?比如页面左侧导航,比如新闻列表,比如天气预报模块,等等。组件就好比螺丝,模块就好比各种型号的自行车,螺丝生产的时候有自己的工业标准,并不关心螺丝将来是用在哪个厂家的哪辆自行车上。所以,组件的标签上不要带模块名字,而是应该用级联写法,比如模块是评论框,那么模块最外层的类可以叫comments,它里面有几个组件,任何组件的类名都不要带comments字样。最后,用.comments .xxx {}就搞定了样式。

    • 有时候你会纠结模块的类名,比如评论区,到底类名应该是comment-section还是comment。说白了,如果下级有类名叫comment,那么顶级类名叫comment-section是可以的,如果一个个的comment形成了list的感觉,顶级类也可以叫comment-list,如果下级并没有一个类名叫comment,那么顶级类名就可以直接叫comment,应该是没问题的。所以,一切看情况而定,类名尽量简单。

    附录一:id什么时候用?怎么写?

    锚链接定位

    <a href="#header">跳转到header</a>配合上<a id="header"></a>实现锚链接。

    <label for="...">

    <label for="a"><input id="a" type="checkbox"></label>用于让label操作控件。

    当做JS的操作绑定元素

    比如BS里面有id="btnGroupDrop1"aria-labelledby="btnGroupDrop1"

        <button id="btnGroupDrop1" type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          Dropdown
        </button>
        <div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
          <a class="dropdown-item" href="#">Dropdown link</a>
          <a class="dropdown-item" href="#">Dropdown link</a>
        </div>
    

    由于JS的元素选择器查找id比查找其他的形式要快,所以给被选择的元素加上id是个好习惯。

    另外,最好给id名的前面加上js-,这表示这个元素是一个js钩子。

    当做最大的模块名

    比如你的页面有5个大模块,比如header、footer、main等等的,你除了可以用<header>标签外,也可以用<div id="header">,当然了,这种情况下能不用id就别用,因为id主要不是干这个用的。

    id的写法

    可以有2种,一种是驼峰写法btnGroupAddon2,一种是下划线写法btn_group_addon_2,具体用哪种都可以,真心没有任何区别,所以项目内部统一一种即可。我个人偏向于下划线写法,因为我喜欢给变量名使用驼峰写法,这样的话两种写法在js中就可以一眼区分。

    一般不要用连接线写法,因为容易跟class混淆,而且id名可以直接拿来当js的window对象的属性,也就是window.btn_group_addon_2就指向该元素,但是window.btn-group-addon-2是非法的写法。

    附录二:注释什么时候写?

    业界目前认为最正确的做法,是只给hack做注释,因为你不注释,我真的不好理解你这个hack是干嘛的。其他情况下,应当通过类名就可以让人明白这个类是干什么的。

    相关文章

      网友评论

          本文标题:对Bootstrap 4 CSS组件架构和命名规则的学习

          本文链接:https://www.haomeiwen.com/subject/avldixtx.html