资讯专栏INFORMATION COLUMN

挑逗Bootstrap4源代码 - Grid篇(下)

fobnn / 2356人阅读

摘要:在这里面有一个新定义的类,它这个嵌入式展开后是,从结构可以看出来,它就是加在元素上的,可以取消列的默认间距。在这里我提供一个自定义的,名字也很简单。写的时候注意顺序,要按照升序排列,小的放在上面,即在上面,写反了将失效。

本文所引用的版本为Bootstrap 4 Beta版,阅读者请先下载好相关源文件。

时光荏苒,若后续版本代码发生变化,将看心情进行更新补充。如果你觉得本文不错,欢迎评论支持,如需转载请标明作者及出处,谢谢。

在日常使用Bootstrap的时候,我们最常见的做法是给HTML内的元素添加上预设的类名,这种方法直观且易于调试。但是对于一个前端洁癖患者来说,在HTML标签内添加一大堆类名简直和内联style一样让人深恶痛绝。那么在这种时候,学会使用Bootstrap的Scss,利用其内置的函数和@mixin来对你自己命名的类进行样式添加就成了一件很棒很酷的事。

涉及文件

变量:_variables.scss(起始行:171,结束行:205)

函数:_function.scss //其中函数主要用于变量文件中,在此不述

公共类:_flex.scss //在utilities文件夹下,用于flex布局的各种类,只是给属性加了包装,同样不述

@mixin:

_breakpoints.scss //断点函数区,包括断点区间查找、自动扩展媒体查询等功能

_grid.scss //辅助mixin,提供容器、行、列创建

_grid-framworks.scss //核心mixin,依据断点,循环创建以flex为基础的12网格

引用:_grid.scss //自动创建包括12列网格在内的布局,本质上是对_grid-frameworks和_grid的引用

_grid-frameworks.scss

@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {
  // Common properties for all breakpoints
  %grid-column {
    position: relative;
    width: 100%;
    min-height: 1px; // Prevent columns from collapsing when empty
    padding-right: ($gutter / 2);
    padding-left:  ($gutter / 2);
  }

  @each $breakpoint in map-keys($breakpoints) {
    $infix: breakpoint-infix($breakpoint, $breakpoints);
    @for $i from 1 through $columns {
      .col#{$infix}-#{$i} {
        @extend %grid-column;
      }
    }
    .col#{$infix},
    .col#{$infix}-auto {
      @extend %grid-column;
    }

    @include media-breakpoint-up($breakpoint, $breakpoints) {
      
      .col#{$infix} {
        flex-basis: 0;
        flex-grow: 1;
        max-width: 100%;
      }
      .col#{$infix}-auto {
        flex: 0 0 auto;
        width: auto;
        max-width: none; // Reset earlier grid tiers
      }

      @for $i from 1 through $columns {
        .col#{$infix}-#{$i} {
          @include make-col($i, $columns);
        }
      }

      @for $i from 1 through $columns {
        .order#{$infix}-#{$i} {
          order: $i;
        }
      }
    }
  }
}

整个文件只有一个@mixin make-grid-columns(),这个@mixin才是真正的搭建12列Grid网格系统的核心,让我们细细来拆解。

首先是参数,引入了列数($columns)、列间距($gutter)、断点列表($breakpoints)。这三者都已经预设好了,不需要操心。

%grid-column {
    position: relative;
    width: 100%;
    min-height: 1px; 
    padding-right: ($gutter / 2);
    padding-left:  ($gutter / 2);
}

下面是占位符%grid-column,这个在之前讲make-col-ready()时已经讲过了,出于减小css体积的考虑,占位符在这里显然优于@mixin。那么这里定义的就是一个列的基本属性,而min-height的设置也是考虑到当列为空时不至于坍缩。

@each $breakpoint in map-keys($breakpoints) {}

接下来是一个大循环,这个循环的根本目的在于为不同的断点加上相匹配的类,它的循环依据就是断点名。

$infix: breakpoint-infix($breakpoint, $breakpoints);

让我们以“md”为例进入这个循环,首先是$infix变量,结合先前的知识,我们了解到,这个$infix的值将是”-md”,让我们记住它,接下来,又是一个小循环。

