深入浅出CSS3 background-clip,background-origin和border-image教程


很久以往 Roger Johansson 就在他的 blog 上做了一个 用 款式操纵表单元素 的测试 , 告诉我们 用意用 款式操纵表单元素是一件不可能的 事件using CSS to style form controls to look exactly the same across browsers and platforms is impossible
甚至 css2.1 标准中也没有明确这方面的规定 , 而是打算将它 fix in future
CSS 2 . 1 does not define which properties apply to form controls and frames, or how CSS can be used to style them. User agents may apply CSS properties to these elements. Authors are recommended to treat such support as experimental. A future level of CSS may specify this further.

所以假如想要让表单元素在各个阅读器下 彻底 统一 , 最好的解决 步骤莫过于 彻底不 理睬操作系统的 款式 , 用自定义的 ui 格调 , 就像 bing 或 Google 的 Jazz UI 那样

 

CSS


 

但是 , 这会招致界面和消费者的系统格格不入 , 当前 google 重要还是针对阅读器做了些特殊 解决 , 如 webkit 下用 gradient 使得按钮看上去好些
 

CSS

 

mac 下 webkit 的按钮不好操纵

 

CSS


 

本文 迁就输入框高度的问题进行调研 , 寻觅更好的解决 步骤
输入框高度
首先 , 这个调研的一个重要缘由是 , 查找 后果页打算进入 标准模式 , 这会招致盒模型的 变迁 , 造成输入框高度和原来不一样 , 所 认为了和线上 动机 维持 统一 , 我们需求找到一个最佳的解决 方案
有同学可能会不解 , 有那么难么 ? 设置一个 height 不就解决了么 ?
<input type= "text" style= "height:28px" />
但是 , 经测试发现这里面的细节问题还是还挺多 , 因为资源有限 , 这里只测试了重要的阅读器和平台 , 包含当前重要用到的 5 个阅读器
·         IE6(xp)
·         IE7(xp)
·         IE8(win7)
·         Firefox 3.5(xp)
·         Firefox 3.5(win7)
·         Firefox 3.5(mac 10.6.2)
·         Firefox 3.5(ubuntu 10.4)
·         Chrome 5(xp)
·         Chrome 5(win7)
·         Chrome 5(mac 10.6.2)
·         Chrome 5(ubuntu 10.4)
通过设定 height 的 模式
我们的 指标是和当前查找框大小 维持 统一 , 既 28px
首先测试的是最 容易的 height, 先看当 火线上的 方案 ( 容易起见就直接写到 style 中了 )
<input type= "text" style= "font: 16px arial; height: 1.78em; padding-top:2px" />
从 款式上推导 , 因为盒模型问题 , 在 IE 下的大小将是 1.78 * 16 = 28px, 而 Firefox 等阅读器应该是 1.78 * 16 + 2px + border-width * 2 = 30 + ? px
测试 后果是
阅读器  height + padding-top + padding-bottom + border-top-width + border-bottom-width 
IE6(xp)  21 + 2 + 1 + 2 + 2 = 28 
IE7(xp)  21 + 2 + 1 + 2 + 2 = 28 
IE8(win7)  21 + 2 + 1 + 2 + 2 = 28 
Firefox 3.5(xp)  21 + 2 + 1 + 2 + 2 = 28 
Firefox 3.5(win7)  23 + 2 + 1 + 1 + 1 = 28 
Firefox 3.5(mac 10.6.2)  19 + 2 + 1 + 3 + 3 = 28 
Firefox 3.5(ubuntu 10.04)  19 + 2 + 1 + 3 + 3 = 28 
Chrome 5(xp)  21 + 2 + 1 + 2 + 2 = 28 
Chrome 5(win7)  21 + 2 + 1 + 2 + 2 = 28 
Chrome 5(mac 10.6.2)  21 + 2 + 1 + 2 + 2 = 28 
Chrome 5(ubuntu 10.04)  21 + 2 + 1 + 2 + 2 = 28 

