快捷搜索:
来自 新京葡娱乐场网址 2020-01-01 16:46 的文章
当前位置: 67677新澳门手机版 > 新京葡娱乐场网址 > 正文

如何编写通用的

如何编写通用的 Helper Class

2017/12/27 · CSS · CSS

本文作者: 伯乐在线 - 叙帝利 。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

新京葡娱乐场网址 1新京葡娱乐场网址 2

Github:

Docs:

新京葡娱乐场网址 3

前言

什么是 helper ?任何框架都不是万能的,而业务需求却是多种多样,很多时候我们只需要更改组件的部分属性,而 helper 就是调整细节的工具。我在之前的文章《如何编写轻量级 CSS 框架》中也举过例子,我们完全没必要因为几个属性的不同而重新编写新组件。大部分的 helper 都是一个类对应一个 CSS 属性,属于最细小的类。通过工作的实践总结,我觉得编写一套简单易用、通俗易懂的 helper 非常重要。本文的目的就是探讨 helper 的组成部分、编写方式以及如何精简 helper 的命名。

Github:

Docs:

组件与零件

详细介绍如何编写 helper 之前,先说一下我对于组件以及零件的看法。在之前编写轻量级 CSS 框架的时候,我们是以组件的方式开发。而编写 helper 更像是开发一个零件,因为 helper 的属性单一,而且多个 helper 可以形成一个组件。比如下面的例子:

假设有 .boxes 组件

