美文网首页栅格系统/网格系统
#1 自定义栅格系统&响应式布局

#1 自定义栅格系统&响应式布局

作者: JamesSawyer | 来源:发表于2016-11-13 19:59 被阅读184次

    原文连接

    一.如何构建自己的栅格系统

    1. grid design
    2. how your grid behaves at different viewports
    3. whether to use HTML OR CSS grid systems

    1.building your grid system

    8步建立自己的栅格系统:

    1. 选择一个栅格系统规范: css grid, Flextbox, 还是floats
    2. 设置 box-sizingborder-box
    3. 创建 grid container
    4. 计算 column-width(列宽)
    5. 决定 gutter(间隔) 位置
    6. 创建debug grid
    7. 制作布局差异(make layout variations)
    8. 使布局变得响应式

    二.具体步骤

    对应上面的8条

    1.选择规范

    CSS Grid最好用,但是浏览器的支持太差,选择使用Flexbox或者Floats。 flexbox和floats之间其实差异很小,下面为了通常情况,选择floats来布局。

    2.设置box-sizing

    box-sizing有3种: content-box, padding-box, border-box, 设置为border-box是最常用的, 设置方法如下

    html {
        box-sizing: border-box
    }
    
    *,
    *:before,
    *:after {
        box-sizing: border-box
    }
    

    3. 设置栅格容器

    每个栅格都有一个容器来决定栅格的最大宽度,一般可以命名为 .l-wrap, 使用 .l 表示 layout, 这种命名规范称之为 SMACSS.

    设置如下:

    .l-wrap {
        max-width: 1140px;
        margin-right: auto;
        margin-left: auto;
    }
    

    强烈推荐使用 em | rem 这样的相对单位,对于响应式布局可以增强可访问性和响应能力, 下面例子为了简洁,还是会使用pixels作为单位。

    4.计算列宽

    我们上面说过使用 floats 来布局,创建列(columns)列间距(gutter)我们由使用下面5个属性(使用flexbox则属性更多一点):

    • width
    • margin-right
    • margin-left
    • padding-right
    • padding-left

    通过上面的介绍,可以大致写出如下html(使用Jade):

    .l-wrap
      .three-col-grid
        .grid-item Grid item 1
        .grid-item Grid item 2
        .grid-item Grid item 3
    

    从这个html,我们可以知道一行总共有3列,并且没有额外的div用来充当gutters,这意味着:

    • 我们列通过 width 属性
    • 我们通过 margin 或者 padding 属性来创建列间距

    如果我们同时考虑columns 和 gutters 会使情况变得复杂,我们先假设没有列间距的情况。

    我们知道整个栅格最大宽度为1140px,这也意味着3个小栅格每个宽度为 1140px/3=380px

    .three-col-grid .grid-item {
        width: 380px;
        float: left;
    }
    

    当我们在浏览器中改变浏览器大小时,发现视窗小于1140px时,栅格会重新占据下一行,这不是我们想要的,所以我们不能使用 px 当作单位,所以我们改用百分比来当作单位:

    .three-col-grid .grid-item {
        width: 33.33333%;
        float: left;
    }
    

    有一点要注意的是: 当一个容器中的所有子元素都是浮动的时候,容器的高度会坍塌(height collapses), 这个现象称之为 float collapse。就好像这个容器没有包含元素一样。所以我们要清除浮动

    .three-col-grid:after {
        display: table;
        clear: both;
        content: '';
    }
    

    如果使用sass的话:

    @mixin clearfix {
        &:after {
            display: table
            clear: both;
            content: '';
        }
    }
    // 使用
    .three-col-grid {@include clearfix}
    
    // sass表示
    @mixin clearfix
      &:after
        display: table
        clear: both
        content: ''
    
    .three-col-grid
      +clearfix
    

    5.决定列间距的位置

    上面我们可以知道,可以使用 margin 或者 padding 来创建列间距,有4种情况:

    • 使用margins,间距放在同一边
    • 使用padding, 间距放在同一边
    • 使用margins, 间距等分的放在2边
    • 使用paddings, 间距等分的放在2边

    从这开始事情将变得复杂,你需要计算列宽依据你选择上面的哪一种方式。

    方法1:one-sided gutters(using margin)

    这个方法使用margin属性,这个间距放在右边或者左边,由你决定。我们假设放在右边:

    .grid-item {
        /* 需要重新计算width 属性 */ 
        margin-right: 20px;
        float: left;
    }
    

    这里有个问题,就是列宽我们使用的是百分比, 而margin使用的是pixels,单位不一致,我们不能同时进行计算。

    这在以前是不能计算的,现在我们可以使用CSS 提供的 calc 函数(注意不支持IE8-和opera mini) 来混合计算不同的单位,浏览器会自动帮助我们计算最后渲染出来的宽度值。

    .grid-item {
        width: calu((100% - 20px * 2) / 3);
        /* 其他属性 */
    }
    

    最后我们需要移除最右边的grid item 的 margin-right

    .grid-item:last-child {
        margin-right: 0;
    }
    

    大多时候,移除最右边盒子的外边距的同时,一般需要将 float 设置为 right,这样可以阻止浏览器给盒子添加的子像素,导致盒子移动到下一行的情况,即:

    .grid-item:last-child {
        margin-right: 0;
        float: right;
    }
    

    这样对一行的情况已经OK了,对于多行的情况,我们需要移除每一行最右边的盒子的外边距,可以使用 nth-child():

    .grid-item:nth-child(3n+3) {
        margin-right: 0;
        float: right;
    }
    

    方法2:one-sided gutters(using paddings)

    和方法1一样,这个方法将列间距放在列的一边。假设放在右边:


    .grid-item {
        /* 宽度属性 */
        padding-right: 20px;
        float: left;
    }
    

    发现宽度和方法1中的不同了吗?因为我们将box-sizing设置为了 'border-box', 现在宽度计算包括padding值。

    这种情况,3列中的2列快读要大于最后一列的宽度,这样会导致怪异的CSS计算情况出现,建议永远不要尝试这种方法,可能出现很丑的界面

    方法3:split gutters(using margin)

    这个方法将列间距放在列的两边,这样代码看起来像这样:

    .grid-item {
        /* 宽度属性 */
        margin-right: 10px;
        margin-left: 10px;
        float: left;
    }
    

    利用 calc() 计算列宽:

    .grid-item {
        /* 注意这里列宽要比第一种情况小 */
        width: calc((100% - 20px * 3) / 3);
        margin-right: 10px;
        margin-left: 10px;
        float: left;
    }
    

    这样就可以了,没有其余的步骤需要去做了,多行也是一样,也不用特意设置很行最后一个盒子的样式了

    方法4: split gutters(using padding)

    这个方法和方法3差不多,但是宽度计算更简单了,因为padding值直接包含在盒子里面:

    .grid-item {
        width: 33.3333%;
        padding-right: 10px;
        padding-left: 10px;
        float: left;
    }
    

    注意使用这个方法,需要在.grid-item 里面在添加一层div,使得2盒子之间的界限更加的清晰,即:

    .l-wrap
      .three-col-grid
        // 需要多添加一层div.grid-inner
        // 使得各个grid-item之间的间隙更加的明显
        .grid-item: .grid-inner Grid item
        .grid-item: .grid-inner Grid item
        .grid-item: .grid-inner Grid item
        .grid-item: .grid-inner Grid item
        .grid-item: .grid-inner Grid item
        .grid-item: .grid-inner Grid item
    

    查看codepen代码

    选择哪一种方法?

    如果要选的话,我会选择列间距放两边而不是把列间距放一边的方法, 因为这样CSS更简单。另外更偏向于使用margin作为列间距,因为代码会更加的干净, 即方法3最为理想。但是方法4使用padding计算更加简单,下面会使用padding来作介绍。

    6.创建调试栅格

    当开始创建栅格时,创建一个控制栅格用于调试对于布局帮助很大,这样可以帮助你正确的创建栅格。

    目前只有一个蹩脚的调试栅格,就是创建HTML元素,添加一些CSS。codepen

    HTML:

    .l-wrap
      .fixed-gutter-grid
        .column
        .column
        .column
        .column
        .column
        .column
        .column
        .column
        .column
        .column
        .column
        .column
    

    CSS(使用margins分开式列间距,即上面的方法3):

    .l-wrap {
      max-width: 1140px;
      margin-right: auto;
      margin-left: atuo;
    }
    
    .column {
      width: calc((100% - 20px * 12) / 12);
      height: 80px;
      margin-left: 10px;
      margin-right: 10px;
      background: rgba(0, 0, 255, 0.25);
      float: left;
    }
    

    7.创建布局变形

    下一步就是根据内容创建布局变形,这也正是栅格系统最耀眼的地方。可以创建给布局一个合理的名字,而不必要写多个栅格class。

    例如,加入你有个栅格系统只用于guest articles,这个布局分布为 2-7-3,这个guest-article 布局为:

    .l-guest-article
      .l-guest.grid-item: .grid-inner item 1
      .l-main.grid-item: .grid-inner item 2
      .l-sidebar.grid-item: .grid-inner item 3
    

    每列宽度为 100% / 12 = 8.333%, 因此.l-guest为 8.333% * 2, 其余栅格依次求出宽度, 可以使用预处理语言(不如sass) 的percentage函数来代替手动计算

    即:

    .l-grid-article
      +clearfix
    
      .l-guest
        width: percentage(2/12)
        
        .grid-inner
          background-color: pink
    
      .l-main
        width: percentage(7/12)
        
        .grid-inner
          background-color: yellow
    
      .l-sidebar
        width: percentage(3/12)
        
        .grid-inner
          background-color: blue
    
    // 将共同部分提取出来
      .grid-item
        padding-right: 10px
        padding-left: 10px
        float: left
    
    .grid-inner
      display: flex
      justify-content: center
      align-items: center
      height: 80px
      text-align: center
    

    栅格系统变种codepen

    8.使布局变得响应式

    最后一步就是让布局变得响应式, 可以根据下图方法:

    可以看出l-guest-articlehtml标记不改变,完全由CSS来控制布局, 当使用CSS来做响应式布局时,强烈建议移动优先原则,这样写的代码更加的简洁

    1.移动布局:

    .l-guest-article
      .l-guest /* 这里什么都不用写*/
      .l-main
        margin-top: 20px
      .l-side-bar
        margin-top: 20px
    

    我们什么也不用做,因为组件默认的会占满父元素宽度,我们可以给上下盒子之间添加一些外边距

    2.平板布局:

    对于这种布局,假定我们的临界点(breakpoint)为700px.

    • .l-guest占据 4/12
    • .l-main.l-sidebar 占据8/12

    我们应当将 .l-main 中的 margin-top 移除, 因为它和 .l-guest在同一行。

    另外如果我们设置 .l-sidebar为8列,它会自动在第2行上,因为第1行没有多余的空间了。我们可以使用 margin-right 或者 float: right让它在右边。

    如下(别忘记容器清除浮动):

    .l-guest-article
      +clearfix
    
      .l-guest
        @media(min-width: 700px)
          width: percentage(4/12)
          float: left
    
      .l-main
        margin-top: 20px
        @media(min-width: 700px)
          width: percentage(8/12)
          margin-top: 0
          float: left
    
      .l-sidebar
        margin-top: 20px
        @media(min-width: 700px)
          width: percentage(8/12)
          float: right
    

    3.桌面布局

    假设临界点为1200px,这个和前面介绍的布局方式一致,为 2-7-3

    值得注意的是,别忘记移除 .l-sidebarmargin-top

    .l-guest-article
      +clearfix
    
      .l-guest
        @media (min-width: 700px)
          width: percentage(4/12)
          float: left
    
        @media (min--width: 1200px)
          width: percentage(2/12)
    
      .l-main
        margin-top: 20px
        
        @media (min-width: 700px)
          width: percentage(8/12)
          margin-top: 0
          float: left
    
        @media (min-width: 1200px)
          width: percentage(7/12)
    
     .l-sidebar
        margin-top: 20px
        
        @media (min-width: 700px)
          width: percentage(8/12)
          float: right
    
        @media (min-width: 1200px)
          width: percentage(3/12)
          margin-top: 0
    

    具体效果 响应式设计

    总结

    通过这篇文章,我们学习了如何自定义栅格系统,以float作为布局规则,主要有以下几个知识点:

    1. 设置box-sizing,容器宽度使用 max-width
    2. 使用 calc() 函数计算列宽(注意IE8-不能使用)
    3. 常见的4种列间距的使用方法,最常用的就是使用margin平分列间距
    4. 使用sass的辅助函数 percentage 来进行宽度计算
    5. 使用 media query 实现响应式布局
    6. 注意使用浮动时,注意清除浮动
    7. 当然还有捎带提及了SMACSS命名方法

    相关文章

      网友评论

        本文标题:#1 自定义栅格系统&响应式布局

        本文链接:https://www.haomeiwen.com/subject/muvcpttx.html