zoukankan      html  css  js  c++  java
  • BEM,SASS,LESS,bootstrap:如何有效地将这些方法,工具和框架聪明地整合?

    https://medium.com/@andersonorui_/bem-sass-and-bootstrap-9f89dc07d20f

    Bootstrap是一个“HTML,CSS和Javascript的框架,用于开发responsive,mobile first project";

    SASS是一个css扩展预编译工具;

    BEM是一个解决css可维护可扩展的方法原则

    我通常使用LESS,一个原因是Bootstrap本身是Less写的。注意SASS和LESS有一些区别可能会让你感觉很奇怪:

    变量覆盖的原则不同: LESS:后面定义的会覆盖前面的,并且在整个代码中都以后面定义的值为准;SASS则是先定义的会先生效直到遇到重新覆盖定义为止。

    注意这个区别对你使用LESS/SASS来开发bootstrap的定制设计时,比如variable.less/sass文件(也就是所谓bootstrap.theme.less),其位置就很重要了,对于less,则需要你的客制化variable放到后面引入,而对于sass则需要最早引入。

    Cleaning up css classes

    现在已经很少使用photoshop或者illustrator了,几乎所有工作从项目开始时就直接在html/css/js中进行,当然有时可能我会使用sketch3来做一下brainstrom或者创建ui elements。也正因为此,我的代码越来越乱,以至于不得不重构代码。当然这个workflow也是我所喜欢的,因为在项目启动时我们几乎不知道我们打算如何去解决问题,我们无法看到所有的patterns,深思熟虑有些浪费时间,所以我往往喜欢在当项目有一个始终一致的模样时才来做这个工作。这样可能更有效果。

    重构之前我可能有下面的html markup,

    <div id=”social-newsletter”>
        <div class=”container”>
            <header class=”text-center”>
                <h1 class=”bottom top”>Acompanhe as novidades</h1>
            </header>
            <div class=”row”>
                <div class=”social col-xs-6 col-sm-2 col-md-2">
                    <div class=”facebook block”>
                        <div class=”centered”>
                            <a href=”http://www.facebook.com" title=”Facebook”>
                                <span class=”sr-only”>facebook</span>
                                <span class=”fa fa-facebook fa-4x”></span>
                            </a>
                        </div>
                    </div>
               </div>
               <div class=”social col-xs-6 col-sm-2 col-md-2">
                   <div class=”twitter block”>
                       <div class=”centered”>
                           <a href=”http://www.twitter.com" title=”Twitter”>
                               <span class=”sr-only”>twitter</span>
                               <span class=”fa fa-twitter fa-4x”></span>
                           </a>
                       </div>
                   </div>
               </div>
               <div class=”social col-xs-6 col-sm-2 col-md-2">
                   <div class=”youtube block”>
                       <div class=”centered”>
                           <a href=”http://www.youtube.com" title=”YouTube”>
                               <span class=”sr-only”>youtube</span>
                               <span class=”fa fa-youtube fa-4x”></span>
                           </a>
                       </div>
                   </div>
               </div>
               <div class=”social col-xs-6 col-sm-2 col-md-2">
                   <div class=”instagram block”>
                       <div class=”centered”>
                           <a href=”http://www.instagram.com" title=”Instagram”>
                               <span class=”sr-only”>instagram</span>
                               <span class=”fa fa-instagram fa-4x”></span>
                           </a>
                       </div>
                   </div>
               </div>
               <div class=”newsletter col-xs-12 col-sm-4 col-md-4">
                   <form>
                        <div class=”block”>
                            <label class=”centered”>Assine nossa newsletter</label>
                        </div>
                        <input type=”email” placeholder=”Insira seu email” class=”col-xs-12 col-sm-12 col-md-12"></input>
                        <button type=”submit” class=”btn btn-danger col-xs-12 col-sm-12 col-md-12">Cadastrar email <i class=”fa fa-paper-plane fa-2x pull-right”></i></button>
                    </form>
                </div>
            </div>
        </div>
    </div>

    通过以BEM方法论,SASS工具支持,可能优化为下面的样子:

    <div class=”social-links js-social-links”>
        <header class=”social-links—header”>
            <h1>Acompanhe as novidades</h1>
        </header>
        <div class=”social-links—content”>
            <div class=”social-links—link js-social-link”>
                <a class=”link—facebook” href=”http://www.facebook.com" title=”Facebook”>
                    <span class=”sr-only”>facebook</span>
                    <span class=”fa fa-facebook”></span>
                </a>
            </div>
            <div class=”social-links—link js-social-link”>
                <a class=”link—twitter” href=”http://www.twitter.com" title=”Twitter”>
                    <span class=”sr-only”>twitter</span>
                    <span class=”fa fa-twitter”></span>
                </a>
            </div>
            <div class=”social-links—link js-social-link”>
                <a class=”link—youtube” href=”http://youtube.com" title=”YouTube”>
                    <span class=”sr-only”>youtube</span>
                    <span class=”fa fa-youtube”></span>
                </a>
            </div>
            <div class=”social-links—link js-social-link”>
                <a class=”link—instagram” href=”http://www.instagram.com" title=”Instagram”>
                    <span class=”sr-only”>instagram</span>
                    <span class=”fa fa-instagram”></span>
                </a>
            </div>
            <form class=”social-links—newsletter js-newsletter”>
                <label class=”newsletter—label”><span>Assine nossa newsletter</span></label>
                <input class=”newsletter—input” type=”email” placeholder=”Insira seu email”/>
                <button class=”newsletter—submit” type=”submit”><span>Cadastrar email</span></button>
            </form>
        </div>
    </div>

    得到的UI效果是这个样子的:

    为了达成上面的亩i奥--更加可读,可理解和富含语义,我需要理解SASS是如何工作的,以及BEM后面所隐含的概念。

    BEM: Block. Eelement . Modifier

    BEM是block,element,modifier的首字母缩写。它的核心想法是通过遵循一套规则使得everything modular---这样将易于重用易于维护,也更加容易理解和自描述。从BEM网站上,我们摘抄以下:

    “A block is A logically and functionally independent page component, the equivalent of a component in Web Components. A block encapsulates behavior (JavaScript), templates, styles (CSS), and other implementation technologies. Blocks being independent allows for their re-use, as well as facilitating the project development and support process.Blocks can be implemented in one or more technologies, for example:
    • behavior — JavaScript, CoffeeScript
    • appearance — CSS, Stylus, Sass
    • templates — BEMHTML, BH, Jade, Handlebars, XSL
    • documentation — Markdown, Wiki, XML.
    "
    A block can be either simple or compound(containing other blocks),比如下面的例子是一个search form block:
    “An element is a part of a block that performs a certain function. Elements are context-dependent: they only make sense in the context of the block they belong to.”
    例如:一个input field和一个button是构成search block的elements:
    “A modifier is a property of a block or an element that alters its look or behavior.”

    Means of Describing Pages and Templates

    blocks和elements一起构成了page content。除了简单地布放在页面上,他们的安排也非常重要。Blocks(or elements)可能按照一定的顺序一个挨着一个的排列。例如,在一个电商网站上,商品一个个罗列:

    或者比如menu items:

    Blocks也可能被包含在其他的block中,比如,一个Head Block包含了logo,searchbox,authblock,menu block。

    而且,我们的building blocks需要一种使用plain text的方式来描述页面的布局。为了实现这一点,每一个block和element都需要很好的命名。Block names应该在整个项目范围内是唯一的;只有相同的block的不同实例化需要使用完全相同的block类,Element名称必须在所属block范围内唯一,一个element可以被在block范围内被重复使用任意次数。

    希望了解更多,可以直接访问BEM的网站: http://bem.info/method/definitions/

    总结以下,BEM的想法就是要创建一个下面的元素组织架构:

    - block

    - block__element

    - block__element__modifier

    <div class="menu menu_hidden">  <span class="menu__item"></span> </div> <div class="menu menu_theme_morning-forest"> <span class="menu__item"></span></div>

    BEM TREE

    {
      block: 'page',
      content: {
        block: 'head',
        content: [
          { block: 'menu', content: ... },
          {
            elem: 'column',
            content: { block: 'logo' }
          },
          {
            elem: 'column',
            content: [
              {
                block: 'search',
                content: [
                  { elem: 'input' },
                  {
                    elem: 'button',
                    content: 'Search'
                  }
                ]
              }
            ]
          },
          {
            elem: 'column',
            content: {
              block: 'auth',
              content: ...
            }
          }
        ]
      }
    }

    element和block可以互相包含。。。

    一般来说,随着项目的发展,blocks倾向于被添加,被删除或者在页面上被移动。比如,你可能希望调换logo和auth block的位置,或者希望将menu放到search block的下方,为了让这个变更过程更加方便简单,要求blocks必须是independent互相独立的

    所谓independent block是以允许放置在页面中的任何地方的方式来实现的,包括随意地嵌入到其他的block中。

    Independent CSS

    从css角度来看这意味着:一个block(or an element)必须有一个唯一的"name"(a css class);HTML elements必须不能在CSS selectors(.menu td)中使用,因为这些包含html tag的selectors固有地不具有context-free的特性;Cascading selectors for several blocks should be avoided:不要使用层叠特性!

    Naming for independent CSS classes

    一种可能的命名方案是:

    • 一个block的css class name和他的block name是一致的
    • 一个element的css class name由block name+element name组成
    <ul class="menu">
      <li class="menu__item">
        ...
      </li>
      <li class="menu__item">
        ...
      </li>
    </ul>

    很有必要将block name包含在一个element的css class name中,因为这将最小化层叠的可能。同时注意使用一致的seperator(这里使用的是__),这对于允许自动化的工具介入开发流程很有帮助。

    当然你可以使用其他的命名方式,我们推荐的方式是:

    • Block name: block name is a keyword that makes sence what is a block about. A block name may be composed of serveral words seperated with hyphen(我这里推荐是blockname由一个或多个单词直接连接而成): bbbb
    • Block prefix: 一个block name通常有一个prefix来帮助指示block的purpose
      •   b-  :比如b-menu-horiz  有实实在在的apperance;   b-bbbb
      •       i-   :比如i-menu  这是一个抽象的block它自己并没有外观,主要用于实现某种功能而存在,比如它提供了一个功能,被b-menu-horiz block加以使用 i-bbbb
      •       l-   : l-bbbbb  表示一个layout的block
    • Element name: 全名称的element name用于指示这个元素属于那一个block,比如 b-blockname__elementname,b-menu-horiz__item, b-popup__content bbbb_eeee
    • Block modifier: 全名称的modifier block用于指示它属于哪个block, 比如b-block-name_modifier-name_modifier-value, b-link_type_pseudo,b-menu-horiz_type_simple,b-popup_direction_up   bbbb__mmmm
    • Element modifier's name: 全名称用于指示他属于哪一个元素(并且哪一个block),b-block-name__element-name_modifier-name_modifer-value,比如b-menu-horiz__item_state_current  bbbb_eeee__mmmm-vvvv

    Independent templates

    从模版引擎的角度来看,block independence意味着:

    • blocks and elements必须在input data中描述,blocks(or elements)must have unique "names" to make things like "Menu" should be placed here"expressible in our templates;
    • Blocks may appear anywhere in a BEM tree

    Modifiers For Elements And Blocks

    我们如果需要创建一个和已经存在的一个block非常接近的block,但是可能外观稍微有些区别,比如,我们有这样一个任务:

    在footer区域增加一个menu block,使用另外一种layout

    为了避免再开发另外一个block,我们可以使用一个Modifier.

    一个Modifier是一个block或者element的属性,该属性仅仅改变block/element的外观或者行为。一个modifier有一个name和value,多个modifier可以同时使用。

    比如,一个block modifer specifies background color,再比如一个元素的modifier更改look of the "current"item.

    从input data角度来看,在一个BEM tree中,modifier是一个描述block/element的实体属性

    <b:menu m:size="big" m:type="buttons">
      ...
    </b:menu>

    同样地,可以是有那个json来描述

    {
      block: 'menu',
      mods: [
       { size: 'big' },
       { type: 'buttons' }
      ]
    }

    从css角度来看,一个modifier是一个额外的css 类用于修饰block或者element

    <ul class="menu menu__size-big menu__type-buttons">
      ...
    </ul>
    .menu_size_big {
      // CSS code to specify height
    }
    .menu_type_buttons .menu__item {
      // CSS code to change item's look
    }

    同样地,对于element modifier可以以类似的方式来实现,比如current menu item可以这样来实现:

    <b:menu>
      <e:item>Index<e:item>
      <e:item m:state="current">Products</e:item>
      <e:item>Contact<e:item>
    </b:menu>
    {
      block: 'menu',
      content: [
        { elem: 'item', content: 'Index' },
        {
          elem: 'item',
          mods: { 'state' : 'current' },
          content: 'Products'
        },
        { elem: 'item', content: 'Contact' }
      ]
    }
    <div class="menu">
      <ul class="menu__layout">
        <li class="menu__layout-unit">
          <div class="menu__item">Index</div>
        </li>
        <li class="menu__layout-unit">
          <div class="menu__item menu__item_state_current">Products</div>
        </li>
        <li class="menu__layout-unit">
          <div class="menu__item">Contact</div>
        </li>
      </ul>
    </div>
    .menu__item_state_current {
      font-weight: bold;
    }

    Blocks Consistency

    一个website有一个Button block,该block可能包含特定的动态行为,比如当一个block被hover时,要求更改它的appearance.

    manager可能会问:在另外一个page中使用同样的button.

    虽然对于一个block有了css implementation,但是这是不够的。重用一个block也意味着重用它的行为,而该行为使用javascript来描述。

    所以一个block必须知道关于它自己的所有事情。为了实现一个block,我们使用各种技术来描述他的外观和行为---我们称之为multilingualism.

    Multilingualism presentation是一个对block从各个programming languages的角度来描述的方法,该方法能够准确描述清楚该block的view和functionality。

    To have a block present on a page as a UI element, we need to implement it in the following techs:

    • Templates(XSL,TT2,Javascript,etc), which turn block declarations into HTML code;
    • CSS that describe apperance of the block;

    如果一个block有动态的behaviour,我们还需要添加

    • 一个javascript implmentation for the block, 

    everything that constitues a block is a technology, including images.

    http://www.smashingmagazine.com/a-new-front-end-methodology-bem-blocks-reiteration/

    我们先来理解我们想达到的目标并且理解layout的结构:

    然后我们需要定义属于不同context的我们的类了:

    1.首先定义整个context block .social-links

    2.在.social-links里面,创建两个其他的blocks: .social-links--header和.social-links--content

    3.在.social-links--header中只有一个h1,唯一的元素;

    4。在.social-links--content block中,有四个elements(.social-links--link)和一个block(.social-links--newsletter)

    5.在.social-links--newsletter block中,我有3个elements: .newsletter--label,.newsletter--input,.newsletter--button

    或许,严格按照BEM命名规范,我需要使用.social-links--newsletter--label,.social-links--newsletter--input,但是我知道我不会在其他地方使用这个newsletter block,所以就简化为一个短小的class了(实际上这个假设本身应该是有问题的!)

    BEM方法论使得创建一个class是很简单的,你只需要知道context(block level),然后按照规则来套用就可以了。

    Bootstrap

    Bootstrap有很多漂亮的功能,但是我只想演示以下如何在SASS中使用guid class.

    在bootstrap中,我们有下面一些@mixins来创建一个grid系统:

    container-fixed()
    make-row()
    make-xs-column()
    make-xs-column-offset()
    make-xs-column-push()
    make-xs-column-pull()
    make-sm-column-offset()
    make-sm-column-push()
    make-sm-column-pull()
    make-md-column-offset()
    make-md-column-push()
    make-md-column-pull()
    make-lg-column-offset()
    make-lg-column-push()
    make-lg-column-pull()
    clearfix()

    这样我们可以像下面的代码一样来做设计:

    section {
        @include make-row();
        article {
            @include make-xs-column(12);
            @include make-sm-column(7);
            @include make-md-column(8);
        }
        aside {
            @include make-xs-column(12);
            @include make-sm-column(3);
            @include make-md-column(4);
        }
    }

    在不使用BEM方法论之前,我们可能这样书写HTML markup:

    <section class=”row”>
        <article class=”col-xs-12 col-sm-7 col-md-8">
            Article content
        </article>
        <aside class=”col-xs-12 col-sm-3 col-md-4">
            Aside content
        </aside>
    </section>

    而当我们引入BEM以及借用BOOTSTRAP LESS/SASS的代码重构后,这样书写html markup:

    <section>
        <article>
            Article content
        </article>
        <aside>
            Aside content
        </aside>
    </section>

    这样的HTML更加清晰和易于理解。

    SASS

    我们再来看看下面两片代码:

    <div class=”social-links—content”>
        <div class=”social col-xs-6 col-sm-2 col-md-2">
            <div class=”twitter block”>
                <div class=”centered”>
                    <a href=”http://www.twitter.com" title=”Twitter”>
                        <span class=”sr-only”>twitter</span>
                        <span class=”fa fa-twitter fa-4x”></span>
                    </a>
                </div>
            </div>
        </div>
    </div>

    以及去除bootstrap的预定义class后的代码:

    <div class=”social-links—content”>
        <div class=”social-links—link js-social-link”>
            <a class=”link—twitter” href=”http://www.twitter.com" title=”Twitter”>
                <span class=”sr-only”>twitter</span>
                <span class=”fa fa-twitter”></span>
            </a>
        </div>
    </div>

    既然我们的想法是清理html代码,使得其更加易读,我删除了所有的bootstrap grid class,取而代之的是通过@extend,@include直接把grid class插入到css中去:

    .social-links—content {
        @extend .container;
     
        .social-link {
            @include make-xs-column(6);
            @include make-sm-column(2);
        }
    }

    然后,我创建一个@mixin来在垂直方向向中间对齐icons:

    @mixin vertical-align() {
        display: block;
        &:before {
            content: ‘’;
            display: inline-block;
            height: 100%;
            vertical-align: middle;
            margin-right: -0.25em;
        }
        > * {
            display: inline-block;
            vertical-align: middle;
            width: 98%;
        }
    }

    这样我就可以这样更新.social-links--content:

    .social-links—content {
        @extend .container;
     
        .social-link {
            @include make-xs-column(6);
            @include make-sm-column(2);
            a {
                @include vertical-align();
            }
        }
    }

    从而将HTML中的div.block和div.centered删除,也就是从下面的HTML:

    <div class=”social col-xs-6 col-sm-2 col-md-2">
        <div class=”twitter block”>
            <div class=”centered”>
                <a href=”http://www.twitter.com" title=”Twitter”>
                    <span class=”sr-only”>twitter</span>
                    <span class=”fa fa-twitter fa-4x”></span>
                </a>
            </div>
        </div>
    </div>

    变成了下面的BEM风格的代码:

    <div class=”social-links—link js-social-link”>
        <a class=”link—twitter” href=”http://www.twitter.com" title=”Twitter”>
            <span class=”sr-only”>twitter</span>
            <span class=”fa fa-twitter”></span>
        </a>
    </div>

     使用LESS 嵌套feature实现BEM命名方法:

    在css开发中,我们非常喜欢使用nested方式来组织css元素,因为这种方式我们可以清晰地看到元素间的层次关系(尽管严格使用BEM命名方式也可以看出来),但是如果一般性地嵌套,则输出的css为后代选择器,一种可行的方法是使用&特殊字符(SASS中使用

    @at-root #{&}__element
    .btn{
      width: 100px;
      &__icon{   //可以看到icon作为btn block的一个元素
        color: blue;
        &--big{  //可以看到.btn__icon--big作为btn block下面的icon元素的一个modifier
            font-size: 20px; 
        }
      }
      &--primary{ //可以看到.btn--primary作为btn block的modifier
        background-color: blue;    
      }
    }
    上面的LESS代码将按照BEM模式的组织方式生成出来的CSS代码如下:
    .btn{width:100px}
    .btn__icon{color:#00f}
    .btn__icon--big{font-size:20px}
    .btn--primary{background-color:#00f}

    http://www.smashingmagazine.com/2014/07/bem-methodology-for-small-projects/

    http://www.smashingmagazine.com/2013/02/the-history-of-the-bem-methodology/

  • 相关阅读:
    Windows 10下CUDA及cuDNN的安装 —— Pytorch
    Centos7 python3环境搭建 兼容python2.7
    VMware中Linux虚拟机与Windows主机共享文件夹
    基于阿里云服务器的网站搭建 新手教程
    CVE-2017-11882 漏洞分析总结 新手漏洞分析详细教程
    Linux基本命令 和 Regex 正则表达式
    Shell 编程 基础用法
    Perl 编程 基础用法
    Python3 网络通信 网络聊天室 文件传输
    Ant Design of Angular
  • 原文地址:https://www.cnblogs.com/kidsitcn/p/4856617.html
Copyright © 2011-2022 走看看