@for $i from 1 through $columns {
   .col#{$infix}-#{$i} {
      @extend %grid-column;
   }
}

这个@for循环的目的,就是为了创建12列的基本属性,因为所有的列都具备%grid-column定义的基本属性,所以我们将这份共性总结出来,多带带设置一个循环进行类名构建,当这个循环结束,你就可以看到css里出现了用逗号相连的col-md-1一直到col-md-12

.col-md-1, .col-md-2, .col-md-3, 
.col-md-4, .col-md-5, .col-md-6, 
.col-md-7, .col-md-8, .col-md-9, 
.col-md-10, .col-md-11, .col-md-12, 
 { position: relative; width: 100%; min-height: 1px; padding-right: 15px; padding-left: 15px; }

它们都有着同样的属性,这也是@extend的好处。但是请注意,我们并没有设置这些列的宽度,所以它们现在还是不可用的状态。

.col#{$infix},
.col#{$infix}-auto {
    @extend %grid-column;
}

接下来有一个多带带的小家伙,通过它,你可以发现.col-md这个类也出现了,也是同样的属性,这个我们就先不去管它了。

@include media-breakpoint-up($breakpoint, $breakpoints) {}

接下拉就是大头了,我们引入了media-brakpoint-up()函数,拿到了media查询的外包装

@media (min-width:768px){}

花括号里就是我们要往这个外包装里塞的内容了。

.col#{$infix} {
    flex-basis: 0;
    flex-grow: 1;
    max-width: 100%;
 }

首先是一个小家伙,又是这货,它多带带给col-md定义了一些flex属性,它的意思表明,当“.col-md”出现的时候,它将撑满整行剩余的空间。

.col#{$infix}-auto {
     flex: 0 0 auto;
     width: auto;
     max-width: none; 
 }

接下来定义了“.col-md-auto”类,这个类挺奇葩,宽度随着内容走,跟列宽毛关系都没有。

@for $i from 1 through $columns {
   .col#{$infix}-#{$i} {
      @include make-col($i, $columns);
   }
}

接下来的@for循环就开始定义我们的列宽了,利用make-col(),我们得到了从col-md-1col-md-12各种不同的列宽。

@for $i from 1 through $columns {
   .order#{$infix}-#{$i} {
      order: $i;
   }
}

最后的这个@for循环也是从1到12遍历一次,熟悉flex的同学会知道,添加的这个order属性就相当于名次,数值越小越靠前,而在flex布局下的12列Grid也正是依靠这一点来对不同的列进行排序的。

至此,“md”下的12列Grid框架构建完成。依次类推,其它的断点列也都是如此生成的。比较特殊的还是断点”xs”,由于先前提到的原因,最小的那一部分是没有前缀的,所以你在css里看到的.col-[1-12]就可以视作.col-xs-[1-12],这需要适应一下。

_grid.scss (根目录)

自动化构建其它诸如”.container”之类的元素,那个$enable-grid-classes布尔值,在变量里的第126行,默认为ture

$enable-grid-classes: true !default;

换句话说,如果你哪天心情不好,不想用bootstrap的网格系统了,直接把这里改成false就行。

@if $enable-grid-classes {
  .row {
    @include make-row();
  }

  .no-gutters {
    margin-right: 0;
    margin-left: 0;

    > .col,
    > [class*="col-"] {
      padding-right: 0;
      padding-left: 0;
    }
  }
}

在这里面有一个新定义的类“.no-gutter”,它这个嵌入式展开后是“.no-gutter>col,.no-gutter>[class*=”col-”]”,从结构可以看出来,它就是加在row元素上的,可以取消列的默认间距。

使用建议

说回我们的Grid,我们知道,如果不加以控制,那么Bootstrap在编译Scss的时候会自动生成所有断点下的列,如果你不打算给每个等级都用上一种布局,那么自动编译的Scss将会产生大量冗余的css代码。

