12条鲜有人知的css事实(续集)【翻译】

 In 网页重构 on 2015-09-11 10:48:07 by 小刀

        此文为译文,作者在这篇文章中提到了12条我们前端人员在日常工作中不是特别熟悉而又确实可以使用或者浏览器是可以很好支持的CSS技巧,熟知这些点,对我们深入研究CSS有很好的帮助。

       鉴于本人英语水平有限,有些地方的翻译可能不是特别准确,或者不是很容易理解,在译文中,我也用括号的方式加了一些简单的算是注释的个人理解。各位读者也可以结合着原文去阅读,以便更好地理解作者所表达的意思!

       原文地址:http://www.sitepoint.com/12-little-known-css-facts-the-sequel/

       翻译:TGideas--johnsqliu

-----------------------------------------------------------------------------------------------

        一年前我发表了《12条鲜有人知的css的事实》,到今天为止,它已成为站点里最受欢迎的文章。那篇文章发表到现在,我已经为新的文章收集了更多css小技巧。我们都知道,所有成功的电影都应该催生出一部时髦的续集,对吧?


图片来自站点/Natalia Balska

      接下来,我们马上进入今年的开发者十二条。我能肯定的是,大部分人对这些多少都有些了解,但你们也可以在评论中让我知道哪些对你来说是陌生的。

1、 border-radius属性可以使用'/'(斜杠)标签 

      这是我四年以前在我的站点写的一些东西,但也行有些新手包括有经验的开发者,还是不太熟悉这些特性。
      不管你信不信,下边是有效的border-radius代码:
.box {
 border-radius: 35px 25px 30px 20px / 35px 25px 15px 30px;
}
      如果你之前没有见过这些,这里你可能会有一些困惑,所以这里有规范的解释:
     “如果斜杠/前后都设了值,那么斜杠前面的值就设定横向的圆角半径值,而斜杠后面的值就是设定纵向的半径值。如果没有斜杠的话,就把横向跟纵向的值设定为相等。”
     规范还提供了下面的图:

图片注释:“border-top-left-radius: 55pt 25pt 的两个值定义了这个圆角的曲率(弯曲度)
      所以,斜杠在值中的作用是让你创建不对称(横向跟纵向值)的圆角曲率。如果你想更详细地了解这些,请查看我上面原文的链接,或者,可以试一下MDN提供的方便互动的例子
 
      很多border-radius 生成器都是不允许你去设置这些项的值。这个MDN生成器是我发现的唯一 一个可以让你去修改的这些值的生成器。
 

2、使用bolderlighter相关关键字进行font-weight属性的定义

     正常来说你所看到的font-weight 属性的定义,它的值要么是normal要么是bold。你也偶尔能看到整数以整百为增量的值:100,200、、最大到900.
     然而,bolder跟lighter这两个值经常会被忘记。
     根据规范定义,这两个关键词指定了比继承值更粗或更细的值。它的出现会让你在处理一个比简单的‘bold’更粗一点或者比正常文 本更细一点的多种权重的字号的时候表现的更加明显。(这块可能会有点难理解,其实这里是跟字体本身有关联的,如果你的字体,比如例子中用到的‘Exo 2’字体中,因为这个字体最细为100,bolder一下就变成400,再bolder一下是700,其实它这个bolder跟lighter是有个固定跳到的数值的,只会匹配到400,700,900这样的值里,当你的继承值为100、200或300,bolder一下,这个bolder的值都会是400,继承值为900,800,lighter一下,这个值都一样会是700,所以两个关键字其实是只会是400、700、900三个值的)
      请看下边CodePen 的demo:
     在这个实例中,我使用的是一个有18款不同样式的Exo 2字体。我的demo中只使用了非斜体样式,这对整百为单位的字号权重来说已经足够了。
     这个实例包含了12层拥有不同font-weight 值的‘box’元素,引入‘bolder’和‘lighter’以便你能了解到字体的权重在不同的上下文继承中有什么样的效果。下面是实例中的CSS。注意代码中的注释,以及记住每一个后面的‘box’都是嵌套在前一层里面的。
.box {
 font-weight: 100;
}

.box-2 {
 font-weight: bolder; /* maps to 400 */
}

.box-3 {
 font-weight: bolder; /* maps to 700 */
}

.box-4 {
 font-weight: 400;
}

.box-5 {
 font-weight: bolder; /* maps to 700 */
}