.boxes { border: 1px solid #eee; border-radius: 5px; margin-bottom: 15px; overflow: hidden; }

1
2
3
4
5
6
.boxes {
    border: 1px solid #eee;
    border-radius: 5px;
    margin-bottom: 15px;
    overflow: hidden;
}

假设有如下 helper

.b-1 { border: 1px solid #eee !important; } .r-5{ border-radius: 5px !important; } .m-b-15{ margin-bottom: 15px !important; } .overflow-hidden { overflow: hidden !important; }

1
2
3
4
5
6
7
8
9
10
11
12
.b-1 {
    border: 1px solid #eee !important;
}
.r-5{
    border-radius: 5px !important;
}
.m-b-15{
    margin-bottom: 15px !important;
}
.overflow-hidden {
    overflow: hidden !important;
}

.boxes = .b-1 .r-5 .m-b-15 .overflow-hidden

我是一个模型爱好者,这样的组合方式让我想到了寿屋的 HEXA GEAR 系列模型,这个系列的特点是“零件 零件=组件、组件 组件=骨架、骨架 骨架=素体、素体 武装=机体”。

在编写 helper 的时候,基于以上想法,我在思考是否可以把 helper 拆分的足够精细,这样它就可以自成一体形成一个框架,也就是“零件 零件=组件、组件 组件=框架”。令人遗憾的是,我的想法已经被人实践,前几天浏览 GitHub 时发现了相关的项目 tailwindcss,这个框架就是以 helper 为基础,通过属性叠加的方式添加样式。

组件式框架和零件式框架是两种完全不同的思想,难分伯仲,各有优缺点。

前言

什么是 helper ?任何框架都不是万能的,而业务需求却是多种多样,很多时候我们只需要更改组件的部分属性,而 helper 就是调整细节的工具。我在之前的文章《如何编写轻量级 CSS 框架》中也举过例子,我们完全没必要因为几个属性的不同而重新编写新组件。大部分的 helper 都是一个类对应一个 CSS 属性,属于最细小的类。通过工作的实践总结,我觉得编写一套简单易用、通俗易懂的 helper 非常重要。本文的目的就是探讨 helper 的组成部分、编写方式以及如何精简 helper 的命名。

Helper 的组成部分

一套完整的 helper 应该包含哪些内容呢?一般常用的有 paddingmarginfont-sizefont-weight 等。为了编写更为通用的 helper,我们需要更细致的划分。虽然我们并没有打算把它写成一个框架,但是我们希望 helper 的功能足够强大。通过对比和思考,我将 helper 暂时划分成以下几个模块:

  • Colors(颜色,包括 bg-color 及 text-color)
  • Paddings(内边距序列)
  • Margins(外边距序列)
  • Typography(排版,包括 font-size 及 font-weight)
  • Border(边框线)
  • Radius(圆角)
  • Shadow(阴影)
  • Size(尺寸,包括 height 及 width)
  • Gutters(栅格间距序列)
  • Alignment(主要是 vertical-align)

和之前编写轻量级框架一样,我们同样使用 Sass 预编译器。helper 类几乎都是 Sass 循环生成的,所以源代码看上去很精简。

组件与零件

详细介绍如何编写 helper 之前,先说一下我对于组件以及零件的看法。在之前编写轻量级 CSS 框架的时候,我们是以组件的方式开发。而编写 helper 更像是开发一个零件,因为 helper 的属性单一,而且多个 helper 可以形成一个组件。比如下面的例子:

假设有 .boxes 组件

.boxes {
    border: 1px solid #eee;
    border-radius: 5px;
    margin-bottom: 15px;
    overflow: hidden;
}

假设有如下 helper

.b-1 {
    border: 1px solid #eee !important;
}
.r-5{
    border-radius: 5px !important;
}
.m-b-15{
    margin-bottom: 15px !important;
}
.overflow-hidden {
    overflow: hidden !important;
}

.boxes = .b-1 .r-5 .m-b-15 .overflow-hidden

我是一个模型爱好者,这样的组合方式让我想到了寿屋的 HEXA GEAR 系列模型,这个系列的特点是“零件 零件=组件、组件 组件=骨架、骨架 骨架=素体、素体 武装=机体”。

在编写 helper 的时候,基于以上想法,我在思考是否可以把 helper 拆分的足够精细,这样它就可以自成一体形成一个框架,也就是“零件 零件=组件、组件 组件=框架”。令人遗憾的是,我的想法已经被人实践,前几天浏览 GitHub 时发现了相关的项目 tailwindcss,这个框架就是以 helper 为基础,通过属性叠加的方式添加样式。

组件式框架和零件式框架是两种完全不同的思想,难分伯仲,各有优缺点。

颜色变量

因为颜色稍微特殊一点,我将颜色与其它内容分开单独介绍。在编写轻量级框架的时候,我也定义了常用的一些颜色,但是面对特殊需求时略显单一,所以我们需要使用 helper 扩充颜色集群。但是颜色是一个无法量化的概念,所以再强大的 helper 也无法面面俱到,只能是一定程度上的补充。参考常用的颜色值,最终我设置了红、橙、黄、绿、青、蓝、靛、紫、粉、冷灰、暖灰等几种色系。

新京葡娱乐场网址 4新京葡娱乐场网址 5

其中每个颜色都有六个亮度值,分别用 -lightest-lighter-light-dark-darker-darkest 表示,此处有参考 tailwindcss 的颜色命名。这些颜色都是通过 Sass 的颜色函数生成的。以灰色为例,Sass 代码如下:

$gray:#999; $gray-light:lighten($gray, 15%); $gray-lighter:lighten($gray, 25%); $gray-lightest:lighten($gray, 35%); $gray-dark:darken($gray, 15%); $gray-darker:darken($gray, 25%); $gray-darkest:darken($gray, 35%);

1
2
3
4
5
6
7
$gray:#999;
$gray-light:lighten($gray, 15%);
$gray-lighter:lighten($gray, 25%);
$gray-lightest:lighten($gray, 35%);
$gray-dark:darken($gray, 15%);
$gray-darker:darken($gray, 25%);
$gray-darkest:darken($gray, 35%);

这些颜色序列看上去很像一套马克笔,不过马克笔灰色系更丰富,包括冷灰、暖灰、蓝灰、绿灰。

其中背景色的循环方式如下,为了便于循环,我们定义了一个 color map,然后用 @each 方法循环。

$color-list:( 'gray':$gray, 'brown':$brown, 'red':$red, 'orange':$orange, 'yellow':$yellow, 'green':$green, 'teal':$teal, 'blue':$blue, 'indigo':$indigo, 'purple':$purple, 'pink':$pink ); @each $name,$color in $color-list { .bg-#{$name} { background-color: $color; } .bg-#{$name}-light { background-color: lighten($color, 15%); } .bg-#{$name}-lighter { background-color: lighten($color, 25%); } .bg-#{$name}-lightest { background-color: lighten($color, 35%); } .bg-#{$name}-dark { background-color: darken($color, 15%); } .bg-#{$name}-darker { background-color: darken($color, 25%); } .bg-#{$name}-darkest { background-color: darken($color, 35%); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$color-list:(
    'gray':$gray,
    'brown':$brown,
    'red':$red,
    'orange':$orange,
    'yellow':$yellow,
    'green':$green,
    'teal':$teal,
    'blue':$blue,
    'indigo':$indigo,
    'purple':$purple,
    'pink':$pink
);
 
@each $name,$color in $color-list {
    .bg-#{$name} {
        background-color: $color;
    }
    .bg-#{$name}-light {
        background-color: lighten($color, 15%);
    }
    .bg-#{$name}-lighter {
        background-color: lighten($color, 25%);
    }
    .bg-#{$name}-lightest {
        background-color: lighten($color, 35%);
    }
    .bg-#{$name}-dark {
        background-color: darken($color, 15%);
    }
    .bg-#{$name}-darker {
        background-color: darken($color, 25%);
    }
    .bg-#{$name}-darkest {
        background-color: darken($color, 35%);
    }
}

