Less在Bootstrap3中解析过程(详细)

前言

    首先阅读本文之前建议先看一下Bootstrap基础以及Less简介, 不然你不会知道我在云什么.因为最近打算用Bootstrap+Less进行开发,但是Less虽然有一些资料,不过大都是Example类型的,感觉比 较抽象更像是API,在网上又找不到比较好的解说,所以打算自己写点.

    对Bootstrap和Less有兴趣的可以看一下官网(中文):http://www.bootcss.com/http://www.bootcss.com/p/lesscss/.

    正文

    在Github上维护的Bootstrap项目就是基于Less的,而且 作为目前来讲最优秀的前端CSS框架Bootstrap的功底也相当不错.所以直接看Less在Bootstrap中是如何实现的就能比较好的了解了.这 里强调一点就是不管我们怎么看Less,最后是为了写出自己的东西,所以一切都是灵活的.

    从https://github.com/twbs/bootstrap上下载到Bootstrap的源代码,这里面有一个Less文件夹,我们研究的重心就是这里了.现在还缺少一个Less的编译环境,可以用Grunt或者Nodejs,这里我选择一个图形界面软件koala.

    Bootstrap源码包含了预先编译的CSS、JavaScript和图标字体文件,并且还有LESS、JavaScript和文档的源码。具体来说,主要文件组织结构如下:

bootstrap/                
               ├── less/
               ├── js/
               ├── fonts/
               ├── dist/
               │   ├── css/
               │   ├── js/
               │   └── fonts/
               ├── docs-assets/
               ├── examples/
               └── *.html

  less/js/ 和 fonts/ 分别包含了CSS、JS和字体图标的源码。dist/ 目录包含了上面所说的预编译Bootstrap包内的所有文件。docs-assets/examples/ 和所有 *.html 文件是文档的源码文件。除了前面提到的这些文件,还包含package定义文件、许可证文件等。

    我们在页面上使用的时候,其实还是引入的CSS文件,只不过它是通 过.less文件编译过来的,有点类似java文件和class文件.打开Less文件夹,我们发现是好多Less文件和一个mixins文件夹.这里我 们先不研究每个文件的具体内容,我们就以一个典型的组件如何实现的去研究它的过程.这里我选择的是一个导航栏,所以新建一个页面,引入通过Less编译好 的文件,然后逐步上溯CSS样式.

    (1) 在Less文件夹外新建一个index.html文件,内容是标准的Bootstrap空白页即可,然后写上一个简单的导航栏,具体代码可以参照Bootstrap官网上的导航栏.先上代码:

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<! DOCTYPE  html>
< html >
   < head >
     < title >Bootstrap 101 Template</ title >
     < meta  name = "viewport"  content = "width=device-width, initial-scale=1.0" >
     <!-- Bootstrap -->
     < link  rel = "stylesheet"  href = "css/bootstrap.css" >
 
     <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
     <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
     <!--[if lt IE 9]>
         <script src="http://cdn.bootcss.com/html5shiv/3.7.0/html5shiv.min.js"></script>
         <script src="http://cdn.bootcss.com/respond.js/1.3.0/respond.min.js"></script>
     <![endif]-->
   </ head >
   < body >
     < nav  class = "navbar navbar-default"  role = "navigation" >
       <!-- Brand and toggle get grouped for better mobile display -->
       < div  class = "navbar-header" >
         < button  type = "button"  class = "navbar-toggle"  data-toggle = "collapse"  data-target = "#bs-example-navbar-collapse-1" >
           < span  class = "sr-only" >Toggle navigation</ span >
           < span  class = "icon-bar" ></ span >
           < span  class = "icon-bar" ></ span >
           < span  class = "icon-bar" ></ span >
         </ button >
         < a  class = "navbar-brand"  href = "#" >Brand</ a >
       </ div >
 
       <!-- Collect the nav links, forms, and other content for toggling -->
       < div  class = "collapse navbar-collapse"  id = "bs-example-navbar-collapse-1" >
         < ul  class = "nav navbar-nav" >
           < li  class = "active" >< a  href = "#" >Link</ a ></ li >
           < li >< a  href = "#" >Link</ a ></ li >
           < li  class = "dropdown" >
             < a  href = "#"  class = "dropdown-toggle"  data-toggle = "dropdown" >Dropdown < b  class = "caret" ></ b ></ a >
             < ul  class = "dropdown-menu" >
               < li >< a  href = "#" >Action</ a ></ li >
               < li >< a  href = "#" >Another action</ a ></ li >
               < li >< a  href = "#" >Something else here</ a ></ li >
               < li  class = "divider" ></ li >
               < li >< a  href = "#" >Separated link</ a ></ li >
               < li  class = "divider" ></ li >
               < li >< a  href = "#" >One more separated link</ a ></ li >
             </ ul >
           </ li >
         </ ul >
         < form  class = "navbar-form navbar-left"  role = "search" >
           < div  class = "form-group" >
             < input  type = "text"  class = "form-control"  placeholder = "Search" >
           </ div >
           < button  type = "submit"  class = "btn btn-default" >Submit</ button >
         </ form >
       </ div > <!-- /.navbar-collapse -->
     </ nav >    
 
     <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
     < script  src = "http://cdn.bootcss.com/jquery/1.10.2/jquery.min.js" ></ script >
     <!-- Include all compiled plugins (below), or include individual files as needed -->
     < script  src = "http://cdn.bootcss.com/twitter-bootstrap/3.0.3/js/bootstrap.min.js" ></ script >
   </ body >
