小tip:FireFox下文本框/域百分比padding bug解决

这篇文章发布于 2012年11月13日,星期二,12:24,归类于 CSS相关。 阅读 66538 次, 今日 9 次 14 条评论

 

一、问题描述

我是流体布局控,经常会遇到文本框以及文本域宽度100%自适应显示的情况。

如下效果图:
文本域宽度100%显示 张鑫旭-鑫空间-鑫生活

在窄屏下,上面的文本框宽度也要跟着外部宽度变小。

难点
对于文本框或者文本域,光标最好距离左侧边缘有一定的间距。因此,我们基本上都有类似下面的设置:

input { padding-left: 10px; }

但是,如果只考虑文本框本身(父标签无其他特殊处理),这一套在流体环境下是行不通的,因为固定的padding数组无法让文本框永远100%自适应外部的宽度,至少非现代浏览器下是如此!//zxx: CSS3计算(calc())就是为了解决这类问题才诞生的!

input { width: calc(100% - 10px); padding-left: 10px; } 

目前而言,好的解决之道是widthpadding均采用百分比值,例如下面这样:

input { width: 92%; padding-left: 4%; padding-right: 4%; }

问题
上面这种写法,IE6+, Opera, Chrome, Safari浏览器都是显示很OK的;唯独FireFox火狐浏览器,其虽然宽度渲染正常,但是,光标的位置确是顶头的(与数值padding的显示完全不同)。

如下截图:
FireFox下面文本框百分比padding显示的问题截图

这个问题再FireFox浏览器下存在已经有3年之久了,到现在还没有修复。您可以狠狠地点击这里:FireFox下文本框百分比padding位置bug demo

如何修复这个问题呢?

//zxx: 可能有人会提议div模拟文本框(即div设置padding值), 文本框本身no border, no padding, 且width:100. 这种操蛋的方法我是一点都不喜欢的(纯属个人喜好,没有攻击的意思),一是啰嗦;二来文本框本身可能就有box-shadow, outline以及内联的交互验证UI(如验证非法红色外发光),难道你想把这些都抹杀掉??

更新2012-11-30

注意:FireFox 17+已经修复了该问题!

二、text-indent修复法

firefox浏览器下的问题其实只是文字的位置问题而已,其本身的宽度渲染都是准确的,因此,我们可以把解决问题的关键点放在解决文字不缩进的问题上——我们自然而然就会想到文字缩进属性text-indent.

于是,在FireFox浏览器下,我们只要设置:

input { text-indent: 4%; }

就可以了!

现在的问题是,如何只让FireFox浏览器设置这个属性呢??FireFox浏览器有专属的hack吗?

我们打开FireBug, 点击下图所示的地方:
FireBug打开浏览器默认的样式设置 张鑫旭-鑫空间-鑫生活

于是,对于刚才的文本框,我们会看到FireFox浏览器默认对其的设置,其中有个这个:
文本框默认的一些属性设置 张鑫旭-鑫空间-鑫生活

这正是我们需要的,因此,添加类似下面的补丁:

input:-moz-read-write{text-indent:4%;}

即可完美修复FireFox浏览器下光标以及文字顶头显示的bug.

修复之后的效果如下截图:
FireFox浏览器下text-indent修复后截图 张鑫旭-鑫空间-鑫生活

1024宽度下的截图:
1024宽度下FireFox浏览器下修复截图

您可以狠狠地点击这里:text-indent修复FireFox下文本框百分比padding问题demo

可能的疑问
说到这里,可能有比较灵光的同行会疑问,既然text-indent可以让文字位置后移,那为何要使用padding呢,直接:

input { width: 100%; text-indent: 4%; }

不就可以了吗?

这确实是个不错的idea, 只可惜在IE6/IE7浏览器下,text-indent会偏移文本框的位置(连文本框自身一起缩进了!)。如下截图示意:
IE6/IE7下文本框一起缩进了! 张鑫旭-鑫空间-鑫生活

如下测试代码:

