<fieldset> изменяет размер неправильно; кажется, имеет неустранимую `min-width: min-content`
Проблема
У меня есть <select>
, где одно из его текстовых значений <option>
очень велико. Я хочу изменить размер <select>
, чтобы он никогда не был шире его родительского элемента, даже если он должен отключить отображаемый текст. max-width: 100%
должен сделать это.
Перед изменением размера:
![the page before resize, showing the whole <code>select</code>]()
Что я хочу после изменения размера:
![my desired page after resize, with the <code>select</code> clipping its contents]()
Но если вы загрузите этот пример jsFiddle и измените размер ширины панелей результатов меньше, чем на <select>
, вы можете видеть, что выбор внутри <fieldset>
не позволяет уменьшить его ширину.
Что я действительно вижу после изменения размера:
![my current page after resize, with a scroll bar]()
Однако эквивалентная страница с <div>
вместо <fieldset>
действительно масштабируется должным образом. Вы можете видеть, что легче проверить свои изменения, если у вас a <fieldset>
и a <div>
рядом друг с другом на одной странице. И если вы удаляете окружающие теги <fieldset>
, то выполняется изменение размера. Тег <fieldset>
каким-то образом вызывает разрыв горизонтального изменения размера.
Действия <fieldset>
выглядят так, как будто существует правило CSS fieldset { min-width: min-content; }
. (min-content
означает грубую наименьшую ширину, которая не приводит к переполнению дочернего элемента.) Если я заменил <fieldset>
на <div>
с min-width: min-content
, он выглядит точно так же. Тем не менее, нет правила с min-content
в моих стилях, в таблице стилей по умолчанию в браузере или в Firebugs CSS Inspector. Я попытался переопределить каждый стиль, видимый в <fieldset>
в Firebugs CSS Inspector и в таблице стилей по умолчанию Firefox forms.css, но это не помогло. В частности, переопределение 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, который должен работать, но isnt:
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, который больше похож на веб-страницу Im, фактически пытающуюся исправить. Вы можете видеть из этого, что <select>
не проблема - встроенный блок div
также не может изменять размер. Хотя этот пример более сложный, я предполагаю, что исправление для простого вышеизложенного случая также устранит этот более сложный случай.
[Изменить: см. ниже сведения о поддержке браузера.]
Любознательная вещь об этой проблеме заключается в том, что если вы установили div.wrapper { width: 50%; }
, <fieldset>
перестает изменять размер в точке, тогда полная -size <select>
ударил бы край окна просмотра. Изменение размера происходит так, как будто <select>
имеет width: 100%
, хотя <select>
выглядит как width: 50%
.
![after resize with 50%-width wrapper div]()
Если предоставить <select>
сам width: 50%
, это поведение не происходит; ширина просто устанавливается правильно.
![after resize with 50%-width select]()
Я не понимаю причину этой разницы. Но это может быть не актуально.
Я также нашел очень похожий вопрос HTML-поле позволяет детям неограниченно расширяться. Ответчик не смог найти решение и догадывается, что нет решения, кроме удаления <fieldset>
. Но Im интересно, если действительно невозможно сделать отображение <fieldset>
правильным, почему? Что в <fieldset>
s spec или CSS по умолчанию вызывает такое поведение? Это особое поведение, вероятно, где-то задокументировано, так как работают несколько браузеров.
Основная цель и требования
Причина, по которой я пытаюсь сделать это, - это часть написания мобильных стилей для существующей страницы с большой формой. Форма имеет несколько разделов, и одна ее часть завернута в <fieldset>
. На смартфоне (или, если вы сделаете окно браузера маленьким), часть страницы с <fieldset>
намного шире, чем остальная часть формы. Большая часть формы ограничивает его ширину просто тонкой, но раздел с <fieldset>
не делает этого, заставляя пользователя уменьшать масштаб или прокручивать вправо, чтобы увидеть весь этот раздел.
Не забудьте просто удалить <fieldset>
, поскольку он создан на многих страницах большого приложения, и я не уверен, что на нем могут зависеть селекторы в CSS или JavaScript.
Я могу использовать JavaScript, если мне нужно, и решение для JavaScript лучше, чем ничего. Но если JavaScript - единственный способ сделать это, Id будет любопытно услышать объяснение, почему это невозможно, используя только CSS и HTML.
Изменить: поддержка браузера
На сайте мне нужно поддерживать Internet Explorer 8 и более поздние версии (мы просто отказались от поддержки IE7), последнего Firefox и новейшего Chrome. Эта страница также должна работать на смартфонах iOS и Android. Некоторое ухудшение, но все еще пригодное для использования поведение приемлемо для Internet Explorer 8.
Я протестировал мой сломанный fieldset
пример в разных браузерах. Он фактически работает в этих браузерах:
- Internet Explorer 8, 9 и 10
- Chrome
- Chrome для Android
Он разбивается в этих браузерах:
- Firefox
- Firefox для Android
- Internet Explorer 7
Таким образом, единственным браузером, который меня волнует, что текущий код работает, - Firefox (как на рабочем столе, так и на мобильном устройстве). Если код был исправлен, поэтому он работал в Firefox, не нарушая его в каких-либо других браузерах, это решило бы мою проблему.
Шаблон HTML-сайта использует условные комментарии Internet Explorer для добавления классов .ie8
и .oldie
к элементу <html>
. Вы можете использовать эти классы в своем CSS, если вам нужно обойти различия стилей в IE. Добавленные классы такие же, как в эта старая версия HTML5 Boilerplate.
Ответы
Ответ 1
Обновление (25 сентября 2017 г.)
К моему большому облегчению, ошибка Firefox, описанная ниже, исправлена с Firefox 53, и ссылка на этот ответ наконец-то была удален из документации Bootstrap.
Исправление
В 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. Поскольку для этого требуется только Gecko, вы можете с полным правом использовать @-moz-document
-one Собственные расширения CSS Mozilla - чтобы скрыть его от других браузеров:
@-moz-document url-prefix() {
fieldset {
display: table-cell;
}
}
(Здесь jsFiddle demo.)
Это исправляет вещи, но если вы что-то вроде меня, ваша реакция была чем-то вроде...
Есть причина, но это не очень.
По умолчанию представление элемента fieldset абсурдно и по существу невозможно указать в CSS. Подумайте об этом: граница fieldset исчезает там, где она перекрывается элементом легенды, но фон остается видимым! Невозможно воспроизвести это с помощью любой другой комбинации элементов.
В довершение всего, реализации полны уступок в отношении унаследованного поведения. Одним из таких является то, что минимальная ширина набора полей никогда не меньше, чем внутренняя ширина его содержимого. WebKit дает вам возможность переопределить это поведение, указав его в таблице стилей по умолчанию, но Gecko² продвигается дальше, а применяет его в механизме рендеринга.
Однако внутренние элементы таблицы представляют собой специальный тип фрейма в Gecko. Размерные ограничения для элементов с этими наборами значений display
вычисляются в отдельный путь кода, полностью обходя минимальную ширину, наложенную на поля.
Снова - ошибка была исправлена с Firefox 53, так что вам не нужен этот взлом, если вы только нацеливаетесь на новые версии.
Использует @-moz-document
безопасно?
Для этой одной проблемы да. @-moz-document
работает так, как предполагалось, во всех версиях Firefox вплоть до 53, где эта ошибка исправлена.
Это не случайно. Отчасти из-за этого ответа ошибка в limit @-moz-document
для таблиц стилей пользователя /UA была сделана в зависимости от того,.
Помимо этого, я больше не рекомендую использовать @-moz-document
исключительно для того, чтобы использовать Firefox в вашем CSS, несмотря на другие ресурсы.³
¹ Значение может быть префиксом. По словам одного читателя, это не влияет на Android 4.1.2 Stock Browser и, возможно, на другие старые версии; У меня не было времени проверить это.
² Все ссылки на источник Gecko в этом ответе относятся к 5065fdc12408 changeet, совершенному 29 июля 2013 года; вы можете сравнить заметки с самой последней версией из Mozilla Central.
³ См., например, SO # 953491: Ориентация только на Firefox с CSS и CSS-трюки: CSS-хаки, ориентированные на Firefox для широко разрекламированных статей на высокопоставленных сайтах.
Ответ 2
Safari для iOS с выбранным ответом
Я нашел ответ от Джордана Грея, чтобы быть особенно полезным.
Однако, похоже, он не решил эту проблему для iOS Safari для меня.
Проблема для меня просто в том, что для набора полей не может быть автоматической ширины, если элемент внутри имеет максимальную ширину в% ширины.
Исправить проблему
Просто установка набора полей на 100% ширину контейнера, похоже, обойдет эту проблему.
Пример
fieldset {
min-width: 0;
width: 100%;
}
Пожалуйста, обратитесь к приведенным ниже примерам работы - если вы удалите% width из набора полей или замените его на auto, он не будет продолжать функционировать.
JSFiddle | Codepen
Ответ 3
Ive боролся в течение многих часов с этим, и в основном, браузер применяет вычисляемый стиль, который вам нужно переопределить в вашем CSS. Я забыл точное свойство, которое устанавливается на элементах fieldset
по сравнению с div
(возможно, min-width
?).
Моим лучшим советом было бы изменить ваш элемент на div
, скопировать вычисленные стили из вашего инспектора, а затем вернуть элемент обратно в fieldset
и сравнить вычисленные стили, чтобы найти виновника.
Надеюсь, что это поможет.
Обновление: Добавление display: table-cell
помогает в браузерах, отличных от Chrome.
Ответ 4
.fake-select { white-space:nowrap; }
заставлял fieldset интерпретировать элемент .fake-select
по его первоначальной ширине, а не по его принудительной ширине (даже когда переполнение скрыто).
Удалите это правило и измените .fake-select
max-width:100%
на width:100%
и все будет соответствовать. Предостережение состоит в том, что вы видите все содержимое поддельного выбора, но я не думаю, что это все так плохо, и теперь оно подходит по горизонтали.
Обновление: с текущими правилами в следующем скрипте (который содержит только реальные выборки), дети набора полей ограничены для исправления ширины. Помимо удаления правил для .fake-select
и исправления комментариев (от // comment
до /* comment */
, я отметил изменения в скрипте CSS.
Теперь я понимаю вашу проблему лучше, и скрипка отражает некоторый прогресс. Я устанавливаю правила по умолчанию для всех <select>
s, а зарезервировать .xxlarge
для тех, которые, как вы знаете, будут шире 480 пикселей (и это работает только потому, что вы знаете) ширину #viewport
и можете вручную добавьте класс в слишком широкий. Просто нужно немного тестирования)
Доказательство