</ html >

    上面代码看个大概即可,一会还要逐步分析.这里有几点要声 明的,第一就是通过Koala将less/bootstrap.less编译成css/bootstrap.css,就编译这一个文件即可,它是 Bootstrap所有样式的一个入口.然后我们在页面中就要引入这个编译后的CSS文件,通过不要关闭你的Koala它会继续监听这个文件,实时更新. 做好上面这些之后,从Bootstrap官网找一段导航栏NavBar的代码放进入,页面生成的效果如下:

111222_PknY_723632.png

    (2) 分析less的文件组织结构

    可以看到less文件夹内和它里面mixins文件夹内都有许多less文件,mixins是less的功能中的混入,以此命名说明其中的 less大多数功能代码.在Bootstrap中我们要研究的文件是:less文件夹中的bootstrap.less(所有样式的对外接 口),variables.less(存储所有的less变量),以及带有nav或者navbar字样的less文件.目前能想到的和导航栏有关的大概就 是这样,然后开始先看一下Bootstrap.less.

    如果对所有的less的结构和作用不清楚,一定要看一下bootstrap.less,这里面对less文件的一个组织结构基本上可以算作是标准了,我在注释里加了中文解释,下面就是代码:

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// Core variables and mixins(最开始引入所有的变量,以及混入规则,这两个应该是各个less的基础.按照less官网说不需要提前定义,less支持按需加载就是需要的时候它自己去找,不过还是建议先加载进来.)
// 这里mixins.less中内容和bootstrap.less类似,没有实际代码,全是@import引入mixins文件夹的内容.
@import  "variables.less" ;
@import  "mixins.less" ;
 
// Reset and dependencies
// 这 3 个less,第一个是重置基本样式,第二个是针对打印机打印时的样式设置,第三个是图标.也就是说这 3 个也是基础的支撑文件.
@import  "normalize.less" ;
@import  "print.less" ;
@import  "glyphicons.less" ;
 
// Core CSS
// 什么叫core,就是核心的东西,这里面的一些脚手架,栅格,表格,表单,按钮,这些都是基础的样式,也是Bootstrap展示的核心.
@import  "scaffolding.less" ;
@import  "type.less" ;
@import  "code.less" ;
@import  "grid.less" ;
@import  "tables.less" ;
@import  "forms.less" ;
@import  "buttons.less" ;
 
// Components
// 组件就是一些网页常见的组成部分,它们可能在一个网站中频繁出现,所以将它们做成组件的形式方便你拿来就用.比如导航,下拉,分页,提示等等...
@import  "component-animations.less" ;
@import  "dropdowns.less" ;
@import  "button-groups.less" ;
@import  "input-groups.less" ;
@import  "navs.less" ;
@import  "navbar.less" ;
@import  "breadcrumbs.less" ;
@import  "pagination.less" ;
@import  "pager.less" ;
@import  "labels.less" ;
@import  "badges.less" ;
@import  "jumbotron.less" ;
@import  "thumbnails.less" ;
@import  "alerts.less" ;
@import  "progress-bars.less" ;
@import  "media.less" ;
@import  "list-group.less" ;
@import  "panels.less" ;
@import  "responsive-embed.less" ;
@import  "wells.less" ;
@import  "close.less" ;
 
// Components w/ JavaScript
// 一些好的效果需要JS支持,JS又需要对CSS样式进行操作,这些less就是为了支持JS插件的
@import  "modals.less" ;
@import  "tooltip.less" ;
@import  "popovers.less" ;
@import  "carousel.less" ;
 
// Utility classes
// 所谓的Utility就是公用的,有效用的.看utilities可以发现其中定义了浮动清除,显示隐藏等基本几个样式,看起来就像是从mixins.less中提取出来的一样.
@import  "utilities.less" ;
@import  "responsive-utilities.less" ;

    根据bootstrap.less的代码可以清晰的看出其中通过less进行编码的文件结构,一共就是几类东西:变量和规则,全局重定义,基础核心(比如table和form等,在原生基础上进行了扩展),常用组件,支持JS的.

    (3) 在相关的文件中寻找对应

    清楚了文件的组织结构,然后开始从后往前递推,看样式是如何生成的.这时 看之前写好的index.html中代码,导航栏整体被包裹在一个nav标签,它的第一个样式是.navbar,Bootstrap中定义navbar是 导航栏的基础样式.在页面上通过Chrome的F12进行样式查看.最终通过.navbar这个类被应用的样式如下:

?

