我说 CSS 类名能够缩写,你不要打我!

认知偏见

当咱们遇到一种与本身认知不一样的方案或者观点的时候,情感上的喜欢和不喜欢确定是冲在咱们前面的,这是咱们的本能无可厚非。你不喜欢一我的,你就很难注意到他身上的优势,你喜欢一我的你本能会忽略这我的身上的缺点。css

像最开始我不喜欢 BEM 同样,我以为它让个人 CSS 名称又长又臭。当我静下心来去思考它要解决的问题时,我知道本身看待问题是如此的带有偏见。前端

任何一种方案的提出一定是要解决一个痛点。建议能够先把我的喜爱滞后,先冷静的思考这个方案要解决什么问题。颇有可能这个方案不是很差,只是他没有解决你的痛点,仅此而已。react

固然本文是想要给你们分享一个观点,因此还请你们多海涵。😄git

你不该该缩写

咱们在学习任何一门计算机语言的时候,都是要求命名必定要具备可读性。好比在原生 js中,咱们会看到这样的命名:github

  • getElementById
  • getElementsByClassName
  • getElementsByName

基本上咱们一看就知道这个是要干什么的,能够若是你发现有的人把上面的命名改为这样:web

  • getEId
  • getECN
  • getEN

我想你和我同样第一眼看到这样的代码,脑壳里面会出现一个大大的问号,可能 getEId 大概还能猜到是要干什么。可是 getEN 我可能会觉得这个是将中文转化成英文的方法吧。npm

因此你们约定俗成的是,在命名的时候不要用缩写,能写全的都尽可能写全,即便那样会增长必定的代码体积,可是对于项目管理来讲是值得推荐的。bootstrap

然而在写 CSS 的时候,我却发现,这个条定律彷佛能够稍微的松动一点点。react-native

何时咱们会选择缩写?

为了避免一开始引出结论引发你们的抵触情绪,我先谈谈在什么状况下咱们会选择缩写?设计模式

  • 生活中:KPI、IOS、CEO、活久见 ...
  • HTML: H一、em、a、br ...
  • JS: var、let、$、_ ...

总结一下,在特定环境中一些出现频率很是高的词组,为了使用方便,咱们会选择使用缩写。

仍是拿咱们以前的 JS 环境举例,像 getElementById 这个方法,在咱们实际开发过程当中,若是你就只用到 10 次左右,我想你并不会考虑去缩写它的问题。

但是当你发现使用它的频次达到了成百上千次的时候,即便你的编辑器,在你输入get 会为你联想出getElementById,你依然会考虑给这个单词取一个更短的名字。好比像这样:

function $(id){
    return document.getElementById(id);
}
复制代码

简单的来讲,咱们想要缩写就是它出现的次数是在是太多了。

语义化 CSS 不该该缩写

在 CSS 这个环境中,对于命名我相信你们听得最多的就是 语义化 这个词了。

对于 CSS 语义化 我比较佩服的就是 禅意花园 了。做者就写了一个 DOM 结构和一些 CSS 类名,而后成百上千的人就能基于他这些 CSS 类名,彻底不须要修改任何的 DOM 结构,就能写出和做者样子彻底不同的页面。这就和换皮肤同样,结构和样式的完美分离。

因此这里仍是要声明一下,对于语义化的命名,我就很是不推荐使用缩写

那么除了 语义化 还有什么可选的 CSS 命名方式呢?

这个问题我相信大多数的前端开发者仍是很难回答的。由于在从业多年以后,我发现一直坚信的 CSS 语义化 是致使我写 CSS 效率低下最根本的缘由。由于命名就是一个须要花费不少时间的东西。具体能够看看我以前写的其它 CSS 相关文章 《如何管理 CSS “内裤”》

基于 CSS 类名能够缩写的这个点,我给到的答案是 ACSS (Atomic CSS),固然这里说 ACSS 是一种命名方式是极为不许确的。

