HTML+CSS入门 如何编写通用的 Helper Class
沉沙 2018-06-15 来源 : 阅读 991 评论 0

摘要:什么是 helper ?任何框架都不是万能的,而业务需求却是多种多样,很多时候我们只需要更改组件的部分属性,而 helper 就是调整细节的工具。大部分的 helper 都是一个类对应一个 CSS 属性,属于最细小的类。编写一套简单易用、通俗易懂的 helper 非常重要。本文的目的就是探讨 helper 的组成部分、编写方式以及如何精简 helper 的命名。希望阅读本篇文章以后大家有所收获,帮助大家对HTML+CSS的理解更加深入。

前言

什么是 helper ?任何框架都不是万能的,而业务需求却是多种多样,很多时候我们只需要更改组件的部分属性,而 helper 就是调整细节的工具。大部分的 helper 都是一个类对应一个 CSS 属性,属于最细小的类。编写一套简单易用、通俗易懂的 helper 非常重要。本文的目的就是探讨 helper 的组成部分、编写方式以及如何精简 helper 的命名。


组件与零件

编写 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


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


Helper 的组成部分

一套完整的 helper 应该包含哪些内容呢?一般常用的有 padding、margin、font-size、font-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)

· …

helper 类几乎都是 Sass 循环生成的,所以源代码看上去很精简。


颜色变量

因为颜色稍微特殊一点,将颜色与其它内容分开单独介绍。在编写轻量级框架的时候,常用的一些颜色面对特殊需求时略显单一,所以我们需要使用 helper 扩充颜色集群。但是颜色是一个无法量化的概念,所以再强大的 helper 也无法面面俱到,只能是一定程度上的补充。

 HTML+CSS入门 如何编写通用的 Helper Class

HTML+CSS入门 如何编写通用的 Helper Class

其中每个颜色都有六个亮度值,分别用 -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%);
    }
}

   

命名策略

无论是框架还是 helper,类命名都决定了其易用性,而且会影响使用者的习惯。不过 helper 的命名比较简单,因为几乎大多数都是单一的 CSS 样式,所以命名策略基本都是对 CSS 属性的抽象与简化。


数字型命名 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 值的话,尺寸型命名就乏力了。凡是可以量化的属性,比如 padding、margin、font-size、border-width 等,应该直接用数值表示,而对于不可以量化的属性,比如 box-shadow,用尺寸型命名比较合适。


精简命名

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

以 padding 循环为例:

<a href='//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 与此类似,循环也很简单。


关于 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;
}

   

可以简化一步,用 - 表示负值,简单易懂,如下:

.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 不太统一。


关于圆角

圆角的 CSS 属性名为 border-radius,如果直接简写的话和 border-right 就重复了,参见其它框架的表示方法有 corner-rounded、rounded 等。我们也可以简化一下,比如直接用 r表示,既可以代表 rounded 也可以代表 radius,一举两得。这样的表示方法应该不会有歧义,毕竟在我们的脑海中,r 表示半径算是一个根深蒂固的概念。Sass 代码如下:

<a href='//www.jobbole.com/members/lowkey2046'>@for</a> $counter from 0 through 10 {
    .r-#{ $counter } {
        border-radius: ($counter * 1px) !important;
    }
    .r-t-l-#{ $counter } {
        border-top-left-radius: ($counter * 1px) !important;
    }
    .r-t-r-#{ $counter } {
        border-top-right-radius: ($counter * 1px) !important;
    }
    .r-b-r-#{ $counter } {
        border-bottom-right-radius: ($counter * 1px) !important;
    }
    .r-b-l-#{ $counter } {
        border-bottom-left-radius: ($counter * 1px) !important;
    }
}

   

我们用 -full 表示 100%,其它框架也基本如此,稍后再谈论 r-100% 这种形式的可行性及问题所在。

.r-full {
    border-radius: 100%
}
.r-t-l-full {
    border-top-left-radius: 100%
}
.r-t-r-full {
    border-top-right-radius: 100%
}
.r-b-r-full {
    border-bottom-right-radius: 100%
}
.r-b-l-full {
    border-bottom-left-radius: 100%
}

   

同样的,高度和宽度的 100% 数值也用 -full 表示,循环方式类似。


