写 SCSS 代码应该遵循的原则

KISS – Keep It Simple Stupid

“Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.”
– Martin Golding

keep sass simple,不要写过度抽象,不要用复杂的语法实现简单的功能。实际上 css 文件不需要很复杂。有了预编译以后,稍不注意就产生过多的层级、巨复杂的选择器了。还有滥用函数,一点点重复都抽象出来。

正确的做法是有逻辑关联的样式才合并到一起。语义上有继承关系的样式,才使用继承。相关的代码不要分散到几百行之外。

DRY – Don’t Repeat Yourself

scss 的变量,extend,mixin 就是为了做这个的。mixin 会生成重复的代码,但是符合 Single source of truth 原则。DRY 不是不让重复(don’t repeat)而是为了保证源头只有一个,源代码只出现在一处,一次修改自动同步到所有的CSS文件。CSS中,机器自动复制出来的的重复,不破坏 DRY 原则。

参考资料:

Single source of truth https://en.wikipedia.org/wiki/Single_source_of_truth
DRY Don’t repeat yourself https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
KISS https://en.wikipedia.org/wiki/KISS_principle
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live

学这些名词有什么用?这些简洁的词,有公认的含义。跟别人交流的时候,提到这个词就明白对方在说什么。就像是成语一样,方便交流。

完成更多事情的拖延症患者

拖延症最典型的症状就是,其它的事情都好有趣啊!

不想做的事正好是最重要,最需要做的。准备开始时,甚至在心里一想起要开始做,就会有别的事出来打岔。

呵呵,解决方法呢,要是 Todo list 够长的话,总会挑出来现在想做的事,去做出来,再打勾,是不是心情好多了?

就算是拖延症患者,永远不做“最”重要的那件事,做下面相对不那么难的,更有意思的事,说不定能完成更多条目呢。

嗯,没必要从上到下开始的。

再说,拖下去,优先级可能会变呢,原来永远不会开始做的事,说不定就变成有趣的事了。

使用 Mixin 性能更好

原文链接: Mixins Better for Performance
本文已获得原作翻译授权,转载译文时请附上原文链接以及译文链接,未经允许不得随意转载译文
译文链接:使用 Mixin 性能更好 
翻译:于坤

谈到预处理器,最常见的问题就是用 @extend 还是 mixin?我一直强烈支持一个观点,尽量不要用 @extend,原因有很多:

1,它会改变你的 css 顺序,有潜在风险
2,它会产生尴尬的分组,将无关的选择器放到一起
3,它很贪婪,@extend 会继承每一个实例,而不仅仅是你真正需要的那个
4,它会让你的代码很快失控(图1图2

现在,因为 @extend 不符合设计模式,奇葩用法逐渐减少,令人欣慰,但我觉得还是不够。

昨天跟一个客户讲课时,提到 @extend。我回答,永远不要用 @extend!客户说,但是 @extend 性能更好啊,生成更少的代码。

确实 @extend(正确使用的话)会产生更少的代码,但是我的回答依然是,不,mixin 对性能更好

就算没有测试,我也能很自信的这样回答,因为我的理由很充分:

因为 gzip 偏爱重复的内容,所以1000个重复的声明,比1000个不同的声明有更好的压缩率。

大家在说性能的时候,通常都是在说文件大小,但我们开启了 gzip 压缩以后(你也开启了吧?),就应该考虑网络传输中的文件大小。

我的想法是,我们用 gzip 压缩 css 以后,含有更多重复字符串的文件,比基本上没有重复内容的要小很多,无论原来的 css 文件大小怎样。我断定,大一点的,但是重复内容更多的文件,压缩后更小。

回到酒店我测试了一下我的理论。

实验

我的步骤是这样的

1,创建两个css文件
2,每个文件都有1000个不同的 class,用 sass 生成

@for $i from 1 through 1000 {
  .#{unique-id()}-#{$i} {
    ...
  }
}

3,我给每一个 class 一个独立的声明,用类名加随机字符串,生成无意义的名称和选择器。

@for $i from 1 through 1000 {
  .#{unique-id()}-#{$i} {
    content: "ibf#{&}jaslbw";
  }
}

4,然后选择三个常见的 css 声明,给这1000个 class 共用:

color: red;
font-weight: bold;
line-height: 2;

5,一个用 mixin 共享这三句样式声明

@mixin foo {
  color: red;
  font-weight: bold;
  line-height: 2;
}
   