Helper 的组成部分

一套完整的 helper 应该包含哪些内容呢?一般常用的有 paddingmarginfont-sizefont-weight 等。为了编写更为通用的 helper,我们需要更细致的划分。虽然我们并没有打算把它写成一个框架,但是我们希望 helper 的功能足够强大。通过对比和思考,我将 helper 暂时划分成以下几个模块:

  • Colors(颜色,包括 bg-color 及 text-color)
  • Paddings(内边距序列)
  • Margins(外边距序列)
  • Typography(排版,包括 font-size 及 font-weight)
  • Border(边框线)
  • Radius(圆角)
  • Shadow(阴影)
  • Size(尺寸,包括 height 及 width)
  • Gutters(栅格间距序列)
  • Alignment(主要是 vertical-align)
  • ...

和之前编写轻量级框架一样,我们同样使用 Sass 预编译器。helper 类几乎都是 Sass 循环生成的,所以源代码看上去很精简。

命名策略

理所当然,我又提到了命名策略。在编写轻量级框架的时候,我也着重讨论了类命名策略以及比较了一些框架的命名方式。无论是框架还是 helper,类命名都决定了其易用性,而且会影响使用者的习惯,所以我会从简洁、直观、易用等几个角度命名。不过 helper 的命名比较简单,因为几乎大多数都是单一的 CSS 样式,所以命名策略基本都是对 CSS 属性的抽象与简化。

颜色变量

因为颜色稍微特殊一点,我将颜色与其它内容分开单独介绍。在编写轻量级框架的时候,我也定义了常用的一些颜色,但是面对特殊需求时略显单一,所以我们需要使用 helper 扩充颜色集群。但是颜色是一个无法量化的概念,所以再强大的 helper 也无法面面俱到,只能是一定程度上的补充。参考常用的颜色值,最终我设置了红、橙、黄、绿、青、蓝、靛、紫、粉、冷灰、暖灰等几种色系。

新京葡娱乐场网址 6

其中每个颜色都有六个亮度值,分别用 -lightest-lighter-light-dark-darker-darkest 表示,此处有参考 tailwindcss 的颜色命名。这些颜色都是通过 Sass 的颜色函数生成的。以灰色为例,Sass 代码如下:

$gray:#999;
$gray-light:lighten($gray, 15%);
$gray-lighter:lighten($gray, 25%);
$gray-lightest:lighten($gray, 35%);
$gray-dark:darken($gray, 15%);
$gray-darker:darken($gray, 25%);
$gray-darkest:darken($gray, 35%);

这些颜色序列看上去很像一套马克笔,不过马克笔灰色系更丰富,包括冷灰、暖灰、蓝灰、绿灰。

其中背景色的循环方式如下,为了便于循环,我们定义了一个 color map,然后用 @each 方法循环。

$color-list:(
    'gray':$gray,
    'brown':$brown,
    'red':$red,
    'orange':$orange,
    'yellow':$yellow,
    'green':$green,
    'teal':$teal,
    'blue':$blue,
    'indigo':$indigo,
    'purple':$purple,
    'pink':$pink
);

