第 22 集:Bootstrap 客制化 utilities(下)

此篇延续 Bootstrap 客制化 Sass utilities(上)最後尚未介绍的 generate-utility,解析 generate-utility 是如何生成通用类别样式。

generate-utility

generate-utility 来自於 mixins/_utilities.scss 这只主要生成通用类别样式的档案。

主要分为三个区块来解析

第一区块:取 values 参数

取得 utilities 资料中 values 的值,并透过回圈读取出来,若 $values 不是 map 型态,则会将其转换为 list 型态(为了让最後生成通用类别样式时可以取得到 key, value)。

@mixin generate-utility($utility, $infix, $is-rfs-media-query: false) {
  $values: map-get($utility, values);

  @if type-of($values) == "string" or type-of(nth($values, 1)) != "list" {
    $values: zip($values, $values);
  }
}
  • 透过回圈读取 $values 内的 api 设置参数。
@each $key, $value in $values {
}

第二区块:取得其它参数

property

property 为要产生的 css 属性名称,型态为字串或阵列。

判断型态是否为字串:

  • 由於後续生成样式使用回圈读 $properties 的方式进行,因此若型态为字串(只有一个属性),则透过append 将 property 值插入到空白阵列中。
@if type-of($properties) == "string" {
  $properties: append((), $properties);
}

$property-class css 属性对应的通用类别名称。(ex:font-size 对应 fs

判断参数中是否有设置 class 参数

  • true:取 class 值作为通用类别名称开头。
  • false:取 $properties 阵列的第一个元素作为通用类别名称开头。

$property-class 值为 null 则赋予空字串。

$property-class: if(map-has-key($utility, class), map-get($utility, class), nth($properties, 1));
$property-class: if($property-class == null, "", $property-class);

state

伪类 Pseudo-classes 参数。(ex::hover:focus

$property-class 值为 null 则赋予空阵列, @each 遇到空置列则不会执行回圈。

$state: if(map-has-key($utility, state), map-get($utility, state), ());

没看到 Bootstrap 原始码使用到,但看了一下生成通用类别的方法,想到了有趣的灵感。

state 使用特性:

  • css 属性设置方式和一般通用类别相同。
  • class 名称会在後方加上 :state 名称。(ex::hover

利用 state 特性,来针对某个 css 属性,设置对应的伪类样式。

举例滑鼠移过 container-fluid 元素时就改变背景颜色。


"container-fluid-hover": (
  property: background-color,
  state: hover,
  class: container-fluid,
  values: (
    "index": $dark;
    "product": $light;
  )
),

编译後的样式

  • 这样只要使用对应的 .container-fluid-*hover 样式就有 hover 效果了。
.container-fluid-index-hover:hover {
  background-color: $dark
}
.container-fluid-product-hover:hover {
  background-color: $light
}

优势:

  • 可以缩减撰写样式的 scss 档。

注意两个前提:

  1. 除非原本的样式原生的通用类别就有。
  2. 除非自己撰写的样式,类似的有复数以上。

若不符合上述前提,就没有达到 缩短程序码 这个目的,其实直接把伪类样式写在原本样式的後方即可。


$infix

判断有取得断点的且 $property-class"" 的情况下,就将 $infix 前方的 - 符号拿掉後并覆盖 $infix 值。

$infix: if($property-class == "" and str-slice($infix, 1, 1) == "-", str-slice($infix, 2), $infix);

property-class-modifier

判断若 $value 的 key 值等於 null,则不加通用类别前缀字。

举例 border

  • 是 null:border
  • 不是 null:border-0

通常用来作为 css 属性的预设样式。(ex:border、rounded、shadow)

$property-class-modifier: if($key, if($property-class == "" and $infix == "", "", "-") + $key, "");

rfs

判断是否有设置响应式,随着视窗大小计算适合的尺寸。(这边先跳过,之後有缘再来写一篇 rfs 计算方式)

@if map-get($utility, rfs) {
  @if $is-rfs-media-query {
    $val: rfs-value($value);

    $value: if($val == rfs-fluid-value($value), null, $val);
  }
  @else {
    $value: rfs-fluid-value($value);
  }
}

第三区块:生成样式

将以上取得的参数,组合起来产生通用类别的样式。

生成的通用类别分为两种:

  • 一般通用类别
  • 包伪类通用类别

两种差别在於,是否有设置 state 伪类参数。

$property-class:通用类别前缀字。
$infix:断点 point。
$property-class-modifier:通用类别 values
参数的 key 值。
$properties: 要执行的 css 属性。
$value:通用类别 values 参数的 value 值。
$enable-important-utilities:是否在生成通用类别样式後方加上 !important(预设是 true)。

.#{$property-class + $infix + $property-class-modifier} {
  @each $property in $properties {
    #{$property}: $value if($enable-important-utilities, !important, null);
  }
}

两种生成样式後的对照图

一般通用类别:

含伪类通用类别:

小技巧:

  • 含伪类通用类别的样式名称可以把伪类 拿掉,只需移除 -#{$pseudo} 即可。


将修改 BS5 的核心 code 简单刻了两个版本 CodePen 连结:


<<:  Day22-TypeScript(TS)的函式(Function) Part2

>>:  不只懂 Vue 语法:试说明有哪些方式可以全域注册方法?

[ Day10] Web 小复习

哈罗各位安安 今天是连续发文的第10天 我没囤文,每天当下产文完成1/3了 洒花~ ㄟ我会不会太早庆...

Day15 开发套件 - 实作MethodChannel

Flutter 端: lib/batterylevel.dart:新增取得电池电量资讯方法,透过建立...

Day28 - 部属到正式环境 (3)

今天的实作内容主要根据教学网站进行。 将应用程序安装到Heroku (接续Day27) 使用GIT将...

资料分析成熟度模型(Data Analytics Maturity Model, DAMM)

资料平台的建构从基础设施建设开始,配合业务需求,以大数据技术作为战略的基石。 基础设施 包括硬体资源...

D25 - 用 Swift 和公开资讯,打造投资理财的 Apps { 三大法人成交比重 资料分析 }

台湾股市有揭露三大法人当日买进卖出的金额,在市场上会有流派依照这些进出的资讯,调整手上的资金部位。因...