@font-face 最佳实践

要想在网页上用一种好看的字体或者 iconfont,都离不开 @font-face,实际使用起来为了兼容各个浏览器,经常需要写一长串的 @font-face 定义,今天来研究一下 @font-face 定义的最佳写法。

浏览器支持情况

IE 6-8 仅支持 eot 格式,现代浏览器基本都能支持四种格式:otf、ttf、woff 和 svg,部分较老的版本可能只支持到 otf 和 ttf。其中 woff 是 W3C 推荐的字体格式。svg 主要用来兼容老的 iOS,如 iOS 4.1 及更早版本。现在应该几乎没人用这么老的 iOS 了吧,所以基本上 eot、ttf 加 woff 就可以很好地兼容目前的桌面和移动浏览器了。

更具体的支持情况可以上 caniuse.com 查询。

最佳实践

@font-face {
  font-family: "MyFont";
  font-weight: normal;
  font-style: normal;
  src: url("myfont.eot");
  src: url("myfont.eot?#iefix") format("embedded-opentype"),
       url("myfont.woff") format("woff"),
       url("myfont.ttf") format("truetype"),
       url("myfont.svg#myfont") format("svg");
}

声明中有两条 src 定义,第二条覆盖了第一条,所以浏览器都会先来读取第二个 src。跟 font-family 的查找一样,浏览器会逐个读取,找到一个支持的格式使用。eot 格式后面所附带的 ?#iefix 是针对 IE 6-8 的 hack。

IE 6-8 是不支持 format() 这种格式说明的,只会读取类似 src:url() 这样的格式,所以 IE 6-8 会把第一个引号到最后一个引号之间的内容都当做字体的 URL,结果就会返回一个 404。因此可以加上一个 ?,后面的内容就成为一个查询字符串,解决了 404 的问题。iefix 在这里是类似于注释的东西,你可以随便写。另外在一部分 Apache 服务器中,缺少了 # 会返回 403,所以再加上 #

阅读全文 »

z-index 层叠原理

z-index 这个属性,相信大家跟我一样,刚看到它的时候都觉得挺简单的,不过是 z 轴的值而已,越大就越靠前。但是实际用起来,往往又出现问题,得不到想要的结果。其实层叠的原理还是有必要深究一番的,至于如何搞清楚,最好的方法当然是看一看标准了。

首先,z-index 的值可以是 auto、整数或 inherit,默认值为 auto该属性只能用在定位元素上,也就是说,对静态定位元素使用 z-index 无效。当用户面朝显示器时,z-index 值越大的元素离用户越近,而具体的层叠规则,先要扯出一个概念:堆叠上下文(stacking context)。是不是联想到了块级格式化上下文(BFC)?在这我也将其简称为 SC 吧。