.box-6 {
 font-weight: bolder; /* maps to 900 */
}

.box-7 {
 font-weight: 700;
}

.box-8 {
 font-weight: bolder; /* maps to 900 */
}

.box-9 {
 font-weight: bolder; /* maps to 900 */
}

.box-10 {
 font-weight: lighter; /* maps to 700 */
}

.box-11 {
 font-weight: lighter; /* maps to 400 */
}

.box-12 {
 font-weight: lighter; /* maps to 100 */
}
     在这个案例中,‘bolder’和‘lighter’关键词只会匹配到100,400,700和900的值。九种不同的状态,这两个关键词都不会匹配到200,300,500,600和800的值。
     这是因为你告诉浏览器在‘bold’和‘light’中去选择接下来的权重。所以它不会选择成最大或最小的权重,而是仅仅根据它所继承的选择一个相对粗或细一点的权重。但是,如果字体的最低权重是300(比如 Open Sans这个字体),而且上下文继承值是400,那么‘lighter’的值就会匹配到300.
     这个大家一开始可能会有些疑惑,但你可以反复折腾上面的demo去看这些关键词是怎么工作的。
 

3、关于outline-offset属性

       outline 属性由于它能够帮助调试而被众所周知(它不影响页面流)。规范上增加了一个outline-offset属性,它的作用完全跟它名字所表示的一样--让你定义它的外框线应该距离元素本身的偏移量。

     上面的demo中,通过拖动范围滑动条向左或向右来看外边框偏移量的改变。示例中的值从0px到30px,当然你完全可以通过css来想要多大就大。需要注意的就是,虽然outline属性是一个简写属性,但它不包含outline-offset属性,所以你每次都需要再单独定义outline-offset
     outline-offset属性唯一的缺点就是,它在IE浏览器(即使是IE11)中不起效 。
 

4、关于table-layout属性

     你可能会想,这是很老的信息了。我对display: table很熟悉,最早用来实现垂直居中的一种方法。但那不是我想说,注意我要说的是table-layout属性,而不是display属性。

 

     table-layout属性不像CSS的其他属性那样容易解释,所以我们还是先来看看规范是如何解释的:
"根据这个算法,table的横向布局不依赖于单元格的内容;它仅仅依赖于表格的宽度、列的宽度以及边框和单元格的间距"

      这可能也是W3C规范史上第一次出现这样很难理解的东西--LOL JK。

      结合一个生动的例子能更好地理解。在下列的demo中,该表格在css中增加了

table-layout: fixed。点击切换按钮去可以切换该效果关闭与打开。

     在上面的例子中,你可以看到使用table-layout: fixed 相对于默认的auto 值的优点。这可能并不总是最佳或者必须的选择,但当你在处理有可变宽度数据单元格的表格时,这是一个不错的选择。
     Chris Coyier去年为这个属性做了一个伟大的改进,所以如果你想要有一个更全面地认识,这是最好的资料。
 

5、vertical-align属性用在表格跟非表格中的时候表现不一样

      如果你在2000年或者更早就开始接触网站编程,或者你处理过很多HTML电子邮件的话,那么你可能会认为vertical-align 属性是对老的HTML4中valign属性一个在HTML5里过时的,不符合功能要求的标签)的一个标准升级。

     但在CSS中vertical-align 并不是起到那样的作用。除开表格,我认为这个属性更牛逼的地方并不在于表格中的表现。
     所以,这个属性被应用于常规的元素跟表格单元的时候有什么不一样的地方呢?
     当vertical-align 不是应用在表格单元的时候,它遵循下边这些基本规则:
  1. 它只在inline或inline-block元素中起效。
  2. 它对元素中的内容不起效,但能改变该元素相对于其他inline或inline-block元素的对齐。
  3. 它受文本/字体属性(比如行高line-height)或者相邻inline或inline-block元素的大小设置的影响。   
来看个实例:
     vertical-align属性定义在input元素上,通过点击相应的按钮,你可以改变vertical-align的值为按钮上对应的值。你会发现每个值都会改变input 元素的位置。
     这个实例可以初步地认识这个属性以及它对应的属性值。更进一步地了解,我们可以看一下 Christopher Aue’s 2014 post
       当它被应用到表格中的时候,vertical-align又表现的很不一样。在这个实例中,把这个属性或者属性值应用在一个或多个表格单元,表格单元的内容会被不同的属性值所影响。
      如上面实例所示,只有四个属性值在表格中起效,虽然左边这个单元设置了baseline 属性起作用,设置了vertical-align 的表格单元内的文本在对齐方式起主要的作用。
 

