阅读 1261

源码分析:如何定制Semantic-UI

SemanticUI简介

我来现在就职的这家公司之前,只使用过Bootstrap,并不知道SemanticUI。后来接手了现在的项目之后才知道有这么个框架。相比于盛行的Bootstrap,SemanticUI有它的值得使用的地方。

  • SemanticUI 像它的名字一样。更加语义化。
  • 默认的样式比Bootstrap好看很多,更加鲜明活泼。个人感觉。
  • 类名比Bootstrap短。并且更加离散。嵌套层级也少很多。

但是它有一个很让人头疼的缺点,就是对开发者的种种不友好。

  • 文档不够详细,很多模块的使用方法都是寥寥数语,或者放的地方很深。需要依靠你自己的编程经验去猜。
  • 模块定制并不像Bootstrap那样可以直接勾选自己需要的模块然后打包。在SemanticUI中,你必须在npm安装过程中选择要安装哪些模块。
  • yarn不友好。如上一条,npm中可以在过程中选择安装哪些模块。但是SemanticUI的安装脚本不被yarn所识别。必须yarn add semantic-ui --ignore-scripts才可以。添加了ignore-scriptes选项自然也就丧失了定制化的功能。由于我现在用的框架是RoR,默认使用的前端管理工具就是yarn,所以感觉很难受。

以上只是随便说了说SemanticUI与Bootstrap的区别,并不全面。因为这不是本文主要内容。

定制SemanticUI

有时候我们希望全局地定制SemanticUI。比如SemanticUI的默认字体大小为14px。而我们的项目默认大小为12px。在我接手项目的时候,诸如此类与框架提供样式相悖的样式都是直接在一个init.scss文件中进行覆盖来重置。感觉很丑,也会造成代码的冗余。

但是由于刚接手时并不了解SemanticUI,而且我身为一个前端程序员入职时居然直接让我上手开发Rails应用,手忙脚乱的我全身心都在学Rails根本没时间考虑这个问题。并且,在SemanticUI 官网中不能很容易地找到定制的方法(其实是有的,但是东一块西一块很难系统地贯穿起来)。所以我也就照着原来的样子做了这个项目一年。

init.scss中有些样式难以找到原来定义的地方,覆盖非常困难。chrome-dev-tool看穿了才会在一个六七行的选择器后面找到这个样式的定义,然后加一下权重进行覆盖 —— 就是再写一个六七行甚至七八行的选择器。不想再说了,痛苦。

最近老板发话了,要做前端的大改版。我终于有机会也有时间进行大重构了。过程可能会跟撕痂一样痛苦,但结果一定会跟撕完了一样爽

如何入手

我是在SemanticUI的Github的src文件夹中看到了这个README.md才知道怎么做的。

里面讲了一些如何重置SemanticUI默认样式,构建适合自己项目的SemanticUI的方法。我一眼就看到了底下的一些关键词resetfont size。惊呆了,原来在这。于是细细地读了起来。

这篇README讲了什么呢?

  1. 如何构建SemanticUI。直接gulp install
  2. 可以监控文件实时构建。gulp watch
  3. 配置文件的位置。
  4. 工作流。使用构建工具构建你专属的SemanticUI并在项目中直接使用构建完成的定制包。
  5. 主题化。
  6. 定制化。

我们要做的是定制自己的主题,自己的UI规范(字体大小,字体颜色,行高,一级二级三级主题色等等...)。所以我们可以先从5和6入手。

主题与样式的层级关系

主题的定义文件有一定的层级关系:

  1. SemanticUI的默认主题。就是什么也不设置一路回车然后直接构建直接使用的主题。
  2. SemanticUI提供的可选的预置的主题包。比如amazon主题或者material主题。
  3. 组件自有的主题。比如全局主题色是#f5f5f5,但是primary按钮组件自己的主题色是蓝色,则以蓝色为准。
  4. 你自己定制的主题。

某个元素应用的主题,是以上面四条倒序查找的。你自己定制的主题优先,没定制则寻找可选主题。如果没进行任何设置,则使用默认主题。

目录结构

以上的主题都是在哪里定义的呢?我们如何修改它?文中提到了目录结构。

  • src/definitions 文件夹中定义了每个组件使用的jscss
  • src/themes 中存放了SemanticUI提供的所有可用的主题。在我们构建时可以选择一个来使用。默认主题也在这里面。
  • src/site 你的专有主题。

源码验证

我们先打开src/semantic.less文件。在文件的最顶部有这样的语句:

& { @import "definitions/globals/reset"; }
复制代码