.box{padding:40px 0; background-color:#B70D0D;}
.box input { width: 200px; text-indent: 20px; }
<p class="box"><input value="我是文字" /></p>

您可以狠狠地点击这里:IE6/IE7文本框text-indent bug示意

IE8+以及其他浏览器下都是OK的,缩进的只是文本框的文字,文本框不动,如下示意:

局限
text-indent撑开文字边距是有局限性的,显而易见,其只能让第一行文字有边距。于是,当面对多行文本域(textarea)的时候,text-indent就捉襟见肘,无能为力了!

因此,对于文本域,我们需要寻求其他完善方法。

三、box-sizing的修复策略

FireFox下文本框或文本域对百分比padding值的显示有问题,但是对具体px的padding值显示却正常。因此,我们可以设置padding-left/padding-right为类似10px这样的具体数值,而把问题解决的重心放在如何宽度100%显示上。

在CSS3属性中,有个叫做box-sizing的好东西,IE8+以及现代浏览器都支持,如果我们设置该属性值为border-box,则padding值不会撑大元素的设定宽度,如width:100px; padding:10px;最后元素占据的宽度还是100像素而不是120像素。

于是,这里,我们可以如下设置CSS:

input:-moz-read-write{width:100%; height:40px; padding:10px; -moz-box-sizing:border-box;}

FireFox即问题修复,如下截图:
box-sizing修复后的FireFox浏览器截图 张鑫旭-鑫空间-鑫生活

您可以狠狠地点击这里:box-sizing修复FireFox文本框百分比宽度问题demo

四、CSS3 cacl()计算修复

上面的box-sizing方法影响到了原本OK的height设置,而使用CSS3 cacl()计算只针对目标属性width进行处理,如下修复代码:

input:-moz-read-write{width:-moz-calc(100% - 20px); padding:10px;}

注意,减号(-)前后需要有空格,否则无法识别。

于是,有大致如下的修复效果图(FireFox浏览器截图):
CSS3 cacl()计算修复后的FireFox浏览器截图 张鑫旭-鑫空间-鑫生活

您可以狠狠地点击这里:box-sizing修复FireFox文本框百分比宽度问题demo

五、文本框文本域含边框时的处理

到目前为止所示的情况都是不含边框的,基本上,全世界90%+的文本框或者是文本域都是有border的,或自身的或CSSer设置的,要知道,border是不支持百分比宽度的,只能是固定数值大小的单位。现在问题来了:含有border的文本域文本框如何实现宽度100%的自适应呢??

使用padding正值+margin负值补间技术
//zxx: 这里的内容有些偏题,不过多展开。

demo抢先,您可以狠狠地点击这里:文本域(含边框)的宽度100%显示demo

固定数值与文本域100%宽度显示截图缩略图

demo中,上面一个例子是仅边框是固定像素值;下面一个是边框以及左右padding都是固定数值。都实现了良好的100%自适应,兼容IE6以及IE7浏览器。

原理(见下图圈中,不言而喻):

然而,在实际的项目中,我并不经常使用上面的方法。一是牵扯父标签;二是牵扯计算;三是无法大范围重用(原因是父标签的padding值设置受限)。

OK,到此为止,感谢阅读,欢迎指正文章表述不准确的地方,吃饭饭去咯~

(本篇完)

分享到:


发表评论(目前14 条评论)

  1. laserw9说道:

    文中有几处地方把 “calc” 错写成 “cacl” 了,不过不影响

  2. 扇扇说道:

    张老师,您好,请问cacl何时会被触发?如何验证?谢谢

  3. 奇云说道:

    那个 IE6/7 的 bug,我发现只要在 input 标签前面加个回车或者空格就解决了。
    但同时有一个蛋疼的问题,value 属性有中文时正常,如果是纯英文,初次渲染时 text-indent 是不生效的,测试于 IETester

  4. 静寂无闻之夜说道:

    比较喜欢text-indent这属性,在产生边距的前提不怎么会影响布局。张大人就是爱折腾呀,哈哈。

  5. ACE说道:

    饮水思源,在这篇文章的指导下解决了问题就回复一下表示支持了

  6. 一路说道:

    关于使用text-indent属性在ie6~7下的问题,我测试了下,给input添加display:block下可以解决,不知道是否合理?

  7. 卜卜口の说道:

    立刻想到box-sizing了 除了CSS3的新属性之外只能是用bug修正bug了

  8. zjx说道:

    用Phonegap做应用,Android2下 calc 函数不起作用,box-sizing 比较稳妥

  9. zhanglei说道:

    请问,光标颜色有办法控制吗? 我们有个项目登陆框背景是黑色的,在 firefox 下光标默认是黑色,就看不见了,请问有办法自定义光标颜色吗?

  10. t说道:

    其实吧 我觉得还不如给它的父元素一个神马的然后把 input 的边框调到木有。这样这个貌似 padding 的东西实际上属于父元素。。。
    或者把 input 的 border 调到 transparent 也可以吧。

  11. yetazhan说道:

    呵呵 来旁观box-sizing貌似我还没有用过,但是看后很受用,顶

  12. baoeni说道:

    今天刚好也遇到这个问题,第一个想到的是box-sizing,可惜IE6、7不能用,不过用你说的:“好的解决之道是width和padding均采用百分比值”应该可以解决。

  13. 彭宁说道:

    很全面,我阅读并编写了代码之后,有很大收获。十分感谢!