关于阴影

我们在之前反复提到了阴影属于非量化的属性,所以只能使用尺寸型命名法,当然用数字也不是不可以,一会儿再详细说明。先看源代码:

.shadow-xs{
    box-shadow:0 1px 5px 1px rgba(0,0,0,.15);
}
.shadow-sm{
    box-shadow:0 2px 10px 2px rgba(0,0,0,.15);
}
.shadow-md{
    box-shadow:0 3px 20px 3px rgba(0,0,0,.15);
}
.shadow-lg{
    box-shadow:0 4px 30px 4px rgba(0,0,0,.15);
}
.shadow-xl{
    box-shadow:0 5px 40px 5px rgba(0,0,0,.15);
}

   

整体而言,比较简洁,不过阴影的数值这里是粗略添加的,实际情况要做调整。


关于强度表示法

通过 font-weight 说一下关于强度的表示法,font-weight 的 CSS 属性本身就有两种表示法,一种是直接文字命名,比如 .f-s-thin , .f-s-normal, .f-s-bold 等,另一种是比较直接的 100 ~ 900 数值型表示法。数值型表示法,简单直观,并没有歧义,也算是约定俗成的规定吧。font-weight 的循环比较简单,而且数值有限,我们可以直接写出从 100 ~ 900 的所有 helper。其它类似的 helper 也可以用 100 ~ 900 表示强度,比如颜色。

需要注意的是,编写 helper 时一定要对数值型、尺寸型、强度型命名做好归类与统一,切记毫无章法地胡乱使用。


类命名中的特殊字符

对于 r-100% 或者 w-100% 这样的写法是可以的,但是在定义 CSS 时要进行字符转义,比如

.r-100\% {
    border-radius: 100%
}

   

使用方式如下

<div class="r-100%"></div>

但是这种写法输入时要按 shift + %,不太方便,所以暂时只作为参考。

另外需要说明一点,我们可以通过特殊字符定义百分数,比如:

.w-50 {
   width: 50px;
}
.w\:50 {
   width: 50%
}

   

通过约定的这种规则,我们就可以为 helper 添加栅格系统了。不过这只是暂时的想法,毕竟我们已经有一套轻量级 CSS 框架了。


序列数量

因为 helper 是循环生成的,所以循环的数量决定了 helper 的丰富度。那么循环的数量多少合适呢?这是所有 helper 最难统一的地方。不可否认,helper 的数量越多,通用性越强,也就越灵活。任何事物都有两面性,虽然 helper 越多越好,但是数量太多会造成文件臃肿。另一方面,其实 helper 并没有必要写的太全面,很多数值存在冗余。

简单来说,对于有限值的 helper 就可以全部写出,比如对其方式、font-weight 等。而对于任意数值的 helper 来说,我们需要选择常用的一些数值,比如 padding、margin 等属性,基本 1~50 px 之间就可以了,而圆角 1~20 px 足矣。不能量化的属性比如阴影就完全看个人喜好了,五个尺寸就差不多。对于实在特殊的需求也只能特殊对待了。


演示

现在我们测试一下我们所写的 helper 是不是能够满足一般需求,比如一个带有圆角阴影的用户卡片,如下:

See the Pen snack-helper-test by Zongbin (@nzbin) on CodePen.

CSS

/**
* ======================================
* snack-helper.css v1.0.0
* https://github.com/nzbin/snack-helper
* ======================================
*/
body{
  padding:30px;
}

   

XHTML

<div class="w-400 shadow-md r-10 b-1 p-10">
    <div class="r-full w-50 h-50 bg-blue-light pull-left m-r-10 overflow-hidden">
      <img class="w-full" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/787950/profile/profile-512.jpg?1" alt="avatar">
    </div>
  Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
</div>

   

这个实例全部是用 helper 完成的,可惜这套 helper 没有栅格系统,所以布局并不灵活,但是结合之前的轻量级框架,会显示出它强大的功能。


总结

编写 helper 比编写框架要容易的多,但简单易用、通俗易懂的 helper 还需要严谨的思考,详细的 helper 可以参见 GitHub 源码。


本文由职坐标整理发布,欢迎关注职坐标WEB前端HTML/CSS频道,获取更多HTML/CSS知识!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程