<fieldset>调整大小错误;似乎具有不可移动的`min-width:min-content`


221

问题

我有一个<select><option>的文本值很长的地方。我要<select>调整其大小,以使其永远不会比其父对象宽,即使它必须切断其显示的文本也是如此。max-width: 100%应该这样做。

调整大小之前:

调整大小前的页面,显示整个<code> select </ code>

调整大小后我想要什么:

调整大小后我想要的页面,用<code> select </ code>剪切其内容

但是,如果您加载此jsFiddle示例,并将“结果”面板的宽度调整为小于的宽度<select>,则可以看到内部的select <fieldset>无法缩小其宽度。

调整大小后,我实际上看到的是:

调整大小后的当前页面,带有滚动条

但是,用a <div>代替a<fieldset>等效页面确实可以正确缩放。如果在一页上一个接一个则可以看到并更轻松地测试更改。并且,如果删除周围的标签,则可以调整大小。该标签在某种程度上导致水平尺寸调整打破。<fieldset><div><fieldset><fieldset>

<fieldset>行为是如果有一个CSS规则fieldset { min-width: min-content; }。(min-content手段,大致的最小宽度不会引起孩子溢出。)如果我更换<fieldset><div>min-width: min-content,它看起来完全一样。但是min-content我的样式,浏览器默认样式表或Firebug的CSS Inspector中都没有规则。我试图覆盖<fieldset>Firebug的CSS检查器和Firefox的默认样式表forms.css中可见的所有样式,但这无济于事。专门覆盖min-widthwidth也没有执行任何操作。

字段集的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属性重置为默认值不会执行任何操作:

fieldset {
    width: auto;
    min-width: 0;
    max-width: none;
}

尝试无法解决问题的其他CSS :