.col-1, .col-2, .col-3,
.col-4, .col-5, .col-6, 
.col-7, .col-8, .col-9, 
.col-10, .col-11, .col-12, 
.col, .col-auto, 
.col-sm-1, .col-sm-2, .col-sm-3, 
.col-sm-4, .col-sm-5, .col-sm-6, 
.col-sm-7, .col-sm-8, .col-sm-9, 
.col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-sm-auto, 
.col-md-1, .col-md-2, .col-md-3, 
.col-md-4, .col-md-5, .col-md-6, 
.col-md-7, .col-md-8, .col-md-9, 
.col-md-10, .col-md-11, .col-md-12, 
.col-md, .col-md-auto, 
.col-lg-1, .col-lg-2, .col-lg-3, 
.col-lg-4, .col-lg-5, .col-lg-6, 
.col-lg-7, .col-lg-8, .col-lg-9, 
.col-lg-10, .col-lg-11, .col-lg-12, 
.col-lg, .col-lg-auto, 
.col-xl-1, .col-xl-2, .col-xl-3, 
.col-xl-4, .col-xl-5, .col-xl-6, 
.col-xl-7, .col-xl-8, .col-xl-9, 
.col-xl-10, .col-xl-11, .col-xl-12, 
.col-xl, .col-xl-auto

比如我只想做桌面端和手机端两种适配,那么我可能只需要lgsm的列,css中其它的列代码对我是没用的。所以面对这种情况,我们就需要对Bootstrap进行修改。这里提供两种化用方式,如果你有其它的主意,也欢迎在评论区留言。

在变量文件中注释掉不需要的列,与之对应的容器等级也不要忘记

$grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  //lg: 992px,
  //xl: 1200px
) !default;
$container-max-widths: (
  sm: 540px,
  md: 720px,
  //lg: 960px,
  //xl: 1140px
) !default;

这是一种很简单的方式,也很直观,我需要什么列就用什么列,不需要的我就给扔掉,但是注意,别扔掉默认值为0的xs。如果你不是前端洁癖患者,只是想缩减css体积,那么推荐用这种方式。

自己新建一个@mixin,替换掉默认的循环创建行为

第一种方式有一个问题,即虽然你注释掉了不需要的列,但仍需要在HTML中写入预设的类名。如果你不希望在HTML中写入一堆以”col-”开头的类名,那么就尝试自己定义一个@mixin,来创建自己的列吧。
创建之前注意,在bootstrap-grid.scss中将@import “grid”注释掉,咱们不需要自动创建。

其次,新建一个scss文件,引入bootstrap-grid

@import "bootstrap-grid"
%grid-column{
  position: relative;
  width: 100%;
  min-height: 1px;
  padding-left: ($grid-gutter-width/2);
  padding-right: ($grid-gutter-width/2);
}
@mixin make-my-col($breakpoint:null,$size:null,$breakpoints: $grid-breakpoints){
  @extend %grid-column;
  @include media-breakpoint-up($breakpoint,$breakpoints){
    @include make-col($size,$grid-columns);
  }
}

在这里我提供一个自定义的@mixin,名字也很简单make-my-col。包含两个参数,一个是$breakpoint(断点名),一个是$size(列宽)。这个@mixin其实是make-grid-columns()的简化版。

具体原理不用多说了,因为是自用,所以我就没去考虑参数验证的问题。如果你有这方面的需求,要应用到项目中,可以考虑加上参数验证。

调用也很简单,在你需要的类中直接调用即可,传入断点名和列宽,就能创建在对应视宽下的列了。

@import "bootstrap-grid";
.side{
  @include make-my-col(sm,2);
  @include make-my-col(md,6);
}
.content{
  @include make-my-col(sm,10);
  @include make-my-col(md,6);
}

P.S.写的时候注意顺序,要按照升序排列,小的放在上面,即sm在md上面,写反了md将失效。

这种方式同样有一个问题,在小型项目中,这样编译出的css能显著缩减css的体积。但在大型项目中,各种类名交错混杂,利用这种创建单个列的方式,最后生成的css代码不见得比bootstrap预定义的类名更好,所以请规范命名,一些容器元素最好保持固定宽度和固定变化。

Scss显然是利用Bootstrap更高效的方式,根据需求,以上两种方式可任选其一。当然,如果你有其它的利用方式,也可以随心所欲地蹂♂躏Bootstrap~

总结

“好的代码像一首诗”