@each $name,$color in $color-list {
    .bg-#{$name} {
        background-color: $color;
    }
    .bg-#{$name}-light {
        background-color: lighten($color, 15%);
    }
    .bg-#{$name}-lighter {
        background-color: lighten($color, 25%);
    }
    .bg-#{$name}-lightest {
        background-color: lighten($color, 35%);
    }
    .bg-#{$name}-dark {
        background-color: darken($color, 15%);
    }
    .bg-#{$name}-darker {
        background-color: darken($color, 25%);
    }
    .bg-#{$name}-darkest {
        background-color: darken($color, 35%);
    }
}

数字型命名 VS. 尺寸型命名

我在工作中接触过两种 helper 序列的表示方法,一种是常见的数字型,另一种是尺寸型。以 padding 为例:

数字型

.p-5 { padding: 5px !important; } .p-10 { padding: 10px !important; } .p-15 { padding: 15px !important; } .p-20 { padding: 20px !important; } .p-25 { padding: 25px !important; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.p-5 {
  padding: 5px !important;
}
.p-10 {
  padding: 10px !important;
}
.p-15 {
  padding: 15px !important;
}
.p-20 {
  padding: 20px !important;
}
.p-25 {
  padding: 25px !important;
}

尺寸型

.p-xs { padding: 5px !important; } .p-sm { padding: 10px !important; } .p-md { padding: 15px !important; } .p-lg { padding: 20px !important; } .p-xl { padding: 25px !important; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.p-xs {
  padding: 5px !important;
}
.p-sm {
  padding: 10px !important;
}
.p-md {
  padding: 15px !important;
}
.p-lg {
  padding: 20px !important;
}
.p-xl {
  padding: 25px !important;
}

虽然在实际应用时,尺寸型写法并没有什么不妥,但很明显它的扩展性很差,而且不直观。作为例子,我只写了五个数值,但如果我们希望添加更多的 padding 值的话,尺寸型命名就乏力了。我认为,凡是可以量化的属性,比如 paddingmarginfont-sizeborder-width 等,应该直接用数值表示,而对于不可以量化的属性,比如 box-shadow,用尺寸型命名比较合适。

命名策略

理所当然,我又提到了命名策略。在编写轻量级框架的时候,我也着重讨论了类命名策略以及比较了一些框架的命名方式。无论是框架还是 helper,类命名都决定了其易用性,而且会影响使用者的习惯,所以我会从简洁、直观、易用等几个角度命名。不过 helper 的命名比较简单,因为几乎大多数都是单一的 CSS 样式,所以命名策略基本都是对 CSS 属性的抽象与简化。

精简命名

大多数的 helpr 命名都是 CSS 属性的首字母缩写形式。比如 p 表示 paddingm 表示 marginf-s 表示 font-size 等。这符合我们期望的简洁直观的要求。但也不能唯缩写论,所有的命名都用缩写,因为有些属性的缩写会重复,而且有些缩写之后就不知道具体含义了。我们可以沿用之前的规则,可以量化的属性都用缩写,不可以量化的属性用简化的全称(比如 box-shadow 可以替换为 shadow)。

新京葡娱乐场网址 ,以 padding 循环为例:

<a href='; $counter from 0 through 6 { .p-#{ $counter * 5 } { padding: ($counter * 5px) !important; } .p-t-#{ $counter * 5 } { padding-top: ($counter * 5px) !important; } .p-r-#{ $counter * 5 } { padding-right: ($counter * 5px) !important; } .p-b-#{ $counter * 5 } { padding-bottom: ($counter * 5px) !important; } .p-l-#{ $counter * 5 } { padding-left: ($counter * 5px) !important; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<a href='http://www.jobbole.com/members/lowkey2046'>@for</a> $counter from 0 through 6 {
    .p-#{ $counter * 5 } {
        padding: ($counter * 5px) !important;
    }
    .p-t-#{ $counter * 5 } {
        padding-top: ($counter * 5px) !important;
    }
    .p-r-#{ $counter * 5 } {
        padding-right: ($counter * 5px) !important;
    }
    .p-b-#{ $counter * 5 } {
        padding-bottom: ($counter * 5px) !important;
    }
    .p-l-#{ $counter * 5 } {
        padding-left: ($counter * 5px) !important;
    }
}