1
2
3
4
5
6
7
8
9
10
@media ( min-width 768px )
.navbar {
border-radius:  4px ;
}
.navbar {
position relative ;
min-height 50px ;
margin-bottom 20px ;
border 1px  solid  transparent ;
}

    第一个是因为媒体设备判断当前页面宽度,然后添加了border-radius.后面是通过.navbar添加了position和 min-height还有margin-bottom和border.然后通过这些开始寻找navbar的less文件,首先在less文件夹下就有一个 navbar.less,其中定义的第一个样式就是.navbar如下:

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Wrapper and base class
//
// Provide a  static  navbar from which we expand to create full-width,  fixed , and
// other navbar variations.
 
.navbar {
   position relative ;
   min-height : @navbar-height; // Ensure a navbar  always  shows (e.g., without a .navbar-brand in collapsed mode)
   margin-bottom : @navbar-margin- bottom ;
   border 1px  solid  transparent ;
 
   // Prevent floats from breaking the navbar
   &:extend(.clearfix  all );
 
   @media ( min-width : @grid-float-breakpoint) {
     border-radius: @navbar-border-radius;
   }
}

    一点点看这个代码,这个navbar写的并不复杂.首先它不是一个规则,也就是没有传递参数一说,说明它内部使用的变量的值应该都来自于 variables.less文件中的设置.先是定义了position:relative的相对定位,这就与之前页面上的position相对应上了. 然后这里有一个min-height设定,我们在页面上看到的是50px,这里是通过@navbar-height变量的,去 variables.less中找找看是不是这样.

    这里我直接将variables.less文件中的涉及navbar的地方列出来:

?

1
2
3
4
5
6
7
8
9
10
11
// Basics of a navbar
@navbar- height :                     50px ;
@navbar- margin-bottom :             @line-height-computed;
@navbar-border-radius:             @border-radius-base;
@navbar-padding-horizontal:        floor((@grid-gutter-width /  2 ));
@navbar-padding-vertical:          ((@navbar-height - @line-height-computed) /  2 );
@navbar-collapse- max-height :        340px ;
 
@navbar-default- color :              #777 ;
@navbar-default-bg:                 #f8f8f8 ;
@navbar-default- border :            darken(@navbar-default-bg,  6.5% );

    看到了吧,高度在这里设置的是50px.然后我们注意到navbar样式的margin-bottom在这里又引用了@line-height-computed.然后继续索引这个变量找到它的值是这样定义的:

?

1
@line-height-computed:    floor((@font-size-base * @line-height-base));    // ~ 20px

    取字体的基本大小这里定义的是14px然后乘以基本行高定义的是 1.428,如此相当于navbar中的margin-bottom的值就是20px.这个和最终显示的样式是相等的,但是这里我们看到这个值并不是直接 设定的,而是根据字体和行高算出来的,在Bootstrap中很多地方应用到这种那方式,也就是牵一发而动全身.这里没法一一去理清它变量间的关系,但是 从设计的方面我们可以知道,这么做是有好处的,比如字体变大了之后,其它与其配合的地方也会有相应的改变,从而在视觉上形成统一.

    然后还有个border: 1px solid transparent;我们看到这个代码变量和其它的,就是直接写死了1px宽并且透明.然后我对navbar.less全局搜索了border,发现都没有通过变量设置,而是直接设置了宽度.

    这样页面上显示的navbar对应的样式没了,我们接着看navbar.less中的navbar样式,里面有一段继承:

?

1
&:extend(.clearfix  all );

    这个的意思很好理解,&表示父级,也就是让父级.navbar继承.clearfix样式.这里清除浮动的样式是定义在/mixins/clearfix.less中,里面只有这一个规则.

    (4) 寻找规律进行分析

    现在把问题拉回到现实,我们研究Bootstrap中less的过程是为了什么?

    我们的目的是为了写出和Bootstrap一样好的CSS代码,这才是我们的目的.诚然Bootstrap中为我们做好了很多如导航之类的组件,但是总有需要我们自己写的东西,这时候我们完全可以参照Bootstrap中对于组件的写法.

    从头查看一遍navbar.less,它并没有嵌套很多类,基本上都是单独列出来的,以应付更灵活的HTML结构.并且组件定义的很细致,基本上从各个方面都有定义class.当然我们自己写的时候应该不用划分这么细致.

    这时候在仔细思考一下它的实现步骤:

    将可配置的灵活的东西定义为变量在variables.less中 --> 将可能被其他地方用到或者通用的规则定义到mixins中 --> 如果能使用Bootstrap的就尽量使用它自带的组件 --> 如果自己开发就为自己的组件单独一个文件,按照less的写法灵活的定位布局以及设置表现样式. 

    如果只是这么看其实less的写法和单纯CSS没什么太大的分别,只不过更加便捷而且加入了一些逻辑.

    结尾

    在一个大页面上非常小的一个点被应用了什么样式是很繁杂的,我问过很多CSS方面的熟练工,得出的结论就是CSS是一个经验很重要的东西.做得多了才会积累出足够的感觉,所以本文也没办告诉你先写1在写2然后1+2=3这样的步骤.

    只是推荐在写或者说学习的过程中多思考,多练习,然后慢慢优化提升.


转载于:https://my.oschina.net/lee2013/blog/291330

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值