/* 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;
}

更多细节

这个更全面,更复杂的jsFiddle示例也出现了问题,该示例与我实际上要修复的网页更加相似。从中可以看出,这<select>不是问题所在–内联块div也无法调整大小。尽管此示例更加复杂,但我认为上面简单案例的修复程序也将解决此复杂案例。

[编辑:请参阅下面的浏览器支持详细信息。]

关于此问题的一个令人奇怪的事情是,如果您设置div.wrapper { width: 50%; },则<fieldset>停止点将在该点调整自身大小,然后原尺寸<select>会碰到视口的边缘。调整大小发生,因为如果<select>width: 100%,即使<select>看起来有width: 50%

用50%宽度的包装器div调整大小后

如果您给出<select>本身width: 50%,则不会发生该行为。宽度只需正确设置即可。

使用50%宽度调整大小后,选择

我不明白这种差异的原因。但这可能不相关。

我还发现非常相似的问题HTML字段集允许孩子无限期扩展。提问者找不到解决方案,并猜测除了删除之外,没有解决方案<fieldset>。但是我想知道,如果真的不可能<fieldset>正确显示,那为什么呢?什么<fieldset>规范默认的CSS如这一问题)导致这种行为?这种特殊行为可能在某个地方记录了下来,因为多个浏览器都是这样工作的。

背景目标和要求

我尝试执行此操作的原因是为具有较大形式的现有页面编写移动样式的一部分。表单有多个部分,其中一部分包裹在中<fieldset>。在智能手机上(或者如果您使浏览器窗口变小),带有的页面部分<fieldset>比表格的其余部分要宽得多。大多数形式都可以很好地限制其宽度,但是带有的部分<fieldset>则不能,因此迫使用户缩小或向右滚动以查看所有部分。

我不敢简单地删除<fieldset>,因为它是在大型应用程序的许多页面上生成的,而且我不确定CSS或JavaScript中的哪些选择器可能依赖于它。

如果需要,我可以使用JavaScript,JavaScript解决方案总比没有好。但是,如果JavaScript是实现此目标的唯一方法,那么我很想听到一个解释,说明为什么仅使用CSS和HTML无法做到这一点。


编辑:浏览器支持

在该站点上,我需要支持Internet Explorer 8和更高版本(我们刚刚放弃了对IE7的支持),最新的Firefox和最新的Chrome。此特定页面也应在iOS和Android智能手机上运行。Internet Explorer 8可以接受稍微降级但仍可用的行为。

我在不同的浏览器上重新测试了损坏的fieldset示例。它实际上已经可以在以下浏览器中运行:

  • Internet Explorer 8、9和10
  • 适用于Android的Chrome

它在以下浏览器中中断:

  • 火狐浏览器
  • Android版Firefox
  • Internet Explorer 7

因此,我关心的唯一破坏当前代码的浏览器是Firefox(在台式机和移动设备上)。如果代码是固定的,那么它可以在Firefox中运行而又不会在任何其他浏览器中破坏它,那将解决我的问题。

该网站的HTML模板使用Internet Explorer条件注释添加类,.ie8.oldie<html>元素。如果需要解决IE中样式差异的问题,可以在CSS中使用这些类。添加的类与此旧版本的HTML5 Boilerplate中的类相同。


41
祝贺这篇出色的论文
Alp

您的简单示例:给出<fieldset>(或div.wrapper)所需的任何宽度,然后select { width:100% }max-width似乎为元素提供了其父元素原始宽度的%,然后不缩放,width但与父元素缩放。我认为这可以满足您的要求(但我可能会误会)。在更复杂的小提琴中,尝试为左栏中的字段提供%宽度和min-pixel-width。然后给右边的字段100-(left-fields-%-width)%width。
Trojan

我只是有个想法:如果将字段集的最小宽度设置为0,该怎么办?这本身可能无法解决问题,但可能值得尝试解决。我现在正在尝试其他方法,但是如果它不起作用,我也将尝试一下
Trojan

您是否需要标签和字段保持同一行?对于小视口,它们会重叠。为什么不使其有所响应,并在必要时中断换行?
Trojan

Answers:


346

更新(2017年9月25日)

以下所述的Firefox错误已从 Firefox 53开始修复,并且该答案的链接最终已从Bootstrap的文档中删除

另外,我真诚地对Mozilla贡献者表示歉意,他们不得不-moz-document部分地因为此答案而阻止删除支持。

解决方法

在WebKit和Firefox 53+中,您只需min-width: 0;在字段集上进行设置即可覆盖默认值min-content。¹

尽管如此,Firefox在字段集方面还是有点奇怪。要使它在较早版本中起作用,必须将display字段集的属性更改为以下值之一:

  • table-cell (推荐的)
  • table-column
  • table-column-group
  • table-footer-group
  • table-header-group
  • table-row
  • table-row-group

其中,我建议table-cell。两者table-row和都可以table-row-group防止您更改宽度,而table-column和可以table-column-group防止您更改高度。

这将(在某种程度上合理地)破坏IE中的呈现。由于只壁虎需要这个,你可以名正言顺地使用@-moz-document酮的Mozilla的专有的CSS扩展 -to从其他浏览器隐藏:

@-moz-document url-prefix() {
    fieldset {
        display: table-cell;
    }
}

(这是一个jsFiddle演示。)


可以解决问题,但是如果您像我一样,您的反应就是…

什么。

有原因的,但这并不漂亮。

fieldset元素的默认表示形式是荒谬的,并且基本上不可能在CSS中指定。想一想:字段集的边框在与图例元素重叠的位置消失了,但是背景仍然可见!无法通过任何其他元素组合来重现此内容。

最重要的是,实现对遗留行为充满了让步。这样的一种是,字段集的最小宽度永远不会小于其内容的固有宽度。WebKit提供了一种通过在默认样式表中指定此行为来覆盖此行为的方法,但是Gecko²更进一步,并在呈现引擎中实施了该行为

但是,内部表元素在Gecko中构成一种特殊的框架类型。具有这些display值集的元素的尺寸约束是在单独的代码路径中计算的,完全避免了施加在字段集上的强制性最小宽度。

同样,此错误已在Firefox 53中修复,因此如果您只针对较新的版本,则不需要此hack。

使用@-moz-document安全吗?

对于这个问题,是的。 @-moz-document可以在所有版本的Firefox(直至53)中按预期工作,该错误已得到修复。

这不是偶然的。部分由于此答案,导致限制@-moz-document用户/ UA样式表的错误取决于首先修复的基础字段集错误。

除此之外,尽管如此,请勿使用@-moz-documentCSS中的Firefox作为目标。³


¹值可以加前缀。一位读者认为,这在Android 4.1.2 Stock Browser和其他旧版本中无效。我还没有时间验证这一点。

²此答案中与Gecko来源相关的所有链接均指向5065fdc12408变更集,该变更于2013年7月29日提交;您可能希望将注释与Mozilla Central的最新修订进行比较。

³参见例如SO#953491:仅针对具有CSSCSS技巧的Firefox:针对Firefox的CSS技巧,针对知名网站上广泛引用的文章。


5
我刚刚注意到该修复程序在IE中中断,只是来到这里并发现您已经在该解决方案中进行了编辑。谢谢!在每个浏览器中,Gecko hack解决方案都对我有效。
罗里·奥肯

我一直在努力解决这个问题,但是您的解决方法是完美的-除非它似乎只能在Firefox中使用。对其他浏览器(尤其是移动浏览器)有什么建议吗?我最大的问题是由于移动设备上方向的改变而调整大小...
Adriaan Nel

30
这是一个绝对出色的答案-彻底,经过研究和简洁。谢谢。
iamkeir 2013年

16
当然,这是一个绝对出色的答案!Bootstrap官方文档指向此处
Ranhiru Jude Cooray 2014年

1
好吧,我对字段集一无所知。我今天在这里学到了一些东西。
superluminary

11

iOS上的Safari问题与选定答案

我发现约旦·格雷的回答特别有帮助。但是,它似乎并没有为我解决Safari iOS上的此问题。

我的问题很简单,如果其中的元素的最大宽度为%宽度,则字段集不能具有自动宽度。

解决问题

只需将字段集设置为容器宽度的100%,似乎可以解决此问题。

fieldset {
    min-width: 0; 
    width: 100%; 
}

请参考以下工作示例-如果您删除了字段集的%宽度或将其替换为auto,它将不会继续起作用。

JSFiddle | 码笔


1
这是对一般问题的补充,我不认为要在iOS中进行测试。:)我几乎认为这也值得您提出并作为一个新问题进行自我解答。我将在本周尝试进行一些额外的测试,并在可行的情况下链接到此答案。
乔丹·格雷

3

我为此付出了许多努力,基本上,浏览器正在应用您需要在CSS中覆盖的计算样式。我忘记了在fieldset元素与divs 上设置的确切属性(也许是min-width?)。

我最好的建议是将元素更改为div,从检查器复制计算出的样式,然后将元素更改回fieldset并比较计算出的样式以找出罪魁祸首。

希望能有所帮助。

更新:display: table-cell在非Chrome浏览器中添加帮助。


我在Firebug的此页面上比较了fieldset和的每个CSS属性。它没有帮助。在Firebug中,唯一具有不同值的属性是和。在数值上不同,但的是,像的。而且,这只是默认值的50%。divwidthperspective-originwidthfieldsetwidthautodivperspective-originwidth
罗里·奥肯

但是,该比较确实在Chrome Web Inspector中提供了帮助。打开示例后,我立即发现它可以在Chrome中运行!在Chrome中进行测试后,我已将min-width: 0;示例添加到示例中,但似乎可以解决Chrome中的问题。Web检查器告诉我,Chrome具有我所假设的样式。因此,现在我只需要解决Firefox和其他尚未测试过的浏览器中的问题。min-width: -webkit-min-content;
罗里·奥肯

很高兴它有所帮助。我可以使用“ display:table-cell”在其他浏览器中解决我的问题。我认为这不是最佳解决方案,但希望对您有用。
phdj

2

.fake-select { white-space:nowrap; }导致字段集通过.fake-select元素的原始宽度而不是其强制宽度来解释元素(即使隐藏了溢出)。

删除该规则,然后将更改为.fake-selectmax-width:100%just” width:100%(完全适合)。需要注意的是,您可以看到伪选择的所有内容,但是我认为这并不是那么糟糕,它现在可以水平放置。

更新:使用以下小提琴中的当前规则(仅包含实际选择),将字段集的子代约束为正确的宽度。除了删除规则.fake-select并修复注释(从// comment/* comment */,我还注意到小提琴CSS的更改。

