從源碼上分析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來作響應式
相關文章
相關標籤/搜索