对于其它几个 helper 与此类似,循环也很简单。

数字型命名 VS. 尺寸型命名

我在工作中接触过两种 helper 序列的表示方法,一种是常见的数字型,另一种是尺寸型。以 padding 为例:

数字型

.p-5 {
  padding: 5px !important;
}
.p-10 {
  padding: 10px !important;
}
.p-15 {
  padding: 15px !important;
}
.p-20 {
  padding: 20px !important;
}
.p-25 {
  padding: 25px !important;
}

尺寸型

.p-xs {
  padding: 5px !important;
}
.p-sm {
  padding: 10px !important;
}
.p-md {
  padding: 15px !important;
}
.p-lg {
  padding: 20px !important;
}
.p-xl {
  padding: 25px !important;
}

虽然在实际应用时,尺寸型写法并没有什么不妥,但很明显它的扩展性很差,而且不直观。作为例子,我只写了五个数值,但如果我们希望添加更多的 padding 值的话,尺寸型命名就乏力了。我认为,凡是可以量化的属性,比如 paddingmarginfont-sizeborder-width 等,应该直接用数值表示,而对于不可以量化的属性,比如 box-shadow,用尺寸型命名比较合适。

关于 Margin 负值

margin 的 helper 相比其它来说比较特殊,因为它有负值,所以我们必须考虑如何表示负值。有些框架用 n (negtive)表示负值。比如 m-{t,r,b,l}-n-* 的形式:

.m-t-n-5 { margin-top: -5px !important; } .m-r-n-5 { margin-right: -5px !important; } .m-b-n-5 { margin-bottom: -5px !important; } .m-l-n-5 { margin-left: -5px !important; }

1
2
3
4
5
6
7
8
9
10
11
12
.m-t-n-5 {
  margin-top: -5px !important;
}
.m-r-n-5 {
  margin-right: -5px !important;
}
.m-b-n-5 {
  margin-bottom: -5px !important;
}
.m-l-n-5 {
  margin-left: -5px !important;
}

我觉得完全可以简化一步,用 - 表示负值,简单易懂,如下:

.m-t--5 { margin-top: -5px !important; } .m-r--5 { margin-right: -5px !important; } .m-b--5 { margin-bottom: -5px !important; } .m-l--5 { margin-left: -5px !important; }

1
2
3
4
5
6
7
8
9
10
11
12
.m-t--5 {
  margin-top: -5px !important;
}
.m-r--5 {
  margin-right: -5px !important;
}
.m-b--5 {
  margin-bottom: -5px !important;
}
.m-l--5 {
  margin-left: -5px !important;
}

虽然这种命名方式很简洁,但看上去和其它 helper 不太统一。

精简命名

大多数的 helpr 命名都是 CSS 属性的首字母缩写形式。比如 p 表示 paddingm 表示 marginf-s 表示 font-size 等。这符合我们期望的简洁直观的要求。但也不能唯缩写论,所有的命名都用缩写,因为有些属性的缩写会重复,而且有些缩写之后就不知道具体含义了。我们可以沿用之前的规则,可以量化的属性都用缩写,不可以量化的属性用简化的全称(比如 box-shadow 可以替换为 shadow)。

以 padding 循环为例:

@for $counter from 0 through 6 {
    .p-#{ $counter * 5 } {
        padding: ($counter * 5px) !important;
    }
    .p-t-#{ $counter * 5 } {
        padding-top: ($counter * 5px) !important;
    }
    .p-r-#{ $counter * 5 } {
        padding-right: ($counter * 5px) !important;
    }
    .p-b-#{ $counter * 5 } {
        padding-bottom: ($counter * 5px) !important;
    }
    .p-l-#{ $counter * 5 } {
        padding-left: ($counter * 5px) !important;
    }
}

对于其它几个 helper 与此类似,循环也很简单。

本文由67677新澳门手机版发布于新京葡娱乐场网址,转载请注明出处:如何编写通用的

关键词: