个性化阅读
专注于IT技术分析

Flexbox和Sass Grid教程:如何简化响应式设计

本文概述

最近, 我面临着创建自己的网格系统的挑战, 并且由于重新发明方向盘对于学习体验总是非常有用的, 所以我选择了它。我知道这将是一个有趣的挑战, 但事实证明如此容易, 我感到惊讶!

Sass和Flexbox网格教程

在本实验中, 我们将研究Flexbox布局以及它们如何允许布局的优美实现而无需进行任何疯狂的修改。另外, 如果你不熟悉Sass, 我们将了解它的工作原理并使用一些方便的Sass实用程序。你甚至可以学习有关CSS网格的新知识, 例如Bootstrap的一部分。

Sass和Flexbox的简短介绍

Sass基本上是一种可以避免CSS缺点的工具, 它是一种脚本语言, 可以解释为CSS。如果你已经在编写CSS样式, 但是该语法看起来非常熟悉, 但是其工具箱中包含变量, 可重用的mixins以及for和while指令等。关于Sass的最方便的事情之一是任何有效的CSS代码都是有效的Sass, 因此你可以逐步转换代码库。

一个简单的for循环示例:

@for $i from 1 through 3 {
  .a-numbered-class-#{$i} {
    width: (20 * $i) * 1px;
  }
}

这个简单的循环从1迭代到3并创建类。迭代的索引将方便地存储在$ i中。我们还可以进行数学运算, 并以不同的宽度每次打印.a-numbered-class-X三次。此代码输出:

.a-numbered-class-1 {
  width: 20px;
}

.a-numbered-class-2 {
  width: 40px;
}

.a-numbered-class-3 {
  width: 60px;
}

正如我们所看到的, 我们可以抽象出你在CSS中要做的许多工作。在CSS中, 你必须手动复制, 粘贴和修改, 这显然更容易出错且不太美观。如果你还没有尝试过, 那就不要再浪费时间了!

Flexbox代表Flexible Box, Flexible Box是一个CSS3布局系统, 可以动态定位和分配元素。这是一个非常强大的工具, 可以轻松进行灵活的布局。有关如何学习Flexbox的更多详细信息, 请查看Chris Coyier的Flexbox完整指南。

网格

进入网格本身, 让我们从其基本元素开始。它们将受到Bootstrap的网格元素的启发:容器, 行和列, 每个元素都包含在其中。

我们将使用BEM命名约定来命名类的名称。 BEM约定非常易于使用, 并添加了许多有关元素及其上下文的信息。简而言之, 你有:

  • 块, “封装了对自己有意义的独立实体”:.block。
  • 元素是”块的一部分, 没有独立的含义”, 由块名称, 两个下划线和元素表示:.block__elem
  • 修饰符, 如”块或元素上的标志”, 用两个破折号表示:.block .block–mod。
容器,行和列

容器

这是网格的最外层元素, 它将包含我们的行元素。容器有两种类型:.container和.container–fluid。

.container的行为定义为某点以下宽度的100%, 其上方具有最大固定宽度, 并且左右边距相等:

$grid__bp-md: 768;
.container {
  max-width: $grid__bp-md * 1px;
  margin: 0 auto;
}

通过扩大和缩小”输出”窗口在此处玩

对于始终具有100%宽度的流体容器, 我们只需使用修饰符覆盖这些属性:

&--fluid {
    margin: 0;
    max-width: 100%;
  }

在这里玩。

那很简单!现在, 我们已经实现了两个容器。让我们继续下一个元素。

行数

行将是我们内容的水平组织者。

我们将使用Flexbox定位行的子元素, 使其包裹起来, 以免它们溢出, 并在行内提供100%的宽度(以便我们以后可以嵌套它们)。

&__row {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
}

如果子元素的宽度之和大于其自身的宽度, 则这将使子元素并排放置并换行。现在, 我们只需要添加一些div, 它将如下所示:

行元素

通过扩展和收缩”输出”窗口在此处进行操作。

事情开始成形, 但这还不是CSS网格。它不见了…