现在,我对您的问题有了更好的了解,而小提琴反映了一些进步。我为所有<select>s 设置了默认规则,并.xxlarge为那些您知道会大于480px的规则保留(这仅适用于您知道的宽度#viewport,并且可以将类手动添加到太宽的像素中。只需进行一些测试)

证明


无论您使用哪种修复方式都必须实际应用<select>。实际网站只有<select>。的要点fake-select是使a的布局规则<select>实际上不为a <select>,只是为了表明此行为不是仅发生于<select>元素的浏览器错误。因此,改变风格而.fake-select不是<select>失败的目的。
罗里·奥肯

我用一个.fake-select<select>(与已经存在的框相同)替换了框以进行演示。所有元素都被限制为父对象的宽度(除非单击它,否则下拉选项,每个选项都显示在一行上,但我认为您无法控制)。我还删除了的所有规则.fake-select。当前的小提琴能满足您的需求吗?
Trojan

它不是。width: 100%适用于页面上的长菜单,但不适用于简短菜单。它将短菜单扩展到页面的整个宽度,但是我希望短菜单保持其短宽度。如果有空间,菜单应该是其自然宽度,但是如果菜单对于其父菜单太大,则应为100%宽度。那max-width是应该做的,但是在这种情况下不能做。
罗里·奥肯

我进行了一些更改,将“ all <select>s”与“ long <select>s” 分开,并且现在仅处理背景宽度。
Trojan

#viewport也没有固定的宽度。这就是为什么我在页面上放置“调整视口大小”按钮的原因-因此,无论视口宽度如何,您都可以测试一切正常。就像.fake-select替代真实<select>测试一样,#viewport也替代真实视口。(“视口”基本上是浏览器窗口)。我将其包含#viewport在页面中,以便您可以轻松地看到伸出视口的元素,而不必滚动查看它们。
罗里·奥肯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.