问题
我有一个 <select>
,其中一个 <option>
的文本值很长。我希望 <select>
调整大小,使其永远不会比其父级宽,即使它必须切断其显示的文本。 max-width: 100%
应该这样做。
调整大小之前:
https://i.stack.imgur.com/RIv8L.png
调整大小后我想要什么:
https://i.stack.imgur.com/DJnrc.png
但是,如果您 load this jsFiddle example 并将结果面板的宽度调整为小于 <select>
的宽度,您会看到 <fieldset>
内的选择无法缩小其宽度。
调整大小后我实际看到的内容:
https://i.stack.imgur.com/fcGsM.png
但是,equivalent page with a <div>
instead of a <fieldset>
确实可以正确缩放。如果您有 a <fieldset>
and a <div>
next to each other on one page,您可以看到它和 test your changes more easily。如果您 delete the surrounding <fieldset>
tags,则调整大小有效。 <fieldset>
标记以某种方式导致水平调整大小中断。
<fieldset>
的作用就像有 CSS 规则 fieldset { min-width: min-content; }
。 (min-content
大致表示不会导致子元素溢出的最小宽度。)如果我将 <fieldset>
替换为 <div>
with min-width: min-content
,它看起来完全一样。然而,在我的样式、浏览器默认样式表或 Firebug 的 CSS Inspector 中没有 min-content
规则。我试图覆盖在 Firebug 的 CSS Inspector 和 Firefox 的默认样式表 forms.css 中的 <fieldset>
上可见的所有样式,但这并没有帮助。具体覆盖 min-width
和 width
也没有做任何事情。
代码
字段集的 HTML:
<fieldset>
<div class="wrapper">
<select id="section" name="section">
<option value="-1"></option>
<option value="1501" selected="selected">Sphinx of black quartz, judge my vow. The quick brown fox jumps over the lazy dog.</option>
<option value="1480">Subcontractor</option>
<option value="3181">Valley</option>
<option value="3180">Ventura</option>
<option value="3220">Very Newest Section</option>
<option value="1481">Visitor</option>
<option value="3200">N/A</option>
</select>
</div>
</fieldset>
我的 CSS 应该可以工作但没有:
fieldset {
/* hide fieldset-specific visual features: */
margin: 0;
padding: 0;
border: none;
}
select {
max-width: 100%;
}
将 width
属性重置为 the defaults 不会执行任何操作:
fieldset {
width: auto;
min-width: 0;
max-width: none;
}
我在其中的其他 CSS try and fail to fix the problem:
/* try lots of things to fix the width, with no success: */
fieldset {
display: block;
min-width: 0;
max-width: 100%;
width: 100%;
text-overflow: clip;
}
div.wrapper {
width: 100%;
}
select {
overflow: hidden;
}
更多细节
此问题也出现在此 more comprehensive, more complicated jsFiddle example 中,它与我实际尝试修复的网页更相似。您可以从中看出 <select>
不是问题——内联块 div
也无法调整大小。虽然这个例子更复杂,但我假设上面简单案例的修复也将修复这个更复杂的案例。
[编辑:请参阅下面的浏览器支持详细信息。]
关于这个问题的一个奇怪的事情是,if you set div.wrapper { width: 50%; }
,<fieldset>
在此时停止调整自身大小,然后全尺寸 <select>
将到达视口的边缘。调整大小就像 <select>
有 width: 100%
,即使 <select>
看起来像它有 width: 50%
。
https://i.stack.imgur.com/ne1lu.png
如果您give the <select>
itself width: 50%
,则不会发生该行为;宽度设置正确。
https://i.stack.imgur.com/kcHbr.png
我不明白造成这种差异的原因。但这可能不相关。
我还发现了非常相似的问题 HTML fieldset allows children to expand indefinitely。除了删除 <fieldset>
之外,提问者找不到解决方案和 guesses that there is no solution。但我想知道,如果真的不可能正确显示 <fieldset>
,那是为什么呢? <fieldset>
的 spec 或 default CSS (as of this question) 中的什么导致了这种行为?这种特殊行为可能记录在某处,因为多个浏览器都是这样工作的。
背景目标和要求
我尝试这样做的原因是为具有大表单的现有页面编写移动样式的一部分。该表单有多个部分,其中一部分包含在 <fieldset>
中。在智能手机上(或者如果您将浏览器窗口缩小),带有 <fieldset>
的页面部分比表单的其余部分宽得多。大多数表单都很好地限制了它的宽度,但带有 <fieldset>
的部分没有,迫使用户缩小或向右滚动以查看所有该部分。
我对简单地删除 <fieldset>
持谨慎态度,因为它是在大型应用程序的许多页面上生成的,而且我不确定 CSS 或 JavaScript 中的哪些选择器可能依赖它。
如果需要,我可以使用 JavaScript,而 JavaScript 解决方案总比没有好。但如果 JavaScript 是做到这一点的唯一方法,我很想知道为什么只使用 CSS 和 HTML 是不可能的。
编辑:浏览器支持
在该站点上,我需要支持 Internet Explorer 8 及更高版本(我们刚刚放弃了对 IE7 的支持)、最新的 Firefox 和最新的 Chrome。此特定页面也应该适用于 iOS 和 Android 智能手机。 Internet Explorer 8 可以接受稍微降级但仍然可用的行为。
我在不同的浏览器上重新测试了 my broken fieldset
example。它实际上已经在这些浏览器中工作:
Internet Explorer 8、9 和 10
铬合金
安卓版 Chrome
它在这些浏览器中中断:
火狐
火狐安卓版
互联网浏览器 7
因此,我关心的当前代码中断的唯一浏览器是 Firefox(在桌面和移动设备上)。如果代码已修复,因此它可以在 Firefox 中运行而不会在任何其他浏览器中破坏它,那将解决我的问题。
站点 HTML 模板使用 Internet Explorer 条件注释将 .ie8
和 .oldie
等类添加到 <html>
元素。如果您需要解决 IE 中的样式差异,您可以在 CSS 中使用这些类。添加的类与 this old version of HTML5 Boilerplate 中的相同。
<fieldset>
(或 div.wrapper
)它需要的任何宽度,然后 select { width:100% }
。 max-width
似乎为元素提供了其父元素 原始 宽度的一些百分比,然后不缩放,而 width
确实随其父元素缩放。我认为这会做你想要的(但我可能误解了)。在您更复杂的小提琴中,尝试为左列中的字段指定一个 %-width 和一个 min-pixel-width。然后给右边的字段 100 - (left-fields-%-width) % 宽度。
更新(2017 年 9 月 25 日)
下面描述的 Firefox bug 自 Firefox 53 起已修复,此答案的链接最终是 removed from Bootstrap's documentation。
此外,我向 Mozilla 贡献者表示诚挚的歉意,他们不得不阻止删除对 -moz-document
的支持,部分原因是这个答案。
修复
在 WebKit 和 Firefox 53+ 中,您只需在字段集上设置 min-width: 0;
即可覆盖默认值 min-content
。¹
尽管如此,Firefox 在字段集方面还是有点……奇怪。要在早期版本中使用此功能,您必须将字段集的 display
属性更改为以下值之一:
表格单元格(推荐)
表列
表列组
表页脚组
表头组
表行
表行组
其中,我推荐 table-cell
。 table-row
和 table-row-group
都阻止您改变宽度,而 table-column
和 table-column-group
阻止您改变高度。
这将(在某种程度上)破坏 IE 中的渲染。由于只有 Gecko 需要此功能,您可以合理地使用 @-moz-document
(Mozilla's proprietary CSS extensions 之一)对其他浏览器隐藏它:
@-moz-document url-prefix() {
fieldset {
display: table-cell;
}
}
(这里有一个 jsFiddle demo。)
这解决了问题,但如果你和我一样,你的反应是……
什么。
有一个原因,但它并不漂亮。
fieldset 元素的默认呈现方式是荒谬的,而且基本上不可能在 CSS 中指定。想一想:字段集的边框在与图例元素重叠的地方消失了,但背景仍然可见!没有办法用任何其他元素组合来重现这一点。
最重要的是,实现对遗留行为充满了让步。其中之一是字段集的最小宽度永远不会小于其内容的固有宽度。 WebKit 为您提供了一种通过在默认样式表中指定它来覆盖此行为的方法,但 Gecko² 更进一步enforces it in the rendering engine。
但是,内部表格元素构成 Gecko 中的 special frame type。具有这些 display
值集的元素的尺寸约束在 separate code path 中计算,完全规避了强加于字段集的强制最小宽度。
再说一遍——从 Firefox 53 开始,bug for this 已被修复,因此如果您只针对较新版本,则不需要此 hack。
使用@-moz-document 安全吗?
对于这个问题,是的。 @-moz-document
在所有版本的 Firefox 中都可以正常工作,直到 53 版本,该错误已修复。
这绝非偶然。部分由于这个答案,limit @-moz-document
to user/UA stylesheets 的错误取决于首先修复的基础字段集错误。
除此之外,请勿在 CSS 中使用 @-moz-document
来定位 Firefox,尽管有其他资源。³
¹ 值可能带有前缀。据一位读者说,这对 Android 4.1.2 Stock Browser 和可能的其他旧版本没有影响;我没有时间验证这一点。
² 此答案中指向 Gecko 源的所有链接均指 5065fdc12408 changeset,于 2013 年 7 月 29 日提交;您不妨将笔记与 most recent revision from Mozilla Central 进行比较。
³ 请参阅例如 SO #953491: Targeting only Firefox with CSS 和 CSS Tricks: CSS hacks targeting Firefox,了解知名网站上被广泛引用的文章。
iOS 上的 Safari 问题选择了答案
我发现 Jordan Gray 的回答特别有帮助。但是,它似乎并没有为我解决 Safari iOS 上的这个问题。
对我来说,问题很简单,如果其中的元素的最大宽度为 % 宽度,则字段集不能具有自动宽度。
修复问题
只需将字段集设置为其容器的 100% 宽度似乎可以解决此问题。
例子
fieldset {
min-width: 0;
width: 100%;
}
请参阅下面的工作示例 - 如果您从字段集中删除 % 宽度或将其替换为自动,它将无法继续运行。
我为此苦苦挣扎了好几个小时,基本上,浏览器正在应用您需要在 CSS 中覆盖的计算样式。我忘记了在 fieldset
元素上设置的确切属性与 div
(也许是 min-width
?)。
我最好的建议是将您的元素更改为 div
,从检查器复制计算的样式,然后将您的元素更改回 fieldset
并比较计算的样式以找出罪魁祸首。
希望有帮助。
更新:添加 display: table-cell
有助于非 Chrome 浏览器。
fieldset
和 div
的每个 CSS 属性。它没有帮助。在 Firebug 中,唯一具有不同值的属性是 width
和 perspective-origin
。 width
在数值上有所不同,但 fieldset
的 width
是 auto
,就像 div
的一样。而 perspective-origin
只是 width
的一个函数——默认情况下是它的 50%。
min-width: 0;
添加到我的示例 after 在 Chrome 中进行测试,但似乎这解决了 Chrome 中的问题。 Web Inspector 告诉我 Chrome 具有样式 min-width: -webkit-min-content;
,正如我假设的那样。所以现在我只需要在 Firefox 和其他我还没有测试过的浏览器中解决这个问题。
.fake-select { white-space:nowrap; }
导致字段集按其原始宽度而不是其强制宽度(即使溢出被隐藏时)解释 .fake-select
元素。
删除该规则,并将 .fake-select
的 max-width:100%
更改为 width:100%
,一切都适合。需要注意的是,您会看到 fake-select 的所有内容,但我认为这并没有那么糟糕,现在它可以水平放置。
更新:使用以下小提琴中的当前规则(仅包含真正的选择),字段集的子项被限制为正确的宽度。除了删除 .fake-select
的规则和修复注释(从 // comment
到 /* comment */
,我注意到小提琴的 CSS 发生了变化。
我现在更好地理解了你的问题,小提琴反映了一些进展。我为所有 <select>
设置默认规则,并为您知道宽度将超过 480 像素的那些保留 .xxlarge
(这仅适用于您知道 #viewport
的宽度,并且可以手动将类添加到那些太宽的类。只需要一点测试)
<select>
起作用。实际站点只有 <select>
。 fake-select
的意义在于拥有 <select>
的布局规则而不是实际的 <select>
,只是为了表明这种行为不是只发生在 <select>
元素上的浏览器错误。因此,将 .fake-select
的样式更改为不太像 <select>
就达不到目的了。
.fake-select
框替换为 <select>
(与已经存在的相同)以进行演示。元素都被限制在父级的宽度(除非你点击它,下拉选项,每个选项都显示在一行上——但我认为你无法控制它)。我还删除了 .fake-select
的所有规则。当前的小提琴可以满足您的需要吗?
width: 100%
适用于页面上的长菜单,但不适用于短菜单。它将短菜单扩展到页面的整个宽度,但我希望短菜单保持它们的短宽度。如果有空间,菜单应该是它们的自然宽度,但如果它们对于它们的父级来说太大,则应该是 100% 宽度。这就是 max-width
应该做的,但在这种情况下没有做。
<select>
”与“长<select>
”分开,现在只处理背景宽度。
#viewport
也没有固定宽度。这就是我在页面上放置 Resize Viewport 按钮的原因——这样无论视口宽度如何,您都可以测试一切是否正常。正如 .fake-select
可以替代真实的 <select>
进行测试一样,#viewport
可以替代真实的视口。 (“视口”基本上是一个浏览器窗口)。我在页面上添加了 #viewport
,这样您就可以轻松地看到突出在视口之外的元素,而不必滚动才能看到它们。