当对同时设置了左和右CSS属性的INPUT进行绝对定位时出现奇怪行为

7
我正在学习绝对定位的CSS格式化<input>。我希望它在其容器内"拉伸",使其左右两侧留出30像素,并填充所有空间...
我已经找到了w3.org网站上的示例,它使用左右两侧来创建CSS中的"框架"。
我还阅读了A-List-Apart的一篇文章,讨论了这种技术,并发现了这里处理类似问题的其他几个问题,但没有一个专注于我将要描述的具体问题。我还发现我可以用<div>包装内部的<input>,但我想深入了解这个主题,以了解为什么它表现不佳...

这是我制作的一个工作示例,用于测试和澄清这个想法。简而言之,它就像这样简单:

<div id="sidebar">
  <input type="text" value="input" />
</div>

使用这种样式:

body { height: 100% } /* Required for percentage heights below */
#sidebar {
    position: absolute;
    top: 0;
    height: 100%;
    left: 0;
    width: 160px;
}
#sidebar input {
    position: absolute;
    margin: 0;
    padding: 0;
    height: 21px;
    left: 30px;
    right: 30px;
    width: auto;
}

有趣的点在于最后三行,当我设置左和右并将宽度设为“自动”时。
结果是,在Chrome(v.26)中只有使用预期效果,但在FF.20或IE.10中,它看起来是损坏的:超出其容器div的右边缘..当只设置左位置时,情况也是如此。
有趣的部分是,这种DIV和内联块SPAN的方法在所有三个浏览器中都能按预期工作。
这是浏览器的错误吗?有没有办法使它在不需要解决方案的情况下正常工作,将<input>与width:100%包含在所述方式中的另一个<div>中?
希望有人对此有线索。
PS:我专注于“现代”,html5浏览器,因此如果它不能在IE8或更早版本上工作,我不介意。

当你想要一个元素表现得像另一种类型的元素时,也许可以通过给它相同的属性来实现这样的元素行为。话虽如此,我的意思是从头开始让它 display:block,并看看它会带给你什么。 - Breezer
我已经尝试过了,当然不是那么容易,但你是对的:永远不要忽略简单的东西 :) - Luke
3个回答

6

观察结果

我对此行为感到惊讶。顶部-右侧-底部-左侧的绝对定位工作得非常好(已经有几年了),但在IE 10和FF上无效,特别是在input type="text"上。

误导:您的方法在input type="range"上确实有效,但在IE 10中无法使用input type="number"。也许这与浏览器负责绘制哪些输入以及那些输入可能会轻松包装操作系统已提供的功能有关。

在FF(PC/Mac)中,我观察到输入的size属性似乎会覆盖除显式宽度分配之外的任何内容。例如,设置size=4将使输入比所需更窄。观察到的宽度似乎是隐式size=20值的结果。

解决方法

尽管如此,我有一个潜在的解决方案,不需要对您的代码进行广泛更改,并且在IE9/10、FF(PC/Mac)、Chrome(PC/Mac)和Safari(Mac)中都可以使用。

演示:http://jsfiddle.net/ws9hf/13/

#sidebar .x {
    position: absolute;
    box-sizing: border-box;
    width: -webkit-calc(100% - 60px);
    width: calc(100% - 60px);
    left: 30px;
    right: 30px; /* fallback */
}

这里使用了calc()函数,它在各个浏览器中都有不错的支持。值得注意的是,W3认为这个功能存在“风险”,因此其未来可能不确定。

尽管calc()函数很“酷”,但实际上,我会将相关输入内容放入另一个元素中并完成操作。这样可以获得更广泛的浏览器支持和未来兼容性。


我同意,关键点可能是浏览器如何渲染<input>控件:如果它们由操作系统绘制,则可能存在一些奇怪的故障在浏览器-操作系统方面,这可能解释它们不同的行为... - Luke
leftright 都存在时,使用 width: calc(100% - leftVal - rightVal) 将会像常规的 div 一样扩展 input 元素。 - manikanta
目前最好的解决方案不涉及任何包装元素,这样就不会出现其他问题,如填充和边框(例如:尝试在“%”中应用填充 - 如果应用于包装器,则它不会成为“输入”的填充。如果您应用于输入,则“%”值将基于包装器宽度计算,而这不是预期的)。 - manikanta

1
您可以将输入内容包装在一个容器 div 中,并对该 div 进行样式设置。

以下是一个示例。
<div id="sidebar">
     <div id="inputContainer">
         <input type="text" value="input" />
     </div>
</div>

body { height: 100% } /* Required for percentage heights below */
#sidebar {
    position: absolute;
    top: 0;
    height: 100%;
    left: 0;
    width: 160px;
}
#sidebar #inputContainer {
    position: absolute;
    margin: 0;
    padding: 0;
    height: 21px;
    left: 30px;
    right: 30px;
}
#inputContainer{
    width: 100%;
}

0

这不完全是你所要求的,但如果你只关心现代浏览器,你可以使用 flexbox 来代替。

你只需要指定你正在使用 flexbox 并且想要一个垂直方向,然后你就可以设置一个 30px 的 margin,而不是使用定位:

#sidebar {
    /* stripped out additional styles and prefixes */
    display: flex;
    flex-direction: column;
}

#sidebar x {
    margin: 0 30px;
}

请在http://jsfiddle.net/ws9hf/8/上查看演示。


在最新的Firefox浏览器(官方版本v.20.0.1)中,您的示例无法按预期工作(“输入”超出了绿色条)。不管怎样,这是我想要更深入研究的另一条路 =) - Luke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接