• 如何组织Html元素与如何进行CSS命名(上)


    最近下决心整理一份对页面元素的组织规则和CSS的命名规则,因为深深感受到如果页面上元素太多,没有规则的命名和组织会让网页的维护性大打折扣。参考了几篇文章并且发散了一下,在这里和大家分享

    BEM(Block Element Modifier)

    本文同时也发表在另一个独立博客 http://qingbob.com/blog/如何组织Html元素与如何进行CSS命名(上)

    如何组织页面上的元素,或者说安排元素之间的关系势必会对css命名产生影响;css命名也是对元素关系的映射。BEM这个方法把元素分为三类,代指 Block , Element , Modifier 。

    举个例子,通常我们会把页面分为header, body, footer部分,可能header部分里面又包括了logo, search, login模块。我们可以把Block理解为一个已经封装好了的组件,比如一个搜索模块(这里说的模块统统指一系列html元素,而非逻辑上的功能代码),它是相对于同级元素比较独立的(也相对于element元素)。

    Element则是block中实现具体功能的部件,比如在搜索模块中最起码需要一个按钮(button),一个输入框(input),它和block的重要区别之一是,它没有block那么独立,一旦离开了上下文环境(比如它所在的block),它失去功能上的意义了。

    这就非常灵活了,因为某一个block可以是它父元素或者其他元素的element,比如我们单独看搜索模块可能是一个独立的block,但是搜索模块通常又是放在页面的header中,那么搜索模块此时又成了header的element,而header又是一个更大的block。

    接下来,BEM作者给出了CSS的具体命名规则希望是

    • 一个block必须有唯一的名字(class),比如
    <u lclass="menu">
      …
    </ul>
    • 而element的命名需要包括它所属的block的名字,并且以分隔符分隔开:
    <ul class="menu">
        <li class="menu__item">…</li>
        <li class="menu__item">…</li>
    </ul>

    当然modifier就更好理解了,比如在一个tab模块中,我们需要突出某个tab,就需要给它添加一个的modifier作用的class,这里的modifier可以使特殊的状态,也可以是特殊的属性。就拿上面那个menu例子来说,我们想增大字体,想标识当前选中的菜单项,就可以添加

    <ul class="menu menu_size_big">
        <li class="menu__item">Index</li>
        <li class="menu__item    menu__item_state_current">Product</li>
    <li class="menu__item">Contact</li> </ul>

    巧合的是,在写这篇文章的同时Smashing Magazine上同时发布了一篇谈BEM现在与将来的文章The Evolution Of The BEM Methodology。主要对BEM过去的里程碑,每个里程碑所得出的一些方法论做了一些总结。比如说谈到BEM的起源其实是为了解决实际项目中css选择器冗长的问题,比如

    .result .albums .album .buy {
            float: left;
         padding:0.4em1em01.6em;
    }
    
    .result .albums .info i {
         font-size:85%;
    }

    有甚者

    .b-foot div div div div div
    {
     background-position:71%;
     background-image: url(../i/foot-5.png);
    }

    .b-foot div div div div div div { background-position:87%; background-image: url(../i/foot-6.png);
    }

    虽然现在看起来很可笑,但我觉得这却是实际中遇见的问题,必须承认我自己有时也陷入这样的怪圈

    这篇文章谈为什么有BEM的来龙去脉更生动一些。有兴趣的同学可以看看。其实BEM是一系列的方法论,甚至还包括文件的命名的文件夹分类规则,XSL templates,甚至整个可供参考的框架。

    因为在这里我只是作为一个组织html元素和css命名的其中一个方法,只做了简明的介绍和总结。

    SMACSS(Scalable and Modular Architecture for CSS)

    这个方法论将css分为5类,分别是

    • Base
    • Layout
    • Module
    • State
    • Theme(忽略这个先)

    下面一一进行介绍

    Base:

    基本(base)规则即那些只使用元素选择器,后代选择等(从不涉及class或者id)的规则,比如

    body, form {
        margin:0;
        padding:0;
    }
    
    a:hover {
        color:#03F;    
    }

    你可以理解为定义一些全局的css样式。通常这种工作也可以交给reset.css或者normalize.css来完成

    Layout Rules:

    这里的布局(Layout)指页面上比较大块的区域,比如header,body, footer。而这里的layout rule也分为两类,一类是通过id定义的,比如

    #header, #article, #footer {
        width:960px;
        margin:auto;
    }

    #article { border: solid #CCC; border-width:1px00;
    }

    还有一类可能是在你用了一些css框架的情况下,比如960.gs

    .container_12 .grid_6,.container_16 .grid_8 {
      width:460px;
    }

    作者建议与layout有关的css规则以l-开头,比如

    .l-fixed#sidebar {
        width:200px;
    }
    Module Rules:

    比如说一些登陆,搜索,文章,这样的元素组合我们就可以称之为module。对于这样一些元素的css命名,作者说就免了前缀,直接用模块名称好了,比如

    .login {
        width:200px;
    }

    作者在这里强调的是,避免使用元素选择器。比如开始我们有这么一段html, 有这么一段样式

    <div class="fld"><span>Folder Name</span></div>
    /* The Folder Module */.fld > span {
        padding-left:20px;
        background: url(icon.png);
    }

    问题是当我们的项目变得庞大,需要增加一个或者更多span标签时

    <div class="fld"><span>Folder Name</span><span>(32 items)</span></div>

    这会就傻×了吧。所以最好是给标签添加上有语义的class名称,比如

    <div class="fld"><span class="fld-name">Folder Name</span><span class="fld-items">(32 items)</span></div>

    还有一种情况,当我们在不同的section中使用了同一个module时,我们可能需要根据module所在的section来重新定义样式,比如

    .pod { 
        width:100%;
    }
    .pod input[type=text]{ 
        width:50%;
    }
    #sidebar .pod input[type=text] { 
        width:100%;
    }

    但这样还是会产生问题,会让css变得没有规则和难以维护,所以作者建议添加一个子模块css(Subclassing Modules),比如这么做

    <div class="pod pod-constrained">...</div><div class="pod pod-callout">...</div>
    .pod { 
        width:100%;
    }
    .pod input[type=text]{ 
        width:50%;
    }
    .pod-constrained input[type=text]{ 
        width:100%;
    }
    .pod-callout { 
        width:200px;
    }
    .pod-callout input[type=text]{ 
        width:180px;
    }
    State Rules

    state 与之前的modifier概念类似,这种类型的class只起一些修饰作用。并且作者建议使用is-开头,比如

    <div id="header"class="is-collapsed">
    <form>
    <div class="msg is-error"> There is an error! </div>
    <label for="searchbox" class="is-hidden">Search</label>
    <input type="search"id="searchbox">
    </form>
    </div>

    要注意它和之前sub-module的区别

    • state规则给layout或者module用都行
    • state规则通常由javascript有关(比如错误,高亮,是否折叠),而sub-module是静态不能随意修改的。只是为了区分模块之间的区别

    在这个方法论的文章中,我觉得最有价值的一篇是谈到css的可访问性的。首先作者给出的两条建议是

    • css不应该依赖DOM树的结构
    • css选择器不宜太深

    假如我们有这么一段css

    #sidebar div {
        border:1px solid #333;
    }
    #sidebar div h3 { margin-top:5px;
    }

    #sidebar div ul { margin-bottom:5px;
    }

    这段css中的div可以看做一个组件,是由h3和ul组成的。如果我们想把这个组件又放在footer中怎么办,看下面这段代码怎么样

    #sidebar div, #footer div {
        border:1px solid #333;
    }

    #sidebar div h3, #footer div h3 { margin-top:5px;
    }

    #sidebar div ul, #footer div ul { margin-bottom:5px;
    }

    代码这么冗余的原因就是因为它与dom联系的太紧密,不如把这层依赖关系去掉,给它加上一个独立的class

    .pod {
        border:1px solid #333;
    }
    .pod > h3 { 
        margin-top:5px;
    }
    .pod > ul {
        margin-bottom:5px;
    }

    我们试图在可维护性,性能,和可读性三者之间保持平衡,虽然css选择器具有一定深度意味着更少的class,但是它增加了可维护性和可读性。除非你压根就不想使用class。

    下一期最后看看高手Nicolas的方法论。并且结合淘宝和人人的css规则看看实际的一些应用情况。

  • 相关阅读:
    深度聚类算法浅谈
    最优运输(Optimal Transfort):从理论到填补的应用
    《Javscript实用教程》目录
    再见,深圳~长沙,我又来啦
    vue中手写table的升降序
    Linux离线安装Python3.6.8
    Python3的threading模块 lock、Rlock的使用
    Python3的multiprocessing多进程-示例
    Python3的multiprocessing多进程-Lock、Rlock进程同步
    Python3的multiprocessing多进程-Queue、Pipe进程间通信
  • 原文地址:https://www.cnblogs.com/hh54188/p/2958617.html
Copyright © 2020-2023  润新知