若是你目前对于 ACSS 这个理念,表示不太容易接受的话,说明它不能解决你工做中的痛点。就把时间拿去打游戏或者和妹子聊天吧,后面的内容就能够忽略了。

为何 ACSS 能够缩写

ACSS 就如同它的名字来讲是原子化CSS。就是把的 CSS 的样式,拆分到原子级别。

简单的说,就是一个命名只有一行代码,一行代码只表示一个样式,是否是听起来特别符合设计模式中的单一指责?

语义化

.main-title{
    font-size:24px;
    line-height:32px;
    color:$color_primary;
    font-weight:700;
}
复制代码
<h2 class="main-title">这是主标题</h2>
复制代码

ACSS

.fontSize24{ font-size:24px; }
.lineHeight32{ line-height:32px; }
.colorPrimary{ color:$color_primary; }
.fontWeight700{ font-weight:700; }
复制代码
<h2 class="fontSize24 lineHeight32 colorPrimary fontWeight700">这是主标题</h2>
复制代码

语义化 Class 和 ACSS Class,被复用的几率基本不在是量级的。就拿上面的例子来讲,一个页面的 .main-title 个数能达到 10 个就已是一个很复杂的页面了。即便是在整站来看被复用的次数也是有限的。

ACSS 里面某些类名即便只是在一个页面被复用的几率,都是远高于语义化 Class 。好比说 font-size:14px;在一个项目中被复用上百次是很常见的事情。

因此 ACSS 里面的类名能够缩写的核心在于,ACSS 的类名被复用的次数是在是太多了。

CSS 如何缩写?

类名不能缩写有一个最核心反驳点在于,如何定义缩写的规则。不一样的人缩写的习惯是不同的。

首先咱们来看看,知名的一些解决方案对于缩写是如何定义的。

@bootstrap v4

{
    "bg-primary":"background-color:$primary;",
    "p-*":"padding: * ;",
    "m-*":"margin: * ;";
    "d-inline":"display: inline;",
    "sm":"small",
    "md":"middle",
    "col":"column",
    "btn":"button",
    "w-":"width:*;"
    /*...*/
}
复制代码

@material-ui

{
    "bgcolor":"backgroundColor",
    "zIndex":"z-index",
    "p":"padding",
    "m":"margin",
    "sm":"small",
    "md":"middle"
    /*...*/
}
复制代码

@张鑫旭老师

{
    "dn":"display:none;",
    "b":"font-weight:bold;",
    "cl":"clear:both;",
    "ovh":"verflow:hidden;",
    "ml10":"margin-left:10px;"
}
复制代码

相信看到这里,你和我同样是凌乱的。哪些能够缩写啊?是用连字符仍是用下滑线仍是用大小写啊?

不过咱们零乱的缘由在于咱们不在这些项目组里面。咱们没有在 material-ui 的项目里写 padding 写过上百次, 也没有在 bootstrap 项目里写 margin 超过成上千次,更没有像张老师同样有超过 10 年的页面编写经验。因此很容易有一些既定的思惟逻辑。

多年的工做经验,我也维护着这样一份枚举映射表。可是我也不得不认可,经过枚举映射的方式,对于新手来讲是很是高的。“汝之蜜糖,乙之砒霜” 就是这样一个道理。

为了解决这个问题,我花了不少的时间,进行着尝试,如下是我目前的结论(基本上是在张老师的逻辑上二次封装的)。

@个人方案

  1. 只取首字母: .db{ display:block; };
  2. 有数字直接链接: .mb10{ margin-bottom:10px; };
  3. 短横线表示负数: .mb-10{ margin-bottom:-10px; };
  4. 百分号用 p(percent)表示: .w100p{ width:100%; };
  5. 小数点用 d(dot)表示: .lh1d5{ line-height:1.5; };
  6. 链接参数(不容许缩写)用下划线: .c_primary{ color:$primay; };
  7. 对于非 ACSS 不要缩写或你们约定俗成的名称: .clearfix{ };

和其它枚举映射表最大不一样点在于,个人映射表是经过上面这套命名规则维系着的。