6、伪元素::first-letter比你想象中更灵活

       伪元素::first-letter可以给元素的第一个字母定义样式,让你实现在印刷中多年前就有的段落效果(drop-cap 印刷的书本中经常能看到的段落中的第一个字比其他字号要大的效果)。
       有个好消息就是浏览器快要出一个关于元素的首字母构成的标准了。我最早在 Matt Andrews的twitter上看到有关这个推文,虽然他仅仅是发推文吐槽::first-letter选择器很糟糕。下边来看下他在CodePen 的实例:
       四大浏览器对这个的处理结果都是一样的,所以我觉得这是一个正确的表现。但如果是括号的一半(‘(’)作为首字母的时候,这可能表现的有点奇怪。这更像是‘首字符’,所以我建议它作为一个新的伪类。
 

7、你可以在HTML class列表中使用无效字符作为分隔符

     这个概念是Ben Everard在2013年的时候提出,而且我认为它值得推广一下。Ben的观点是用斜杠去将他的HTML类名进行分组,以便他的代码能够更好地阅读或浏览。他的观点认为,转义斜杠是一个无效字符,浏览器会无视它。
     所以你的HTML实例可能是这样的:
<div class="col col-4 col-8 c-list bx bx--rounded bx--transparent">
     使用斜杠后,变成这样:
<div class="col col-4 col-8 / c-list / bx bx--rounded bx--transparent">
     你也可以使用任何字符(无效的或者空字符)去实现同样的效果:
<div class="col col-4 col-8 ** c-list ** bx bx--rounded bx--transparent">

<div class="col col-4 col-8 || c-list || bx bx--rounded bx--transparent">

<div class="col col-4 col-8 && c-list && bx bx--rounded bx--transparent">
     所有这些都是有效的,你也可以在下面的实例中去测试一下:
      这些我所指无效的分隔符不能作为你样式里的类名。所以下边的写法是错误的,所写的样式也不会起效:
./ {
 color: blue;
}
     你如果非要用这些字符在你样式里用来选中对应的html元素的话,你可以用工具把他们进行转义后再在CSS中进行使用,所以上面的例子如果这样写的话是可以生效的:
.\/ {
 color: blue;
}
    另外,Unicode 字符可以不用转义,这样的话你就可以做些像下边这样疯狂的尝试:
 
<div class="♥ ★"></div>
      对应的样式:
.♥ {
 color: hotpink;
}

.★ {
 color: yellow;
}
     当然,你也可以将这些字符进行转义,而不是直接将这些字符插入到页面中。下边的代码跟前面的代码块效果一样:
.\2665 {
 color: hotpink;
}

.\2605 {
 color: yellow;
}

8、动画重复的次数可以是带小数的值

      在写CSS关键帧动画的时候,你应该可以用animation-iteration-count 属性来定义动画重复执行的次数:
.example {
 animation-iteration-count: 3;
}
     这个例子中的整数值将会让这个动画重复执行3次。但你可能不知道这里我们可以使用小数值:
.example {
 animation-iteration-count: .5;
}
      在这个案例中,这个动画将执行半次(它会在第一次动画循环的中途停止)。我们来看一个两个球在页面上的动画案例,上面的那个球设置动画重复的次数为”1“,而下边的求的重复次数为”.5“
       更新:有评论指出,这个案例在PC或者手机版的Safari中不能正常执行。这是填充模式的相对关系中的一个bug, 我在这里写了个文档,这个bug现在已经被修复,这也会在以后稳定更新后改正过来。
      有趣的是,动画的迭代时间并不依赖于正在进行的懂行的属性或者某个值。如果你的某个物体运行100px,动画执行一半的点不一定正好是50px。比如上面的动画用的是linear 的timing效果,所以这个可以确定的是第二个球会刚好停在正中间的位置。
      下边这里我们用跟上面两个球同样的动画,但使用ease 的timing效果:
       可以看到,第二个球停在了正中间往后的位置,这是因为使用了不同的timing效果。
       如果你理解timing功能的话,你会发现使用ease-in-out 也会跟使用linear 一样让第二个球停在同样的位置。可以反复设置执行次数的小数值跟timing functions的值来看不同的效果。
 

9、动画名称会在动画的简写方式中影响动画的使用

     有些开发者可能已经发现了这一点,在规范中对这个也有个提醒。比方说,你有以下的动画代码:
@keyframes reverse {
 from {
 left: 0;
 }

 to {
 left: 300px;
 }
}

.example {
 animation: reverse 2s 1s;
}
注意这里我使用reverse作为动画的名称。简单来看,这并没什么不妥,但要注意当我们在用上面的代码作为一个例子时发生了什么:
       这段动画并不起效,因为‘reverse’是animation-direction属性的一个关键字。任何的动画名称在匹配到一个简写语法中的关键字值的时候都会发生这样的情况。但在普通写法中这样的情况不会发生(animation-name这样单独的动画名称写法的时候)。
     动画命名在简写语法中包含了任何定时功能的关键字 (比如infinitealternaterunningpaused 等等)都会被阻断。
 

10、使用样式选取元素列表中元素的范围

       我不知道是谁首先这样用的,但我第一次是在Gunnar Bittersmann 的这个demo 中看到的。比如说有一个20个元素的有序列表,你想选择第7到14个元素。这里你可以使用一个选择器来实现:

ol li:nth-child(n+7):nth-child(-n+14) {
 background: lightpink;
}
更新:在评论中有人指出,这个功能在Safari中不起效。幸运地是,Matt Pomaski 提出了一个解决方案:只需将选择器中的顺序换一下,变成这样:ol li:nth-child(-n+14):nth-child(n+7)。Webkit不能识别这种写法,所以你最终还是可以让它在Safari中正常运行。
      这个代码使用了链式结构的伪类表达式。虽然表达式有点难理解,但你可以通过表达式中的数字看到你想要选中的范围。
     更详细地解释这个工作的原理:在链式结构的第一部分,表达式为“选中第七个元素及后面的所有元素”。第二部分的意思是“选取第十四个元素及前面的所有元素”。但由于两部分是链接在一起的,每一个限制前一个的范围。所以链式结构的第二部分不允许第一部分超过第十四个元素,然而第一部分又不允许第二部分选取到第七个元素之前的元素。
     想更进一步了解这种类型的选择器和表达式,你可以阅读我以前的在这个主题的资料

 

11、伪元素也适用于一些空元素

     如果你跟我一样,尝试过把伪元素附加到一个图片或者表格input标签上。你会发现这样并不生效因为伪元素在非闭合元素上无效。我想很多开发者都认为空元素(即没有闭合标签的元素)都是这样的。但这并不正确。
     你可以将一些伪元素附加到一些不可替换的空元素上。这包含了hr 元素,如下边的例子:
 在例子中有颜色的区域是一个水平线(hr 元素),有::before 和::after 伪元素附加在这个元素上。有趣的是,在一个同样是不可替换的空元素br 上,却无法实现同样的效果。
     如果你疯狂到把meta标签和 link 元素设置为display: block ,你也可以给meta标签和 link 元素附加伪类,如下边例子所示。

     在例子中有颜色的区域是一个水平线(hr 元素),有::before 和::after 伪元素附加在这个元素上。有趣的是,在一个同样是不可替换的空元素br 上,却无法实现同样的效果。
     如果你疯狂到把meta标签和 link 元素设置为display: block ,你也可以给meta标签和 link 元素附加伪类,如下边例子所示。
 

12、有些属性值在选择器中是不区分大小写的

    这是一个不起眼的点,让他们通过下边的HTML来看:

<div class="box"></div>
<input type="email">

    你可以通过属性选择器来给他们两个添加样式,像这样:

div[class="box"] {
 color: blue;
}

input[type="email"] {
 border: solid 1px red;
}

      上面这样是没问题的,那下边这样呢?

div[class="BOX"] {
 color: blue;
}

input[type="EMAIL"] {
 border: solid 1px red;
}

      现在两个属性值都是大写的。在这个示例中,因为class 属性是区分大小写的,所以 .box 元素的样式不生效。而另外一个email的标签,却由于type 的属性值不区分大小写,所以它的样式能生效。这并非什么重大发现,只是一些你之前可能没留意到的。

 

总结

       这个希望不是那么俗气的续集到此结束了。
     感觉好像我每周都在学一些独一无二的CSS小技巧,也希望有些东西对大多人来说都是全新的知识。晦涩的CSS诀窍或技术,你更喜欢哪个?是否有一些特性或功能是你认为你不是特别了解但又是具有很好的浏览器支持的?请再评论中告知我们。

 

评论