从源码上分析bootstrap的grid system

概述

bootstrap的grid system由3部分组成:css

  • container
  • row
  • columns

container有2种。container: 固定宽度且水平居中; container-fluid: 满屏。
row占满整个container, 一行能够包括12个column。
column有4种类型:lg, md, sm, xs,分别对应着4种设备屏幕大小。html

learn morebootstrap

准备

首先,咱们先用bower来安装bootstrap-sass, 咱们从bootstrap的sass源码来分析。segmentfault

bower install bootstrap-sass --save

grid system主要涉及3个文件。_grid.scss, mixin/_grid.scss, mixin/_gridframework.scsssass

分析

container

css.container {
  @include container-fixed;

  @media (min-width: $screen-sm-min) {
    width: $container-sm;
  }
  // more
}

@include引入了一个mixin:container-fixed, 他设置了margin-leftmargin-right都为auto
而后经过media query来设定不一样的width
这样的话,就可使得.container水平居中了。oop

$screen-sm-min4种设备屏幕大小的breakpoint之一(能够在_variables.scss)找到。ui

$screen-xs: 480px !default; // 手机
$screen-sm: 768px !default; // 平板
$screen-md: 992 !default;  // 桌面计算机
$screen-lg: 1200 !default;

row

css.row {
  @include make-row;
}

@mixin make-row($gutter: $grid-gutter-width) {
  margin-left:  ($gutter / -2);
}

make-row设置了margin-left/right负值,这样就能够把row的width变大。code

Columns

建立column的公共样式

@include make-grid-columns;
@mixin make-grid-columns($i: 1, $list: ".col-xs-#{$i}, .col-sm-#{$i}, .col-md-#{$i}, .col-lg-#{$i}") {
  @for $i from (1 + 1) through $grid-columns {
    $list: "#{$list}, .col-xs-#{$i}, .col-sm-#{$i}, .col-md-#{$i}, .col-lg-#{$i}";
  }
  #{$list} {
    position: relative;
    padding-left:  ($grid-gutter-width / 2);
    padding-right: ($grid-gutter-width / 2);
  }
}

//上面的scss会编译成下面的css:
.col-[xs,sm,md,lg]-[1-9] {
    position: realative;
    padding-left: 15px;
}

#{$i}的做用是把$i字符串转换成变量。dochtm

在for循环中,为何不从1开始呢?
由于$list每次循环后都要加上原来的$list(也就是+=),而且$list的初始值不能为空,因此他的初始值就是1(col-sm-1)。开发

position: relative在这里的做用是什么呢?

在下面,咱们会讲到每一个column都有一个width, 他的值是percentage的。根据doc, 百分比是相对于该元素的containning block.

但我以为他的做用是为了他的children(position: absolute)能够更好的定位。

建立column的float的属性

css// 建立xs columns
@include make-grid(xs);

// 给column设置float属性
@mixin make-grid($class) {
  @include float-grid-columns($class);
}

// 这个跟上面的make-grid-columns差很少
@mixin float-grid-columns($class, $i: 1, $list: ".col-#{$class}-#{$i}") {
  @for $i from (1 + 1) through $grid-columns {
    $list: "#{$list}, .col-#{$class}-#{$i}";
  }
  #{$list} {
    float: left;
  }
}

这里我有个疑问:既然float-grid-columns的做用是让每种column都浮动。那么他为何不写在make-grid-columns里面呢?那里不是都写column的公共样式吗?

建立column的width

@mixin make-grid($class) {
  // 传了个width参数
  @include loop-grid-columns($grid-columns, $class, width);
}

// 起到一个循环的做用
@mixin loop-grid-columns($columns, $class, $type) {
  @for $i from 0 through $columns {
    @include calc-grid-column($i, $class, $type);
  }
}

@mixin calc-grid-column($index, $class, $type) {
  @if ($type == width) and ($index > 0) {
    .col-#{$class}-#{$index} {
      width: percentage(($index / $grid-columns));
    }
  }

当我没设置box-sizing: border-box的时候,12个column不会恰好占满的一行。
由于有padding, margin的存在。

但若是设置以后,margin就属于width了。这样就刚恰好。

这个也是bootstrap grid system可以平均分红12列的缘由。

建立column的push

他会设置column的左边和他的containning block的距离

scss// 若是index不为0,如2。因此left: 2 / 12.
@if ($type == push) and ($index > 0) {
  .col-#{$class}-push-#{$index} {
    left: percentage(($index / $grid-columns));
  }
}
@if ($type == push) and ($index == 0) {
    .col-#{$class}-push-0 {
      left: auto;
    }
}

建立column的offset

这个也会使得column偏移。那他和上面的push有什么不一样呢?

scss@if ($type == offset) {
  .col-#{$class}-offset-#{$index} {
    margin-left: percentage(($index / $grid-columns));
  }
}

由于offset设置的是margin-left,因此他是占据空间的。

html// #column2在这里会挤压到另外一行
<div class="col-lg-2 col-lg-offset-10" id="column1"></div>
<div class="col-lg-4" id="column2"></div>
html// #column2不会被挤压到另外一行
<div class="col-lg-2 col-lg-push-10" id="column1"></div>
<div class="col-lg-4" id="column2"></div>

总结

  • 利用box-sizing: border-box来平均分红12列,
  • 利用sass来迅速开发
  • 利用media query来作响应式
相关文章
相关标签/搜索