简单的说就是记忆上述这套命名规则会比记忆一整套映射表是更容易的。

而且命名规则会减小开发时候疑惑的几率。好比我如今须要一个背景颜色,若是没有命名规则,我就要去看一下映射表里面,是相似于 material 的bgcolor 仍是和bootstrap 同样叫 bg-。若是有明确的命名规则你就知道确定是叫 bc 由于只取首字母。

有一套命名规则,也比较便于其它的人往里面添加经常使用的类,而不是根据我的的习惯。固然要说服不一样的人定义同一套规则也是很难的,对于这个我只能说随缘吧。

<div class="pt16 pl16 pr16 pb16">
  <h3 class="fs16 lh24 fw700 mb4">Atomic css</h3>
  <p class="fs12 lh20">Atomic css 的开发体验真是太好了,速度也是超快。</p>
</div>
复制代码
<style> .card{ padding: 16px; } .title{ font-size:16px; line-height:24px; font-weight:700; margin-bottom:4px; } .content{ font-size:12px; line-height: 20px; } </style>
<div class="card">
  <h3 class="title">Atomic css</h3>
  <p class="content">Atomic css 的开发体验真是太好了,速度也是超快。</p>
</div>
复制代码

当别人还在纠结这个容器是叫 card 仍是叫 box 的时候,你的代码已经都写完了。当你熟练整个命名规则以后,在开发过程当中你会有种,你想要某个样式,而后你的代码就已经写完了的错觉。这个对于 开发体验 来讲是很是好的。

固然我这个方案也不并完美,仍是有些边边角角不能彻底覆盖,可是基本上平常基础的样式是彻底没有问题的。若是你有比我这个规则更少的命名方案,请和我分享。

若是你有使用 emmet 这个插件,你会发现你甚至连编写 css 的属性均可以是使用缩写的而后 tab 补全的。固然个人规则和 emmet 的有些不一样,可是不影响实际的使用。

自定义项目的样式库

ACSS 这个映射表和设计同窗的原子设计素材有很大的关系,甚至说,应该保持一致。好比说你的项目 A 全部的间距都是基于 5 的倍数开发的,那么你的这份映射表里就应该会有:

.mb5{ margin-bottom: 5px; }
.mb10{ margin-bottom: 10px; }
.pt10{ padding-top:10px; }
.pb10{ padding-bottom: 10px; }
/* ... */
复制代码

你的项目 B 全部的间距都是基于 4 的倍数开发的,那么你的映射表里就不该该有上面 5 的倍数的逻辑,而是:

.mb4{ margin-bottom: 4px; }
.mb8{ margin-bottom: 8px; }
.pt4{ padding-top:4px; }
.pb8{ padding-bottom: 8px; }
/* ... */
复制代码

若是你以为每次新项目都要去写这个很麻烦,能够推荐咱们这边封装的 Mixin 库,less 和 sass 都有 ui-system

对于了解 style-system 的朋友可能会发现,对于间距咱们并无采用相似于 style-system 中倍数逻辑( material-ui 和 bootstrap 是采用的这个逻辑 )。

$margins: [4px,8px,16px,24px,32px];
.mb-1{ margin-bottom:$margins[1]; }
.mb-2{ margin-bottom:$margins[2]; }
.mb-3{ margin-bottom:$margins[3]; }
.mb-4{ margin-bottom:$margins[4]; }
/*...*/
复制代码

简单的说,咱们以为这个很不直观。而且若是咱们要增长一个 20px 的间距,咱们的整个逻辑就会出现问题以前叫 mb-3的类名要换成 mb-4(固然 style-system 的逻辑应该是先定义好设计规范再开发,不该该在后期添加不符合设计规范的间距)。

然而实际每每是计划赶不上变化,因此还不如直接用数字来的直接简单粗暴,在开发的还不用思考。mb4就是 margin-bottom:4px; 不是什么 margin-bottom:$margins[4],你还不知道这个$margins 数组里面是啥。

样式不止 CSS

