• 技术文章 >web前端 >Bootstrap教程

    浅谈BootStrap实现栅格布局的方法

    青灯夜游青灯夜游2021-06-01 18:22:37转载154
    本篇文章给大家介绍一下BootStrap实现栅格布局的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

    【相关推荐:《bootstrap教程》】

    1. 基本点

    box-sizing: border-box

    这是最基本的一点,将盒子模型设置成边框盒子.这样 width 属性指定的盒子宽度就包括 border + padding + content。只要 width 固定,指定 paddingborder 将不会改变盒子的大小。

    *,
    *::before,
    *::after {
        box-size: border-box;
    }

    知识前置

    本文栅格实现参考 bootstrap 源码实现

    2. Container

    一般来说作为应用最顶层的容器分为两种:

    响应式容器会根据屏幕宽度的不同,根据媒体查询使用 max-width 约束容器的宽度。因为 bootstrap 移动优先的原则,所以是先满足小屏幕的容器样式,然后再根据媒体查询扩展大屏幕的样式。

    container 基本数据


    xs < 576pxsm >= 576pxmd >=768pxlg >=992pxxl >=1200px
    .container100%540px720px960px1140px
    .container-sm100%540px720px960px1140px
    .container-md100%100%720px960px1140px
    .container-lg100%100%100%960px1140px
    .container-xl100%100%100%100%1140px
    .container-fluid100%100%100%100%100%

    断点:

    $grid-breakpoints: (
        xs: 0,
        sm: 576px,
        md: 768px,
        lg: 992px,
        xl: 1200px
    );

    不同断点对应的容器宽度:

    $container-max-widths: (
        sm: 540px, // min-width: 576px
        md: 720px, // min-width: 768px
        lg: 960px, // min-width: 992px
        xl: 1140px // min-width: 1200px
    );

    实际上断点到底取在哪里,可以随意自定义。这里只是引用的 bootstrap 的规范而已。

    2.1 固定容器实现

    固定容器实现很简单。无非就是将容器的宽度设置为 100%, 水平居中而已。

    /**
     * 基本容器的样式
     * 宽度 100%
     * 有半个槽宽的内边距
     * 水平居中
     * @param $gutter 槽宽, 如果只是想要一个普通的容器。可以将参数槽宽设置为 0
     *                默认值是 $gird-gutter-width
     */
    @mixin make-container($gutter: $grid-gutter-width) {
        width: 100%;
        padding-right: $gutter / 2;
        padding-left: $gutter / 2;
        margin-right: auto;
        margin-left: auto;
    }

    槽宽这个概念如果用过 bootstrap 应该能够理解。如果不理解可以跳到本文底部,有详细介绍。

    当屏幕宽度小于 576px 的时候,所有的容器宽度都是 100%。即 xs 的情况下:

    .container,
    .container-sm,
    .container-md,
    .container-lg,
    .container-xl,
    .container-fluid {
        @include make-container();
    }

    2.2 响应式容器实现

    要实现响应式容器,就是要根据不同的断点分别给不同的容器设置媒体查询,以 max-width 约束容器的宽度。

    根据规范所示:

    分析一下,就可以发现。每个断点处需要设置媒体查询的容器数刚好在 .container-#{$breakpoint} 处停止。

    使用 sass 描述如下:

    @each $breakpoint, $container-max-width in $container-max-widths {
        /**
        * .container
        * .container-sm
        * .container-md
        * .container-lg
        * .container-xl
        * 按照断点设置媒体查询
        * 其实就是通过 max-width 控制容器到底有多宽
        */
        @include media-breakpoint-up($breakpoint, $grid-breakpoints) {
            // 每个断点的屏幕最大 width
            %responsitive-#{$breakpoint} {
                max-width: $container-max-width;
            }
    
            // 用于确定哪些容器需要设置媒体查询的 flag
            $extend-breakpoint: true;
    
            @each $name, $width in $grid-breakpoints {
                @if $extend-breakpoint {
                    .container#{breakpoint-infix($name)} {
                        @extend %responsitive-#{$breakpoint};
                	}
            	}
    
            	@if $name == $breakpoint {
                $extend-breakpoint: false;
            	}
        	}
    
    
    	}
    
    }

    其中两个辅助函数 breakpoint-min, breakpoint-infix:

    /**
     * 根据断点名称取得对应的断点 width.
     * 注意:如果是 xs 断点,返回的是 null
     * @param $name:  传入的 map key
     * @param $breakpoints-map: 断点 map
     * @return: 断点对应的 mind-width
     */
    @function breakpoint-min($name, $breakpoints-map: $grid-breakpoints) {
        $min: map-get($map: $breakpoints-map, $key: $name);
        @return if($min != 0, $min, null);
    }
    
    /**
     * 根据断点名称作为 key 查询map
     * 若是 map 中 key对应的 value 不为 0 则生成后缀名
     * 否则返回空串
     *
     * @param $name:  传入的 map key
     * @param $breakpoints-map: 断点 map
     * @return: 断点对应的后缀名 格式 '-sm'
     */
    @function breakpoint-infix($name, $breakpoints-map: $grid-breakpoints) {
        @return if(breakpoint-min($name) != null, '-#{$name}', '');
    }

    辅助 mixin media-breakpoint-up

    /**
     * 根据 $name 作为 key 查询 $breakpoints-map 中对应的断点值 
     * 如果断点值存在,则对相应内容设置媒体查询
     * 如果断点值不存在,则将混合的内容原样输出
     * 
     * @param $name 断点名称
     * @param $breakpoints-map 保存断点的 map
     */
    @mixin media-breakpoint-up($name, $breakpoints-map: $grid-breakpoints) {
        $min: breakpoint-min($name, $breakpoints-map);
    
        @if $min {
            @media (min-width: $min) {
                @content;
            }
        }@else {
            @content;
        }
    }

    3. Row

    栅格布局主要就是围绕 rowcolumn 展开。行中放置列,列中放置应用内容,列中又可以嵌套行(子子孙孙无穷尽也(x))。

    行其实就是一个固定的容器,所以样式也很简单。

    /**
     * 行基础样式
     * 开启 flex 布局
     * 允许多行容器
     * 左右有半个槽宽的负外边距
     * 
     * @param $gutter 槽宽
     */
    @mixin make-row($gutter: $grid-gutter-width) {
      display: flex;
      flex-wrap: wrap;
      margin-right: -$gutter / 2;
      margin-left: -$gutter / 2;
    }
    // 行
    .row {
        @include make-row();
    }

    4. Column

    column 是栅格布局中最重要的部分,同时也是最复杂的一部分。

    有多种列可供使用:

    如果是在小屏幕下,我们通常不会让一行有很多列,通常一行都只有一列。所以根据不同的屏幕断点,bootstrap 还提供了响应式列。

    语义是,当屏幕大于等于断点对应宽度时,呈现列的语义形式。当小于断点宽度时,所有的列都退化成 width: 100%; 的形式。同样的,这也通过媒体查询实现.

    4.1 列基础样式

    所有列的最基础的样式:

    /**
    * 列基础样式
    * 开启相对定位,作为列中内容绝对定位的参考点
    * width 为 100%
    * 左右有半个槽宽的外边距
    */
    %grid-column {
        position: relative;
        width: 100%;
        padding-left: $gutter / 2;
        padding-right: $gutter / 2;
    }

    这个样式用于当屏幕小于对应断点的时候,列的样式进行退化

    4.2 设置 .col, .col-${i}, .col-auto 的基础样式

    $infix: breakpoint-infix($breakpoint, $breakpoints);
    
    // .col-*-i 系列设置基础样式
    @if $columns > 0 {
        @for $i from 1 through $columns {
            .col#{$infix}-#{$i} {
                @extend %grid-column;
        	}
    	}
    }
    
    // .col-*, -col-*-auto 系列设置列基础样式
    .col#{$infix},
    .col#{$infix}-auto {
        @extend %grid-column;
    }

    我们这里以 $breakpoint: sm 为例,则 $infix: '-sm'。变量 $colums: 12 是默认的一行可以分为多少列.

    执行完之后, .col-sm, .col-sm-#{$i}(i 取值 1-12), .col-sm-auto 它们的默认样式都设置成了 %grid-column。退化的基本样式就设置好了。

    之后就开始设置媒体查询,以确定不同的列的样式。

    因为此时的例子 $breakpoint: sm, 所以接下来的内容都会被编译进 @media(min-width: 576px) 中:

    4.3 列样式设置

    等宽列样式设置

    flex:1 1 0; max-width: 100%。列可以等比例放大等比例缩小。初始行可用空间计算值是整个 main size。(如果不理解,可以去搜索 flex-basis: 0 代表什么含义)。这样的话,无论 .row 下放置多少个 .col-sm,每个 .col-sm 的宽度都是相等的。(前提是列能容纳得了内容)

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

    .row-cols#{$infix}-#{$i}

    这个是 bootstrap 的特色类,这个类应用在 row 上。约束其下最多可以拥有多少个等宽列.这个类对于其他的列是不影响的,仅仅影响等宽列。(是通过选择器优先级实现的)

    // 设置 .row-cols-*-i 系列 的样式
    @if $grid-row-columns > 0 {
        @for $i from 1 through $grid-row-columns {
            .row-cols-sm-#{$i} {
                @include row-cols($i);
        	}
    	}
    
    }

    辅助 mixin row-cols

    /**
     * 设置 .row-col-*-i 系列下的列样式
     * flex: 0 0 100% / $count,即是一个不会放大不会缩小,永远按 i 的值等比例平分行的列
     * 
     * @param $count 要平分的列数
     */
    @mixin row-cols($count) {
        & > * {
            flex: 0 0 100% / $count;
            max-width: 100% / $count;
        }
        
    }

    .row-cols-sm-1 > * 的选择器特殊性和 .col-sm 相同。但是前者声明在后者后面,所以造成了样式覆盖。即 .row-cols#{$infix}-#{$i} 只对等宽列起效。

    严格的说,当使用对应断点的 .row-cols-#{$breakpoint}-#{$i} 之后,会对其下列中 .col-#{$breakpoint} 及断点之前的等宽列生效。即 .row-cols-md-4 会对 .col, .col-sm, .col-md 都生效。原因是因为整个循环顺序是从 xs -> xl。如果不明白,看一下编译输出的 CSS 就知道为什么了。

    可变宽度弹性列样式设置 .col-sm-auto

    // 设置 .col-*-auto 的样式
    .col-sm-auto {
        @include make-col-auto();
    }

    辅助 mixin make-col-auto

    /**
     * 设置 .col-*-auto 的样式
     * 默认情况下是一个不会放大不会缩小,宽度由 flex item 宽度决定的盒子
     */
    @mixin make-col-auto() {
        flex: 0 0 auto;
        width: auto;
        max-width: 100%;
    }

    设置比例列样式 .col-sm-#{$i}

    // 设置 .col-*-i 系列的样式
    @if $columns > 0 {
        @for $i from 1 through $columns {
            .col-sm-#{$i} {
                @include make-col($i, $columns);
        	}
    	}
    }

    辅助 mixin make-col

    /**
     * .col-*-i 的样式
     * 
     * @param $size 占据的列数
     * @param $columns: 总可用列数
     */
    @mixin make-col($size, $columns: $grid-columns) {
        flex: 0 0 percentage($size / $columns);
        max-width: percentage($size / $columns);
    }

    这里就是按比例分配,如果 $i: 5, 则 .col-sm-5 就占据整行宽度的 5/12

    flex 布局中使用 order 属性来视觉排序 flex item.所以 bootstrap 也提供了列排序的类

    // 列排序相关
    .order-sm-first {
        order: -1;
    }
    
    .order-sm-last {
        order: $columns + 1;
    }
    
    // 一行最多12列,也就是说从 -1 开始编号就可以安排完整行所有的列排列顺序
    @for $i from 0 through $columns {
        .order-sm-#{$i} {
            order: $i;
    	}
    }

    只要明白浏览器视觉排序是按照 order 数值从小到大排序就能了解这个是干嘛的了。

    列偏移

    实际需求中,总是会有列偏移的需求,这里是通过 margin-left 实现。

    // 设置列偏移
    @if $columns > 0 {
        @for $i from 0 through ($columns - 1) {
            @if not ($infix == '' and $i == 0) {
                .offset#{$infix}-#{$i} {
                    @include make-col-offset($i, $columns);
            	}
        	}
    	}
    }

    辅助 mixin make-col-offset:

    @mixin make-col-offset($size, $columns: $grid-columns) {
        $num: $size / $columns;
        margin-left: if($num == 0, 0, percentage($num));
    }

    整个创建响应式列的流程就是这样,这里只是举了断点为 sm 的情况,其他断点也是这个流程。就不一一赘述了,实际上实现也是通过循环。如果不需要响应式,只是需要等宽列,可变宽度弹性列,比例列的话就更简单了,我相信如果能理解上面的内容的话以读者的聪明才智可以很容易自己写出来。

    5. 槽

    槽(gutter) 是两列之间的间距。槽的数量是列数量 - 1.

    槽公式:
    设栅格行宽度为 w, 列宽度为 c(这里的列宽指内容区域), 槽宽度为 g, 列数为 n
    则 w = n * c + (n - 1) * g

    bootstarp 的设计是这样的:

    1.png

    6. 完整源码

    完整源码移步 git 仓库(不是 bootstrap 完整版本,是个人重写加了注释的仅具有 grid 功能的版本。内容不多)

    bootstrap-grid地址:https://github.com/IliyaRin/bootstrap-grid

    更多编程相关知识,请访问:编程入门!!

    以上就是浅谈BootStrap实现栅格布局的方法的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:BootStrap 栅格布局
    上一篇:浅谈bootstrapTable如何动态设置行和列的颜色 下一篇:浅谈bootstrap中的navbar导航栏
    第16期线上培训班

    相关文章推荐

    • 浅谈查看bootstrap和jQuery版本对应关系的方法• 3 分钟使用Bootstrap-Table实现满意的表格功能• 深入解析bootstrap-select中的多选和模糊查询下拉框• bootstrapTable如何重新加载数据?3种方式了解一下!• bootstrapValidator如何验证最大值和最小值限制• 浅谈bootstrapTable如何动态设置行和列的颜色

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网