文档中的每个元素,都存在于一个 SC 中,根元素会生成一个根堆叠上下文(root stacking context),而对于其他元素,只有满足两个条件才会生成一个新的 SC:z-index 不为 auto 且必须是定位元素 (position 的值不为 staticSC 是可以嵌套的。

SC 是进行堆叠的基本单位。假如元素 A 生成了一个 SC,那么 A 的所有后代元素的堆叠顺序如下:

  1. A 的背景和边框
  2. z-index 为负值的各个 SC
  3. 静态定位的块级元素
  4. 静态定位的浮动元素
  5. 静态定位的行内元素,包括 inline table 和 inline block
  6. z-index 为 0 的子 SC,和 z-indexauto 的定位元素
  7. z-index 为正值的子 SC

其中顺序是由远到近的,即 1 在最下层,7 在最上层。需要注意的是,划分堆叠次序时,子 SC 内的元素都是作为一个整体参与堆叠,也就是各个 SC 中的元素不会串台,比如两个定位元素 A 和 B,z-index 值分别为 1 和 2,则 B 在 A 之上,并且 B 的后代元素,也都在 A 的后代元素之上。即使 A 中的某个后代设置了 z-index 为 9999,也会被 B 以及其后代所遮挡。所以说堆叠上下文是进行堆叠的基本单位,只有搞定了这一概念,才能理解元素是如何堆叠的。每个 SC 就像是一层楼,后代元素都处在这层楼里,不管后代有多高的 z-index 值,一楼的元素也永远不会遮挡二楼三楼的元素。
阅读全文 »

IE6 与 :hover 相关的一些 bug

IE6 的 :hover 伪类存在着一系列问题,简单记录:

只有 a 元素支持 :hover

这个想必是众所周知的,IE6 只能在 a 元素上使用 :hover,其他元素上无效。如果需要,可以通过 JavaScript 的 mouseovermouseout 事件来实现,或者 mouseentermouseleave,后一组事件是前一组的不冒泡版本。

:hover 规则不生效

假设如下的规则:

a span { color: green; }
a:hover span { color: red; }

在 IE6 中,第二条规则不会生效,鼠标指向 a 元素时,a 内的 span 不会变色。这是 IE6 的另一个 bug,如果某个链接没有定义 :hover 规则,直接定义 :hover 的子元素,那么子元素的样式不会生效。查看示例页面。解决办法是必须要定义 :hover,并加上一些特定的规则或造成样式上的改变,比如 padding:0,或 border:none,或 background:none 等。注意 a 元素必须要有 href 属性,否则 hover 也不会被触发。

/* 解决 */
a span { color: green; }
a:hover { padding:0; } /* 或 border:none  */
a:hover span { color: red; }

阅读全文 »

CSS属性之content

content 是 CSS 里面一个不太常用的属性,之前对它的了解不是很多,今天正好去 MDN 上查了一下,在此分享分享。

content 需要跟 ::before::after 伪元素搭配使用,用来向元素之前或之后插入内容。被插入的内容属于匿名的替换元素(replaced elements)。

说到伪元素顺便聊下关于冒号的疑问,以前书上都是用单冒号来表示的(:before),在 CSS3 中新引入了双冒号,目的是为了跟伪类相区分。浏览器也都兼容旧的写法,所以在 CSS3 以前的伪元素(:first-line, :first-letter, :before, :after)用单冒号或双冒号都可以,但 ::selection 是 CSS3 中引入的,必须用双冒号。

content 属性如果用在普通的元素上,值会自动转化为 normal
阅读全文 »

该用条件样式表还是CSS hack?

本文摘自Paul Irish的博客

针对IE的种种问题,通常有几种解决方案,一种是条件样式表,也就是结合IE的条件注释来加载专用的css文件:

<link rel="stylesheet" type="text/css" media="screen" href="css/style.css" />
<!--[if IE 7]><link rel="stylesheet" type="text/css" media="screen" href="css/ie7.css" /><![endif]-->
<!--[if IE 6]><link rel="stylesheet" type="text/css" media="screen" href="css/ie6.css" /><![endif]-->

还有许多人用的是CSS hack:

div.infoBox { float: left; margin-left: 10px; _margin-left: 5px; }

CSS hack 可以做到不影响其他浏览器的表现,坏处就是代码无法通过校验器的校验,因为hack是不合标准的CSS代码。所以条件样式表曾经备受标准化社区的推崇,因为既能解决问题,又可以通过校验。

但条件样式表也存在一些问题:

  • 条件样式表意味着会给IE增添了一到两个额外的HTTP请求。
  • 由于条件样式表存在于head元素中,浏览器会先下载样式表,增加了页面渲染的等待时间。
  • Yahoo内部的编码最佳实践中也不推荐使用条件样式表。
  • CSS文件被分割成了多个文件,增加了以后维护的难度。

所以Paul Irish的看法是,两种都不要用。同时他推荐了一种解决方案:

<!--[if lt IE 7]> <html class="ie6"> <![endif]-->
<!--[if IE 7]>    <html class="ie7"> <![endif]-->
<!--[if IE 8]>    <html class="ie8"> <![endif]-->
<!--[if gt IE 8]><!--> <html> <!--<![endif]-->

用条件注释来给html标签添加一个额外的类,这样所有的CSS都可以写进同一个文件:

div.foo { color: inherit;}
.ie6 div.foo { color: #ff8000; }

这种方法能够通过校验,也兼容各个浏览器。

Google HTML/CSS代码风格指南

本文翻译自Google HTML/CSS Style Guide

Google发布过各种编程语言的代码风格指南,今天看了一下关于HTML/CSS的,顺便整理翻译了下其中有用的东西,放在这里。Google的东西看一下还是会受益很多的,遵守这些规则,能够渐渐帮你形成良好的代码风格,同时在性能方面也很有益。留作参考吧。

通用风格守则

协议

把图片、媒体文件、样式表和脚本URL中的协议部分(http:,https:)省略掉,除非文件使用的不是这两种协议。这种方法使URL变成相对地址,可以避免混合内容的问题,同时略微地减少代码量。

【注:关于混合内容的问题(mixed content issues),可以看另一篇文章《关于URL中协议的省略》。】

<!-- 不推荐 -->
<script src="http://www.google.com/js/gweb/analytics/autotrack.js"></script>
<!-- 推荐 -->
<script src="//www.google.com/js/gweb/analytics/autotrack.js"></script>
/* 不推荐 */
.example {
  background: url(http://www.google.com/images/example);
}
/* 推荐 */
.example {
  background: url(//www.google.com/images/example);
}

通用格式化守则

缩进

使用两个空格来缩进。不要使用tab或者tab跟空格混合使用。

<ul>
  <li>Fantastic
  <li>Great
</ul>/
.example {
  color: blue;
}

大小写

所有代码都用小写字母,包括:元素名、属性名、属性值(除了text/CDATA)、选择器、CSS属性值,当然字符串中可以用大写。

<!-- 不推荐 -->
<A HREF="/">Home</A>
<!-- 推荐 -->
<img src="google.png" alt="Google">

末尾空格

去掉所有的末尾空格,它们是不必要的,有时候会带来麻烦。
阅读全文 »

CSS 属性值中的百分比

CSS 中经常会出现百分比单位,搞清它们的基数是件很重要的事情。我查了查 CSS2.1 标准,在此整理一下:

百分比的基数

乘以包含块的宽度

margin, padding, left, right, text-indent, width, max-width, min-width

乘以包含块的高度

top, bottom, height, max-height, min-height

对于包含块(containing block)这个概念,不能简单理解成就是父元素。分情况而言:如果元素为静态定位或者相对定位,包含块一般就是其父元素;但如果元素是绝对定位,包含块应该是离它最近的 position 为 absoluterelative、或者 fixed 的祖先元素。对固定定位的元素,它的包含块是视口(viewport)。具体可以参考 这篇文章

乘以元素的字体大小

line-height

乘以元素的行高

vertical-align

background-position 里的百分比

background-position 分别设置水平方向和垂直方向上的两个值,如果使用百分比,那么这个位移会同时应用于元素和图像。例如 background-position: 50% 50% 会把图片的(50%, 50%)这一点与元素区域的(50%, 50%)对齐,相当于设置了 background-position: center center。同理 background-position: 100% 100% 相当于 background-position: right bottom。如果只设置一个值,那另一个值自动设为 50%。

阅读全文 »

IE的CSS hack及条件注释

对于搞前端的同学们来说,实现跨浏览器的兼容,IE是一个大麻烦。可是鉴于低版本IE在国内不可忽视的占有率,我们还是需要好好掌握一些CSS hack。

总结了一些针对IE6-9的属性值hack:

.foo{
     color:green\9;    /* 所有IE */
     color:green\9\0;  /* IE9 */
     color:green \0;   /* IE9 */
     color:green\0;    /* IE8,9 */
    *color:green;      /* IE6,7 */
    +color:green;      /* IE6,7 */
    _color:green;      /* IE6 */
}

还有一种是选择器hack。对IE6可以用 * html ,如下

* html .foo{ color:green; } /* IE6可识别 */

对IE7可以用 *:first-child+html*+html

*:first-child+html .foo{ color:green; } /* IE7可识别 */
            *+html .foo{ color:green; } /* IE7可识别 */

微软推荐使用的方法则是条件注释。因为以上的hack并不是规范化的做法,无法通过 W3C 的 CSS 校验。条件注释的写法如下:
阅读全文 »

flight