列是网站内容所在的位置。它们定义了该行被分成多少部分以及它们占据了多少。我们将进行十二列的布局。这意味着我们可以将行分为一个或最多十二个部分。

首先, 一些基本数学。当我们要有一列时, 其宽度应为100%。如果我们要十二列。然后每个应该占宽度的8.333…%或100/12。

使用Flexbox, 要以这种方式分发内容, 我们可以使用flex-basis。

为了分成四列, 我们现在将添加以下内容:

flex-basis: (100 / 4 ) * 1%;

这样, 我们可以使每个元素占据宽度的25%或我们想要的任何百分比。

在这里玩。

让我们变得更有活力。由于我们希望这能反映我们可能的类, 因此我们将其命名为.col-1, 这是一个列div的类, 其宽度为8.333%, 因为其中的十二个必须在换行之前适合。百分比将一直递增, 直到.col-12, 它将占100%。

$grid__cols: 12;
@for $i from 1 through $grid__cols {
  .col-#{$i} {
    flex-basis: (100 / ($grid__cols / $i) ) * 1%;
  }
}

只是为了澄清情况, 假设我们要将宽度分为四个相等的部分。我们需要.col-3, 因为它适合12的4倍, 这意味着.col-3应该具有25%的flex-basis:

100 / ($grid__cols / $i) 
100 /     (12  / 3)       =  25

这已经开始看起来像网格!

看起来像网格!

在这里玩。

屏幕宽度相关列

现在, 我们希望能够拥有一个元素, 该元素在移动设备上具有一定宽度, 而在平板电脑上具有不同的宽度, 依此类推。我们将使用取决于窗口宽度的某些断点。我们的UI将对这些断点做出反应, 并适应适合不同设备屏幕尺寸的理想布局。我们将按大小来命名断点:small(sm), medium(md)等, .col-sm-12将是一个元素, 至少在sm断点之前占据12列。

让我们重命名.col- *类.col-sm- *。由于我们的网格将首先移动, 因此我们将其属性应用于所有屏幕尺寸。对于我们需要在更大的屏幕上表现不同的那些, 我们将添加类:.col-md- *。

想象一个带有.col-sm-12和.col-md-4的元素。预期的行为将是, 在断点” md”(中)以下, 它将具有100%的宽度, 在断点” md”(中)之上, 将具有33.333%的宽度-这是非常常见的情况, 因为在移动设备上, 你可能需要将元素堆叠在顶部而不是在其旁边。当你的宽度受到更多限制时, 彼此可以互相配合。

达到断点后堆叠列

为此, 我们需要在断点处添加一个媒体查询(一个表达式, 该表达式只在特定宽度以上或以下执行, 或者在特定设备上执行), 并像以前对sm一样创建md列:

@media screen and (min-width: $grid__bp-md * 1px) {
  @for $i from 1 through $grid__cols {
    &__col-md-#{$i} {
      flex-basis: (100 / ($grid__cols / $i) ) * 1%;
    }
  }
}

在这里玩。

这已经接近有用的东西了。相当多的WET(明白吗?不是DRY…), 所以让它变得更加抽象。

如我们所见, 我们将需要为每个断点提供媒体查询, 因此让我们创建一个混入, 它接收一个动态创建媒体查询的断点。它可能看起来像这样:

@mixin create-mq($breakpoint) {
  @if($breakpoint == 0) {
    @content;
  } @else {
    @media screen and (min-width: $breakpoint *1px) {
      @content;
    }
  }
}

现在, 让我们将创建__col类的内容包装在一个称为create-col-classs的mixin中, 并使用create-mq mixin。

@mixin create-col-classes($modifier, $grid__cols, $breakpoint) {
  @include create-mq($breakpoint) {
    @for $i from 1 through $grid__cols {
      &__col#{$modifier}-#{$i} {
        flex-basis: (100 / ($grid__cols / $i) ) * 1%;
      }
    }
  }
}

就是这样。要使用它, 我们现在在Sass映射中定义断点, 并对其进行迭代。

$map-grid-props: ('-sm': 0, '-md': $grid__bp-md, '-lg': $grid__bp-lg);
@each $modifier , $breakpoint in $map-grid-props {
  @include create-col-classes($modifier, $grid__cols, $breakpoint);
}