动机相当 事实 , 全部阅读器都是 28px, 看来 即便是 Firefox 和 Chrom 在 quirks 模式下的 input 都没有遵照盒模型 , 所以线上的输入框高度在各个阅读器下很 圆满地 维持 统一
但是假如是在 standards 模式下 , 后果则是
阅读器  height + padding-top + padding-bottom + border-top-width + border-bottom-width 
IE6(xp)  28 + 2 + 1 + 2 + 2 = 35 
IE7(xp)  28 + 2 + 1 + 2 + 2 = 35 
IE8(win7)  28 + 2 + 1 + 2 + 2 = 35 
Firefox 3.5(xp)  28 + 2 + 1 + 2 + 2 = 35 
Firefox 3.5(win7)  28 + 2 + 1 + 1 + 1 = 32 
Firefox 3.5(mac 10.6.2)  28 + 2 + 1 + 3 + 3 = 37 
Firefox 3.5(ubuntu 10.04)  28 + 2 + 1 + 3 + 3 = 37 
Chrome 5(xp)  28 + 2 + 1 + 2 + 2 = 35 
Chrome 5(win7)  28 + 2 + 1 + 2 + 2 = 35 
Chrome 5(mac 10.6.2)  28 + 2 + 1 + 2 + 2 = 35 
Chrome 5(ubuntu 10.04)  28 + 2 + 1 + 2 + 2 = 35 

就仅仅加了一句 <!DOCTYPE html> , 却招致阅读器差距变得如此大 , 细心 视察发现 , 重要问题在 Firefox 上 它的 border 在 win7 下是 1 像素 , xp 下是 2 像素 , mac 下是 3 像素 , 令人很头疼 , 于是打算换一种 方案试试
padding 的 模式
因为 Firefox 的 border 问题 , 设定 height 是不可能 保障高度 统一的 , 除非推断再去推断操作系统类型 , 但那样做太麻烦了 , 并且说不定 mobile 版又不一样
那是不是 可以不通过设置 height 来操纵 ? 在当前的大查找首页也是 standards 模式 , 它是采纳 padding 的 模式来实现 28px 的高度的
<input type= "text" style= "font: 16px arial; padding:3px" />
这种写法的测试 后果是
阅读器  height + padding-top + padding-bottom + border-top-width + border-bottom-width 
IE6(xp)  18 + 3 + 3 + 2 + 2 = 28 
IE7(xp)  18 + 3 + 3 + 2 + 2 = 28 
IE8(win7)  18 + 3 + 3 + 2 + 2 = 28 
Firefox 3.5(xp)  19 + 3 + 3 + 2 + 2 = 29 
Firefox 3.5(win7)  19 + 3 + 3 + 1 + 1 = 27 
Firefox 3.5(mac 10.6.2)  20 + 3 + 3 + 3 + 3 = 32 
Firefox 3.5(ubuntu 10.04)  19 + 3 + 3 + 3 + 3 = 31 
Chrome 5(xp)  19 + 3 + 3 + 2 + 2 = 29 
Chrome 5(win7)  19 + 3 + 3 + 2 + 2 = 29 
Chrome 5(mac 10.6.2)  18 + 3 + 3 + 2 + 2 = 28 
Chrome 5(ubuntu 10.04)  19 + 3 + 3 + 2 + 2 = 29 

在不设定输入框高度的状况下 , 阅读器会自行指定一个 , 并且都有差距 , mac 上的 Firefox 更是高出了 4 像素 , 但总的来说 , 动机 固然不 圆满 , 但还是 可以 承受 , 大 部分状况下都只差一个像素
但是这种 步骤带来了众多不确定性 , 内容区的高度是随着字体大小而变的 , 假如 font-size 是 14px, 阅读器的高度又 维持 统一了
阅读器  height 
IE6(xp)  16 
IE7(xp)  16 
IE8(win7)  16 
Firefox 3.5(xp)  16 
Firefox 3.5(win7)  16 
Firefox 3.5(mac 10.6.2)  16 
Firefox 3.5(ubuntu 10.04)  16 
Chrome 5(xp)  16 
Chrome 5(win7)  16 
Chrome 5(mac 10.6.2)  16 
Chrome 5(ubuntu 10.04)  16 