这里导入了一个reset文件到当前的semantic.less。我们来看一下reset中都有什么。首先,reset文件的顶部定义了两个变量,一个叫做@type一个叫做@element

@type    : 'global';
@element : 'reset';
复制代码

紧接着导入了主题配置文件:@import (multiple) '../../theme.config';。在这个配置文件中我们又看到了如下两个变量:

/* Global */
@site       : 'default';
@reset      : 'default';

...... ......

/*******************************
            Folders
*******************************/

/* Path to theme packages */
@themesFolder : 'themes';

/* Path to site override folder */
@siteFolder   : 'site/';
复制代码

注释写的很清楚了,是文件夹路径变量。分别是主题包路径和覆盖文件的路径。这两个路径在哪里被用到了呢?继续看这个文件,在最底部,引入了一个theme.less文件。该文件中有这样一段代码:

/*--------------------
   Site Variables
---------------------*/

/* Default site.variables */
@import "@{themesFolder}/default/globals/site.variables";

/* Packaged site.variables */
@import "@{themesFolder}/@{site}/globals/site.variables";

/* Component's site.variables */
@import (optional) "@{themesFolder}/@{theme}/globals/site.variables";

/* Site theme site.variables */
@import (optional) "@{siteFolder}/globals/site.variables";
复制代码

注释表明是网站变量。里面用到了上一个文件theme.config中定义的四个变量。指向了四个路径引入了四个文件。到这里你应该意识到了,我们重置样式的地方应该就在这些地方。

请注意这四个文件的顺序:

  1. default网站变量。
  2. 可选包网站变量。
  3. 组件自己的变量。
  4. 你自己定制的网站变量。

由于CSS的特性,层级一样的重复声明的样式是后盖前。所以以上文件以后面的为准。即,最权威的是你自己定义的样式。这与之前所说的主题层级的加载优先级是吻合的。

回顾一下theme.config。这里定义的变量:

/* Path to theme packages */
@themesFolder : 'themes';

/* Path to site override folder */
@siteFolder   : 'site/';
复制代码

我们便知道这四个路径都指到哪里了。既然以我们自定义的主题为准,那么我们直接看@import (optional) "@{siteFolder}/globals/site.variables";也就是site/globals/site.variables。里面空空如也,只有一句注释:用户全局变量。找到了!我们只要在这里重置样式就可以了。

定位到文件了,该如何书写呢?面对空空如也的文件无从下手?通常面对这种情况,最好的做法是看它默认的文件是怎么写的。

打开src/themes/default/globals/site.variables,看到下面几个代码片段,你就会茅塞顿开:

@fontName          : 'Lato';

......


@emSize   : 14px;

@fontSize : 14px;
......

@primaryColor        : @blue;
@secondaryColor      : @black;

......

复制代码

以字体大小为例,如果我们要更改我们全局的字体大小,以12px为基准。我们回到我们空空的site/globals/site.variables文件。添加如下代码:

@emSize   : 12px;

@fontSize : 12px;

复制代码

这样我们就完成了样式覆盖,使用12px作为基准字体大小了。

举一反三

我们已经会了如何定制全局的样式。那么一些特殊化的定制要如何完成呢?比如,全局字体大小为12px,但是产品和UI要求了,所有的按钮内字体都要是14px

其实根据上面的经验,我们的做法还是一样的。

首先打开src/site/elements/button.variables。熟悉的一幕又出现了:只有一句注释。再打开src/themes/default/elements/button.variables又看到了令人兴奋的片段(别想歪):

/* Button */
@verticalMargin: 0em;
@horizontalMargin: 0.25em;
@backgroundColor: #E0E1E2;
@backgroundImage: none;
@background: @backgroundColor @backgroundImage;
@lineHeight: 1em;
复制代码

咋整?回到那个空文件进行变量覆盖呀~就这么简单。

最后一步

已经对默认的样式进行覆盖了,是时候打包我们自己的SemanticUI了!

gulp clean
gulp build
复制代码

打包成功后使用时会发现,样式乖乖的都按规定走了。再也不用写七八行的选择器了。爽。再见了init.scss

讨论

有的人说了,既然都动了源码,干嘛不直接在src/themes/default/elements/button.variables改了算了。有两个原因不这么做:

  1. 不讲道理的原因:官方说了你最好在自己的重置文件里写。
  2. 因为你在自己的重置文件里写,知道自己重置了哪些样式,而直接修改原来的,就啥也不知道了。

学会了这种方式以后,你就可以基于SemanticUI进行“二次开发”,打造适合你的SemanticUI框架。

安利

丑爆手搭博客了解一下:http://qxchenblog.cn

文章分类
阅读