我们的网格系统已基本完成!我们定义了一个.container__col-sm- *类作为默认类, 我们可以使用container__col-md- *和container__col-lg- *在更大的屏幕上修改其行为。

我们甚至可以嵌套行!在这里玩。

这样做的好处是, 如果我们现在希望它具有与Bootstrap v4相同的所有断点, 则只需执行以下操作:

$grid__bp-sm: 576;
$grid__bp-md: 768;
$grid__bp-lg: 992;
$grid__bp-xl: 1200;
$map-grid-props: (
        '': 0, '-sm': $grid__bp-sm, '-md': $grid__bp-md, '-lg': $grid__bp-lg, '-xl': $grid__bp-xl
);

就是这样!在这里玩。

请注意, Bootstrap如何采用比我们最初讨论的更完整的”移动优先”方法。最小的窗口大小没有后缀, 例如sm或md, 原因是等效于.container__col-X的类不仅会在0到576px的窗口宽度中应用;如果我们不明确覆盖它, 则它将是每个窗口大小的列数。否则, 我们可以添加类.container__col-sm-Y, 使其在sm断点之间的宽度为Y列。

偏移量

偏移量将增加上一列的边距。 .container__col-offset-4将在所有屏幕尺寸上增加左边距:33.333%。 .container__col-md-offset-4将执行相同的操作, 但在md断点之上。

现在实现起来很简单。我们在创建类的同一循环上添加了-offset属性, 但是编写了margin-left属性而不是flex-bases。我们也必须为-offset-0做额外的操作, 因为我们可能想在更大的屏幕上清除边距:

@mixin create-col-classes($modifier, $grid-cols, $breakpoint) {
  @include create-mq($breakpoint) {
    &__col#{$modifier}-offset-0 {
      margin-left: 0;
    }
    @for $i from 1 through $grid-cols {
      &__col#{$modifier}-#{$i} {
        flex-basis: (100 / ($grid-cols / $i) ) * 1%;
      }
      &__col#{$modifier}-offset-#{$i} {
        margin-left: (100 / ($grid-cols / $i) ) * 1%;
      }
    }
  }
}

现在, 我们有功能齐全的胶印!在这里玩。

显示性

有时我们希望显示/隐藏某个点之下或之上的元素。为此, 我们可以使类像Bootstrap v4一样可用。

例如, .hidden-md-up类将从md断点向上隐藏该类的任何元素;相反, .hidden-md-down会将其隐藏在断点下方。

这样的代码又很简单:我们只是迭代断点, 并为每个断点创建一个.hidden- *类。不过, 我们修改了create-mq类, 使其更加抽象:

@each $modifier , $breakpoint in $map-grid-props {
  @if($modifier == '') {
    $modifier: '-xs';
  }
  @include create-mq($breakpoint - 1, 'max') {
    .hidden#{$modifier}-down {
      display: none !important;
    }
  }
  @include create-mq($breakpoint, 'min') {
    .hidden#{$modifier}-up {
      display: none !important;
    }
  }
}

附带说明一下, 这不是!important的少数几个好用法之一吗?注意, 该元素在display:block规则中可能具有更高的特异性, 但我们仍希望将其隐藏在断点以下或上方。如果你不同意这种方法, 请在评论中告诉我!

就是这样:现在我们有了一个可显示系统。

在这里玩。

总结

尽管此”框架”尚未投入生产, 但它显示了Flexbox布局可以多么强大, Sass多么方便。仅用几行代码, 我们就实现了CSS框架/网格的核心功能。

也可以作为一个教训, 使几乎所有软件的基本版本都可以非常容易地实现。现实世界中的具体问题开始加重并使其变得困难。

我创建了一个GitHub存储库, 你可以在其中提交问题或请求。

你希望实现哪些功能?实施可以简化还是更优雅?

请随时让我知道你对以下评论的看法。

赞(0)
未经允许不得转载:srcmini » Flexbox和Sass Grid教程:如何简化响应式设计

评论 抢沙发

评论前必须登录!