是不是还有更好的 方案呢 ?
box-sizing
height 和 padding 都 无奈 圆满操纵输入框高度 , 而 border 的大小又不能改 , 难道就真的没 步骤了么 ? 不禁 惦记 quirks 模式下的容易 , 设定一个高度就 圆满了 , 要是能既进 standards 模式 , 又能用到旧盒模型就好了 , 很自然地就想到了一个 向来没用过的 css 属性 box-sizing, 以往向来没想好这属性到底能用在哪里 , 终于这下派上用场了 , 使用它我们就 可以解决 Firefox 下 3 种 border 的区别 , 让 Firefox 自己去算内容区的高度
但是因为 IE6/7 不 支撑这个属性 , 所以需求写 hack, 因为 IE 下的默许 border 值是 2, padding 是 1, 所以 height 需求减 6 像素 , 也便是
-moz-box-sizing : border-box ;
-webkit-box-sizing : border-box ;
box-sizing : border-box ;
height : 28px ;
* height : 22px ;
这样 , 就能 保障绝大 部分的阅读器下 动机 统一了 , box-sizing 属性的 支撑状况如下表所示 , 来自 mozilla 支撑的 拜访十分广 ,
Browser  Lowest Version  Support of 
Internet Explorer  8.0  box-sizing 
Firefox (Gecko)  1.0 (1.0)  -moz-box-sizing 
Opera  7.0  box-sizing 
Safari (WebKit)  3.0 (522)  -webkit-box-sizing 

不过 , 事件还没有 完毕 , 方才 假如了 IE 下默许 padding 是 1 像素 , 但是当前众多 css reset 都会将 input 的 padding 设为 0, 于是 , IE 下的差异将不是 6 像素 , 而是 4 像素 , 所 认为了幸免受到影响 , 提议将 padding 设为 0
padding-top : 0 ;
padding-bottom : 0 ;
height : 28px ;
* height : 24px ;
阅读器在 quirks 下的实现 步骤
回过头来看 Firefox 和 Chrome 在 quirks 模式下 使用了非 标准的盒模型 , 看样子是故意去做的 , 它是如何实现的呢 ?
于是在 webkit 源码中寻觅 , 一开始 认为它是在源码中对 quirks 下的 input 做了特殊 解决 , 但没看找到又什么特殊的地方 , 而在看到计算 box 高度的时候
int RenderBox::calcContentBoxHeight( int height) const
{
    if (style()->boxSizing() == BORDER_BOX)
        height -= (borderTop() + borderBottom() + paddingTop() + paddingBottom());
    return max( 0 , height);
}
蓦地想到 , 会不会是通过阅读器默许 款式来实现的呢 ? 将这种特殊的逻辑直接写在代码中 确切太恶心了 , 既然 支撑 box-sizing 属性 , 直接将它写在 quirks 的默许 款式不就 圆满解决了么
果然 , 在 Firefox 的 res/quirk.css 中发现了这句
/*
* Quirk: Use border-box box sizing for text inputs, password inputs, and
* textareas.  (b=184478 on why we use content-box sizing in standards mode)
*/
 
/* Note that all other <input>s already use border-box
sizing, so we're ok with this selector */
input :not ([ type = image ]), textarea {
  -moz-box-sizing: border -box;
}
在 webkit 源码中的 WebCore/css/quirks.css 发现了这句
/* This will apply only to text fields, since all other inputs already use border box sizing */
input :not ([ type = image ]), textarea {
    -webkit-box-sizing: border -box;
}
原来阅读器便是这么解决的 , 那么在 标准模式下用它将是一种 比较好的 方案
one more thing
不过这种写法在 Firefox 3.5 以下的版本会有个问题 , 那便是输入框内容将 无奈垂直居中 , 以英文为例 , 3.5 中和顶部的差距是 5 像素 , 而 3.6 是 7 像素 , 当前还没想到解决 方案
 

CSS

 

幸好在 Firefox 3.6 中解决了这个问题 , 并且 3.5 会默许 晋级到 3.6, 所以这个问题也就不需求考量了
论断
从这个例子 可以 苦楚地体验 , 假如没有统一的 标准 , 要兼容不同阅读器是如此的 困苦 , 并且这还仅仅是一个很不 彻底的测试 , 好在阅读器还是尽可能做到了最大兼容 , 比方 , 假如 windows 下默许主题和经典主题有区别 , 就 象征着全部 windows 下的测试都要乘 2.