如何更好地控制input输入框的高度

所属分类: 网页制作 / CSS 阅读数: 476
收藏 0 赞 0 分享
很久以前 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 那样

然而 , 这会导致界面和用户的系统格格不入 , 目前 google 主要还是针对浏览器做了些特殊处理 , 如 webkit 下用 gradient 使得按钮看上去好些

mac 下 webkit 的按钮不好控制

本文将就输入框高度的问题进行调研 , 寻找更好的解决方法
输入框高度
首先 , 这个调研的一个主要原因是 , 搜索结果页打算进入标准模式 , 这会导致盒模型的变化 , 造成输入框高度和原来不一样 , 所以为了和线上效果保持一致 , 我们需要找到一个最佳的解决方案
有同学可能会不解 , 有那么难么 ? 设置一个 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 像素 , 目前还没想到解决方案

幸好在 Firefox 3.6 中解决了这个问题 , 而且 3.5 会默认升级到 3.6, 所以这个问题也就不需要考虑了
结论
从这个例子可以痛苦地体验 , 如果没有统一的规范 , 要兼容不同浏览器是如此的困难 , 而且这还仅仅是一个很不完全的测试 , 好在浏览器还是尽可能做到了最大兼容 , 比如 , 假设 windows 下默认主题和经典主题有区别 , 就意味着所有 windows 下的测试都要乘 2.
更多精彩内容其他人还在看

CSS配合JavaScript做酷的动态页面效果

  利用CSS配合JavaScript的可以做很多更酷的动态页面效果,在本教程的最后给大家简单介绍一下CSS配合JS的应用。首先,要搞清楚事件和动作的概念。在客户端脚本中,JavaScript 通过对事件进行响应来获得与用户的交互。例如,当用户单击一个按钮或者在某段文字上移动鼠标
收藏 0 赞 0 分享

WEB标准,Web前端开发工程师必备技术列表

  想要打造并拥有一流的Web产品开发团队,在团队成员基础能力上一定要下功夫。对于Web前端产品开发来说,仅仅掌握Web1.0时代简单的"网页套接"是完全不够的。我结合自己的团队配备,特此罗列了Web前端产品工程师所涉及的技能列表如下:   通过许多实际项目,
收藏 0 赞 0 分享

用CSS制作Alpha滤镜测试板

alpha滤镜给制作网页特效提供了较大的创作空间,但由于它控制参数较多,在实际应用时,为了确定一组合适的参数值,不得不反复调整修改,在编辑窗口和预览窗口来回倒腾,甚是麻烦,本文介绍了一种简单的方法。制作一个“Alpha滤镜参数测试板”,在测试板上输入参数
收藏 0 赞 0 分享

非常流行的所谓的气泡窗口

普通的Alt无法自定义风格,而Sweet Titles通过JS脚本与CSS的集合.自定义了这种伪Alt风格. 前一段时间非常流行的,就所谓的气泡窗口(鼠标移到链接处出现的). 我们这里实现的用的是Sweet Titles的插件.显示效果完全由CSS控制.. 先下载Sweet Ti
收藏 0 赞 0 分享

CSS教程:li和ul标签用法举例

LI代码的格式化: A).运用CSS格式化列表符: ul li{ list-style-type:none; } B).如果你想将列表符换成图像,则: ul li{ list-style-type:none; list-style-image: url(/blog/images/
收藏 0 赞 0 分享

CSS教程:CSS中的定位(position)

  使用CSS来定位页面内层的位置,一直是比较难以掌握的事情,很多时候,往往被绝对定位的元素,总是以浏览器的左上角为坐标原点,此时,如果浏览器的大小改变,被定义的层就会偏离设计想要的位置,让人很挠头。   其实,要想控制好层的绝对定位,只要理解CSS中关于定位
收藏 0 赞 0 分享

CSS教程:盒模型(BOX Model)

  如果想熟练掌握DIV和CSS的布局方法,首先要对盒模型有足够的了解。每个HTML元素都可以看作一个装了东西的盒子,盒子里面的内容到盒子的边框之间的距离即填充(padding),盒子本身有边框(border),而盒子边框外和其他盒子之间,还有边界(margin),如图1所示。
收藏 0 赞 0 分享

无延迟翻滚的图形与CSS混合风格按钮

  在一个具有图形背景的按钮中添加CSS风格的文本,这种建立按钮的方法结合了具有CSS翻滚(CSS rollover)标记的开发速度和效率,从而有效地提高按钮外表图像的三维效果。   相比于常规的图形按钮,这些图形/CSS混合按钮可易于建立和载入,因为你只需要为空白按钮外面
收藏 0 赞 0 分享

css里expression实现界面对象的批量控制

用过css样式我们就知道, 可以定义一批对象的class属性来指定同一个样式来统一界面. 但如何统一同类型的对象的事件? 比如:界面有无数个 <img src="**.jpg"> 如何实现鼠标经过此图片, 图片的src变成是**_over.jpg?
收藏 0 赞 0 分享

CSS教程:水平对齐(text-align)

  水平对齐(text-align),用以设定元素内文本的水平对齐方式。   1.语法   text-align具体参数如下: 语法:text-align:left|right|center|justify 说明:设定元素内文本的水平对齐方式。 参数:left:左
收藏 0 赞 0 分享
查看更多