以前对这句话只觉得莫名高大上,却没有多少感触。而在阅读了Bootstrap用Scss写的源码之后,却是真切地感受到了这一点。打开变量(_variables.scss)文件的时候,带给我的震惊是不可言表的。严谨而有序,体量庞大而层次井然。这些模块如果一个个看下来,相信会获益良多。所以如果你和我一样,是Scss的初学者,那么浏览一下Bootstrap的源码,绝对会爽翻。

Grid应该是Bootstrap的核心区块了,从这里入手虽然比较难,但是方便从根本上了解Bootstrap的运行方式。

总的来说,Beta版本的Bootstrap4相比于Alpha版本已经往前迈了一大步,告别了传统盒模型的布局方式,转身拥抱flexbox,同时删去了很多以前的残余代码,在初期,习惯使用b3的同学可能会觉得不大适应,具体表现是

“哎?我写了这个类咋没反应啊?”

眼下这个时候,官方说明文档都不见得会同步更新,看源代码才是最直接的阅读学习方式。

Grid篇到此结束,谢谢阅读,欢迎指出本文的错漏之处,前端新手上路,请多指教。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/112562.html

相关文章

  • 挑逗Bootstrap4代码 - Grid(上)

    摘要:候补,分别代表两种宽度之间和仅在一种宽度下的情形。这里是一个很重要的变化,大家可以注意到,这里的变成了,这也是主要的改进之一,这个基础构建的变化意味着整个框架在很大程度上都会建立在的基础上滚蛋吧。 本文所引用的版本为Bootstrap 4 Beta版,阅读者请先下载好相关源文件。 时光荏苒,若后续版本代码发生变化,将看心情进行更新补充。如果你觉得本文不错,欢迎评论支持,如需转载请标明...

    wizChen 评论0 收藏0
  • bootstrap4源码阅读体会

    摘要:通过阅读发现了不少知识的盲点和误解,对有了更深入的理解。总结几点印象较深的体会,分享给大家。但是通过阅读源码改变了这种认识模块化很简单灵活,这是其优点,同时也是一个缺点。 欢迎到个人博客参观: 点击这里 bootstrap已经使用了很长时间,但是从来没有好好研究过其设计结构,春节期间闲来无事就阅读了源码。通过阅读发现了不少知识的盲点和误解,对css有了更深入的理解。总结几点印象较深的体...

    incredible 评论0 收藏0
  • bootstrap4.0 css架构

    摘要:原子性的默认变量一般是用来设置默认值,然后根据需求来覆盖的。语义化的变量名,值为直接的属性值。组件文件互不引用。组合有几个入口文件对组件进行按顺序的引入,形成不同的专用,形成完整可用的样式,注意引用顺序。 原子性 sass的默认变量一般是用来设置默认值,然后根据需求来覆盖的。覆盖的方式也很简单,只需要在默认变量之前重新声明下变量即可 存放变量的文件。语义化的变量名,值为直接的属性值。 ...

    solocoder 评论0 收藏0
  • 基于angular4+ng-bootstrap+bootstrap+scss的后台管理系统界面

    摘要:描述在刚才发布的不久,很多人不懂得怎么应用,直到现在也很多人不懂怎么用,于是我在余业时间做了这么一个后台管理系统页面,希望对大家有帮助从我个人的感觉来说,语法很舒服,上手起来也比较快可能是因为我有方面的经验吧,但同这些的思想有所不同,初学者 描述 在angular2刚才发布的不久,很多人不懂得怎么应用,直到现在也很多人不懂怎么用, 于是我在余业时间做了这么一个后台管理系统页面,希望对大...

    spacewander 评论0 收藏0
  • 基于angular4+ng-bootstrap+bootstrap+scss的后台管理系统界面

    摘要:描述在刚才发布的不久,很多人不懂得怎么应用,直到现在也很多人不懂怎么用,于是我在余业时间做了这么一个后台管理系统页面,希望对大家有帮助从我个人的感觉来说,语法很舒服,上手起来也比较快可能是因为我有方面的经验吧,但同这些的思想有所不同,初学者 描述 在angular2刚才发布的不久,很多人不懂得怎么应用,直到现在也很多人不懂怎么用, 于是我在余业时间做了这么一个后台管理系统页面,希望对大...

    Muninn 评论0 收藏0

发表评论

0条评论

fobnn

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<