.#{unique-id()}-#{$i} {
  @include foo;
  content: "ibf#{&}jaslbw";
}

6,另外一个用 @extend 共享

%foo {
  color: red;
  font-weight: bold;
  line-height: 2;
}
   
.#{unique-id()}-#{$i} {
  @extend %foo;
  content: "ibf#{&}jaslbw";
}

测试代码都在 github(https://github.com/csswizardry/extend-vs-mixin)

这样生成了两个文件,每个都有1000个独立的 class,1000个独立的声明,还有分别用两种方法共享三条 css 规则。文件谁大谁小应该不出所料:

– mixin.css 108K
– extend.css 72K
– 两个文件的差距有 36K
使用 mixin 产生的文件是使用 @extend 的150%

这跟我的期望一样,mixin确实比 @extend 产生的文件更大。但是!我们不用担心文件系统中的文件大小,而应该关心 gzip 压缩后的文件大小。我用gzip压缩后:

– mixin.css 12K
– extend.css 18K
– 两个文件相差 6K
使用 mixin 比 @extend 减少了33.333%的文件大小。

差距惊人!一开始 mixin 是 @extend 的1.5倍,现在却比 @extend 小 0.3倍。我的理论是对的!

让测试更真实

我认为上面的测试很公平,类名用独特的字符串阻止压缩,这样更能提现共享规则的压缩效果。也就是说,这个测试太理想,不真实。所以我决定做更有说服力的测试,从真实的项目中拿出编译后的 css 文件,复制两份,然后分别 @import 刚才生成的两个测试文件。这时我的测试文件和1794行真正的、实际项目里正在用的 css 放在一起。生成的测试文件如下:

– mixin.css 16K
– extend.css 22K
– 两个文件差距是 6K
使用 mixin 比使用 @extend 小27%。

绝对数字微不足道(才6K)但是相对值却是节省27%的宽带,做的调整仅仅是用 mixin 生成重复的声明,代替用 @extend 生成重复的选择器。

使用 mixin 性能更好

我的测试显示,mixin 最终比使用 @extend 网络性能更好,未压缩时更大的文件,gzip 的工作原理也让它们变得更节省宽带。这表明 @extend 并没有性能优势,加上它对 css 的坏处,请不要再用它了。

 

原文链接: Mixins Better for Performance
本文已获得原作翻译授权,转载译文时请附上原文链接以及译文链接,未经允许不得随意转载译文
译文链接:使用 Mixin 性能更好 
翻译:于坤

何时用 @extend 何时用 Mixin

原文链接: When to use @extend; when to use a mixin
本文已获得原作翻译授权,转载译文时请附上原文链接以及译文链接,未经允许不得随意转载译文
译文链接:何时用 @extend 何时用 mixin
翻译:于坤

何时用 @extend 何时用 mixin,这是我常被问到的一个问题,有些过时的经验说,不带参数的 mixin 不好,生成的结果中到处都有重复的代码,有点脏。事实比这个说法更微妙,下面详细说。

何时使用@extend

开门见山的说,我的建议是不要用 @extend。

就像是傻瓜的黄金(fool’s gold, pyrite, iron pyrite 黄铁矿,一个金色矿物的通称。因为黄铁矿类似于黄金的颜色,它常常被误认为是真材实料。由于黄铁矿相对一钱不值, 因此才有这个词。)它有非常多的约定和更多的注意事项。

如果你确定一定以及肯定要用 @extend,请:
1,再考虑一下
2,尽量用占位符 placeholder
3,注意编译后的内容

理论上来说,@extend 很棒,但实际应用中,太多地方容易出错了。我看过让样式文件变两倍多的;看过源码顺序被破坏;看过触发 4095 选择器 bug。

Internet Explorer 6 to 9.
– A sheet may contain up to 4095 rules
– A sheet may @import up to 31 sheets
– @import nesting supports up to 4 levels deep

IE10 (any browser/document mode):
– A sheet may contain up to 65534 rules
– A document may use up to 4095 stylesheets
– @import nesting is limited to 4095 levels (due to the 4095 stylesheet limit)

 

这类特性或者工具,带来的好处不明显,一旦出错却会造成很大麻烦的,使用时应该慎之又慎。如果你需要把样式表拆分才能避免4095个选择器bug,说明你用的这个工具非常不合理。

声明:我觉得我有必要说明一下,我不恨 @extend,只是觉得要正确使用它,要警惕,有很多注意事项。

如果你真的要用,何时使用呢?

很重要的一点,@extend 创造层级关系。使用时,你是在把别处的样式和层级关系,移植到另外的层级关系。结果所有这些选择器都产生了关联,错误的使用 @extend 会产生错误的层级。就像你用颜色排列收藏的CD一样,可行,但是这种关联没什么用。

至关重要的是,要让正确的特性产生关联。

经常有人写出这样的代码,我自己以前也这样写(假设…代表100行代码):

%brand-font {
font-family: webfont, sans-serif;
font-weight: 700;
}

...

h1 {
@extend %brand-font;
font-size: 2em;
}

...

.btn {
@extend %brand-font;
display: inline-block;
padding: 1em;
}

...

.promo {
@extend %brand-font;
background-color: #BADA55;
color: #fff;
}

...

.footer-message {
@extend %brand-font;
font-size: 0.75em;
}

生成的结果如下:

h1, .btn, .promo, .footer-message {
font-family: webfont, sans-serif;
font-weight: 700;
}

...

h1 {
font-size: 2em;
}

...

.btn {
display: inline-block;
padding: 1em;
}

...

.promo {
background-color: #BADA55;
color: #fff;
}

...

.footer-message {
font-size: 0.75em;
}

这里的问题是,我强制把相隔数百行,完全不相关的规则放到一起,让这些规则产生了没必要的联系。只是碰巧都用了同一段样式规则,就让代码优先级变得非常跳跃,非常不好。

把选择器移动到几百行代码之外的不恰当位置,只是为了与不相关的代码共享一段规则,这不是 @extend 的正确用法(实际上,这正是典型的不带参数的 mixin 的应用场景,后文会详细说)。

另一种 @extend 的错误用法,看起来如下:

%bold {
font-weight: bold;
}

...

.header--home > .header__tagline {
@extend %bold;
color: #333;
font-style: italic;
}

...

.btn--warning {
@extend %bold;
background-color: red;
color: white;
}

...

.alert--error > .alert__text {
@extend %bold;
color: red;
}

产生的结果如下:

.header--home > .header__tagline,
.btn--warning,
.alert--error > .alert__text {
font-weight: bold;
}

...

.header--home > .header__tagline {
color: #333;
font-style: italic;
}

...

.btn--warning {
background-color: red;
color: white;
}

...

.alert--error > .alert__text {
color: red;
}

产生的代码有299 bytes

你本来想避免重复,结果却可能产生更长的代码。

如果每次都把这句 font-weight: bold; 写出来的话,代码只有 264 bytes。这只是一个很小的测试,但也说明了这样做收益会递减。@extend 只继承一句样式,结果可能会适得其反。

那么,到底何时使用 @extend 呢?

用到真正有联系的规则上,一个完美的用法如下:

.btn,
%btn {
display: inline-block;
padding: 1em;
}

.btn-positive {
@extend %btn;
background-color: green;
color: white;
}

.btn-negative {
@extend %btn;
background-color: red;
color: white;
}

.btn-neutral {
@extend %btn;
background-color: lightgray;
color: black;
}

生成的结果是:

.btn,
.btn-positive,
.btn-negative,
.btn-neutral {
display: inline-block;
padding: 1em;
}

.btn-positive {
background-color: green;
color: white;
}

.btn-negative {
background-color: red;
color: white;
}

.btn-neutral {
background-color: lightgray;
color: black;
}

这才是 @extend 的正确用法。css 规则有继承关系,它们共享同样的样式,是因为一样的理由,而不是因为巧合。而且,也不会让同一个选择器分散到几百行以外。

何时使用 mixin

“不带参数的 mixin 不好”这个经验,有他对的一面,但也不是这么简单。

这句规则误解了DRY原则,DRY的目标是在一个项目中保持单一真实数据源,是在说不要重复你自己,不是完全不重复。

如果你手写50次同样的声明,你是在重复你自己,这不符合DRY原则。如果你用程序生成50次,自己没有重复写,这符合DRY原则。你只是用程序生成了重复的内容,但是没有重复你自己。这是一个相当微妙但重要的区别,编译出来的重复不是坏事,在源处重复才是坏事。

单一真是数据源的意思是,把重复使用的数据源保存到一个地方,不用复制就可以回收和再利用。当然了,系统可能帮助我们重复了,但是它的来源只有一个。这意味着我们可以只修改一次,变化就自动同步到所有地方;我们的源代码没有重复,是唯一的真实数据源,这就是DRY的原则。

考虑到这一点,我们就可以想到,没有参数的 mixin 也可以非常有用。来重新看一下 %brand-font{} 这个例子。

假设有些地方必须用特定的字体和加粗:

.foo {
font-family: webfont, sans-serif;
font-weight: 700;
}

...

.bar {
font-family: webfont, sans-serif;
font-weight: 700;
}

...

.baz {
font-family: webfont, sans-serif;
font-weight: 700;
}

加粗的700不是常用的 regular 或 bold ,在代码中一遍又一遍的手写这两句声明很繁琐乏味。如果我们需要修改字体或者加粗,就需要搜遍整个项目,在每个地方都修改。

前面已经介绍了这种情况不应该用 @extend,可能我们应该做的是用 mixin:

@mixin webfont() {
font-family: webfont, sans-serif;
font-weight: 700;
}

...

.foo {
@include webfont();
}

...

.bar {
@include webfont();
}

...

.baz {
@include webfont();
}

是的,这里会产生重复,但是我们没有重复自己。这点很重要,这些规则之间没有逻辑关系,不应当产生关联。他们没有任何关系,只是碰巧都使用了同一段规则。所以这里的重复很合理。我们希望把这些声明用在 n 个地方,所以他们出现在了 n 个地方,也符合预期 。

无参数的 mixin 非常适合重复的吐出同一段规则,同时保持单一真实数据源。 这里 sass 就像在自动从剪贴板拷贝/粘贴一样。我们有单一真实数据源,我们可以只修改一次,处处生效,非常DRY。
(这里提醒一下,Gzip更适合重复的内容,所以轻微增加文件大小的缺点完全可以忽略)

当然,带参数的 mixin 非常适合生成值不固定的结构。这种用法既DRY,又保持单一真实数据源,还能自动生成,举例:

@mixin truncate($width: 100%) {
width: $width;
max-width: 100%;
display: block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}

.foo {
@include truncate(100px);
}

生成相同的声明,但是宽度值不同,正是 mixin 的典型用法。这是最常见,也是广泛推荐的 mixin 用法。在这点上我们意见都一致。

总结

当你想 DRY 的地方真正有继承关系,或者在主题上相关的时候,才用 @extend。不要强行把代码放到一起,这样会让代码分组不合理,源码顺序也会被打乱。

需要给相同的结构设置不同的值,或者想让 sass 代替你复制、粘贴的时候使用 mixin,这样写仍然会保持单一真实数据源。

总结的总结

@extend 有理由才用,mixin 喜欢就用。(Use @extend for same-for-a-reason; use a mixin for same-just-because.)

参考资料:

Extend 尽量用占位符 http://csswizardry.com/2014/01/extending-silent-classes-in-sass/
IE 4095 选择器 bug http://blogs.msdn.com/b/ieinternals/archive/2011/05/14/10164546.aspx
CSS 优先级图示 http://csswizardry.com/2014/10/the-specificity-graph/
单一真实数据源 https://en.wikipedia.org/wiki/Single_source_of_truth
tl:dr Too long; didn’t read. https://en.wiktionary.org/wiki/TL;DR

原文链接: When to use @extend; when to use a mixin
本文已获得原作翻译授权,转载译文时请附上原文链接以及译文链接,未经允许不得随意转载译文
译文链接:何时用 @extend 何时用 mixin
翻译:于坤

网页的几种编码方式GB2312、GBK、GB18030?

chrome 内置的编码方式,适用于中文的有

Unicode(utf-8)
(简体)GBK
(简体)gb18030
(繁体)BIG5

但是没有多年前常用的设置 gb-2312。
如果网站设置的编码方式是 <meta charset="gb-2312" >
浏览器会自动选择一个编码方式,有可能是gb18030,这时候显示正常,也有可能是其他编码方式,页面里的中文就会显示为乱码。

=====

科普:GB2312、GBK、GB18030 这几种字符集的主要区别是什么?

GB 2312 或 GB 2312-80 是中国国家标准简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,又称GB0,由中国国家标准总局发布,1981年5月1日实施。GB2312编码通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持GB 2312。

GB 2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。

GBK
GBK即汉字内码扩展规范,K为汉语拼音 Kuo Zhan(扩展)中“扩”字的声母。
包含了GB2312中的全部汉字、非汉字符号。BIG5中的全部汉字。

GB18030与GB 2312-1980完全兼容,与GBK基本兼容,支持GB 13000及Unicode的全部统一汉字。