本文虽然一直是在围绕着 CSS 展开的,但其实我想说的实际上是 样式能够尝试考虑 ACSS, 而后 ACSS 的地方能够尝试考虑 缩写 这个点。

样式写多了的同窗会知道,经常使用样式的来来去去也就那几个,无非就是调整一下他们的排列组合。每次写这些重复的样式代码我就感受本身是在重复造轮子。

随着 JS 疯同样的发展,CSS-in-js 也正发热发光。但这并不影响咱们这整套逻辑。这里拿比较有名的 emotion 举例。

import react from 'react';
import "acss.scss";

render (<h2 className="fs24 lh32 c_primary fw700">{children}</h2>);
复制代码
import react from 'react';
import { css, jsx } from '@emotion/core';
const primary = 'blue';

render(
<h2 className={css` font-size:24px; line-height:32px; color:${primary}; font-weight:700; `}>这是主标题</h2>
);
复制代码

咱们甚至用原生的 CSS 就解决了 CSS-in-js 要解决的问题(对于这个点我就不展开了,你们能够思考如下为啥CSS-in-js 这样的理论恰好在组件化风行的时候出现?)。

若是你想在 React-native 中也使用以上的开发体验。能够去看一下咱们这边针对于 React-native 开发的 ACSS 组件 @_nu/react-native-acss

import React from 'react';
import {Text, View, ImageBackground, Image} from './packages/withAcss';
import mImg1 from "./assets/1.jpg";
import mImg2 from "./assets/2.jpg";

export default function App() {
    return (
        <View bc="#f5f5f5" pt={100} ph={30} h="100%"> <View mb={16} aic> <Image br={32} w={64} h={64} source={mImg1}/> </View> <Text c="#ffffff" p={16} bc="#4c5fe2" tac mb={16}>Hello world!</Text> <ImageBackground source={mImg2} mb={40}> <View bc="rgba(255,255,255,.8)"> <Text fs={40} lh={100} tac fwb c="#4c5fe2">Hello Again!</Text> </View> </ImageBackground> </View> ); }; 复制代码

想要实现上面的效果,只须要这几行代码,你能够对比如下以前无论是用styleSheets 仍是用 style-components 的代码量。就知道这个是多么的酣畅淋漓。

最后

本文一开始虽然只是想解释,CSS 类名能够缩写这一个点。但到最后仍是难免我介绍了我钟爱的 ACSS,并王婆卖瓜的推荐了三个工具。毕竟是花了本身不少心力,仍是但愿能被更多人看到和使用。

  1. ACSS: ACSS 命名规则;
  2. ui-system: 自定义 ACSS 基础库构建工具;
  3. @_nu/react-native-acss:react native ACSS 组件;

本文观点属于经验总结,走的是务实的逻辑,可能实现方案看起来有点丑陋。

可是不能解决问题,优雅又有何用呢?有什么疏漏,还请你们海涵,能够给我留言指正。

解决方案

更新于 2019/10/22

名称 NPM github CDN
@_nu/css-acss
npm package
github
jsdelivr

讲了这么多,感受都只是空谈理论。这边我多年的使用经验,总结的一个 ACSS 的 npm 类库 @_nu/css-acss 供你们使用。

对于 ACSS, bootstrap, material-ui, github ... 都有相关的 类库,而后整个 ** 类库** 最完善的属于 tailwindcss。固然他们都是基于 style-system 理论建立的。上手成本相对较高,且每每须要设计师的介入。

和这些项目相比,我这边的方案,优势在于简单和极致的 CSS 开发体验。简单到整个逻辑只落点在命名规则,看完文档 5 分钟就会用,甚至彻底理解全部的逻辑。极致的 CSS 开发体验,体如今熟悉这套规则以后,你会开始怀疑,你的手指速度慢于你思考 CSS 的速度。

固然为了追求简单和开发体验这也是缺点,就是不够完善,没有处理相似 hover,focus... 等中间态,也没有添加任何自定义的响应点。这部分须要你们基于本身项目和 命名规则 自由扩展。

相关文章
相关标签/搜索