Почему ширина применяется к кнопке с встроенным дисплеем?
Согласно MDN, a button
является встроенным элементом.
Однако элементы кнопки стиль по умолчанию с display: inline-block
(см. этот вопрос)
button, textarea,
input, select { display: inline-block }
Пока все хорошо.
Однако:
Если теперь я устанавливаю кнопку с display:inline
- ширина применяется!
button,
div {
width: 200px;
border: 1px solid red;
display: inline;
}
<button>button</button>
<div>div</div>
Ответы
Ответ 1
Как уже упоминалось в комментариях, я уверен, что это связано с особенностями рендеринга, характерным для браузера, так как это типично для элементов формы. То, что я считаю, происходит, когда вы устанавливаете display: inline
на кнопку, это... ничего. Фактически он совпадает с типичным по умолчанию браузером display: inline-block
, на котором применяется свойство width
.
Обратитесь к разделу 10.2, в котором описывается свойство width
. В частности, это объясняет, почему именно свойство width
не применяется к встроенным элементам (или встроенным блокам):
Это свойство не применяется к незанятым встроенным элементам. Ширина содержимого незаменимых ячеек встроенного элемента - это размер отображаемого содержимого внутри них (до любого относительного смещения дочерних элементов). Напомним, что встроенные коробки поступают в строковые поля. Ширина строк строк задается их содержащим блоком, но может быть закорочена наличием поплавков.
Короче говоря, это потому, что содержимое встроенных элементов находится в строках. Невозможно напрямую контролировать ширину строки строки; он полностью определяется содержащим блоком и любыми случайными поплавками. Вы можете увидеть пример рендеринга строки в раздел 9.4.2, в котором описываются контексты форматирования.
Если display: inline
действительно сделал кнопку рендеринга в виде встроенного блока, все его содержимое прольется через, и оно больше не будет выглядеть, или как кнопка. Имеет смысл хотеть предотвратить это, и я думаю, что именно то, что делают браузеры.
Так что же они делают, чтобы предотвратить это? Является ли кнопка замененным элементом? Не могу сказать точно. Но обратите внимание: в разделе раздел 9.2.2 говорится:
Ящики встроенного уровня, которые не являются встроенными блоками (например, замененными элементами линейного уровня, элементами встроенного блока и элементами inline-table), называются атомарными ящиками на уровне строки, поскольку они участвуют в их встроенном контексте форматирования как единый непрозрачная коробка.
В Разделе 10 явно не упоминаются атомарные ящики на уровне строки, но в нем есть разделы для вычисления измерений для встроенных замещаемых элементов, а также элементы встроенного блока, заменяемые или не замененные, все из которых считаются атомными линиями, как упомянутое выше. Во всех этих случаях свойство width
применяется как обычно, если оно не auto
.
Таким образом, в то время как он все еще спорно или нет кнопка заменяемый элемент, он, вероятно, не имеет значения для целей данного вопроса. Но это все еще какой-то атомный встроенный элемент, поскольку он все еще участвует в встроенном контексте форматирования. Однако для того, что стоит, кажется, он сжимается, чтобы соответствовать его содержимому, если вы не устанавливаете ширину, поэтому его поведение, вероятно, ближе к поведению встроенного блока в этом случае. Тогда можно было бы сказать, что фактическое значение display
становится inline-block
, хотя это никогда не отражается в инструментах разработчика, потому что вычисляемое значение делает не изменится (опять-таки побочный эффект поведения, характерного для браузера).
Ответ 2
Так как Boltclock, я не думаю, что есть простой ответ на этот вопрос, это как бы свалка моих мыслей по этому вопросу в качестве ответа, но я надеюсь, что это будет информативным.
Хотя свойство отображения CSS поверхностно довольно просто, оно фактически содержит множество аспектов. Проект черновика уровня 3 css-display отражает некоторые из этих сложностей, но по-прежнему не охватывает его адекватно.
Спецификация HTML5 указывает рендеринг элементов <button>
:
Когда привязка кнопки применяется к элементу кнопки, элемент как ожидается, будет отображаться как "встроенный блок", который отображается как кнопка, содержимое - это содержимое элемента.
В блоке inline-block
есть несколько аспектов:
Это означает, что он участвует в встроенном контексте форматирования в строке строки. Он течет последовательно с другими элементами, находящимися в одной строке. Содержимое линейного окна может быть выровнено по центру с свойством text-align:center
на его контейнере, а поле строки укорачивается, избегая плавающих элементов.
2. Применяет свойство width, а значение auto shrink-to-fit
В отличие от не замененных элементов display:inline
применяется значение ширины. Но также, если значение ширины не задано, для определения ширины применяется алгоритм с усадки. Это похоже на плавающие элементы или элементы display:table
, но отличные от display:block
элементов, которые максимально широки, если не задана ширина. Он также не похож на замененные встроенные элементы и заменяет встроенные элементы блока, которые, если ширина не указана, используют свою внутреннюю ширину, если они имеют одно значение и значение по умолчанию 300 пикселей, если они этого не делают. Термоусадка - это бессмысленная концепция для замененных элементов.
Элементы блока контейнера состоят из стека строк. Содержимое перетекает из одного строкового блока в другое, а высота элементов встроенного блока растет (при условии переполнения), чтобы полностью содержать все строки строки.
Когда элемент inline-block содержит несколько строк, его базовая линия является последней из этих строк. Это отличается от поплавков или элементов display:table-cell
, которые также сжимаются к месту, блокируют элементы контейнера. Поплавки находятся вне нормального потока, поэтому у них нет базовой линии, элементы display:table-cell
имеют базовую линию, которая является базовой линией их первой строки строки. Кнопка, которая имеет несколько строк, выравнивает по вертикали в соответствии с этим последним правилом строки.
Теперь это нормально для настройки отображения по умолчанию. и требование рендеринга HTML5 означает, что используемое значение отображения для кнопок inline-block
, даже если указанное значение inline
. Но он не учитывает поведение, когда указанное значение block
. В этом случае элемент имеет разрыв строки до и после него, а margin:auto
центрирует поле как элемент display:block
, и это не то, что можно было бы ожидать от inline-block
.
Однако его ширина для заданного значения auto
сжимается до соответствия, как встроенный блок, тогда как ожидаемое поведение для display:block
по возможности является максимально возможным. Насколько мне известно, единственное отображаемое значение, которое ведет себя так: display:table
, но нет ничего другого, чтобы предположить, что используется display:table
.
Так что в спецификации нет ничего, что можно найти точно. Мы можем только надеяться, что когда спецификация css-display завершится, она будет охватывать это поведение.
Ответ 3
Существует 2 типа элементов.
- Незаменяемые элементы
- Замененные элементы
Button
принадлежит к категории замещенных элементов.
Вы можете найти более подробную ссылку ниже.
Итак, для Button
, согласно spec, он становится правильным.
Встроенные, незаменяемые элементы
Свойство width
не применяется. Вычисленное значение auto
для margin-left
или margin-right
становится используемым значением 0
.
Встроенные, замененные элементы (Этот раздел относится к Button
)
Вычисленное значение auto
для margin-left
или margin-right
становится используемым значением 0
.
Если height
и width
оба имеют вычисленные значения auto
, и этот элемент также имеет собственный width
, то это внутреннее width
является используемым значением width
.
Если height
и width
оба имеют вычисленные значения auto
, и элемент не имеет собственного width
, но имеет внутреннее height
и внутреннее отношение; или если width
имеет вычисленное значение auto
, height
имеет некоторое другое вычисленное значение, и элемент имеет внутреннее отношение; то используемое значение width
равно:
(used height) * (intrinsic ratio)
Если height
и width
оба имеют вычисленные значения auto
, и элемент имеет внутреннее отношение, но не имеет встроенных height
или width
, тогда используемое значение width
равно undefined в CSS 2.1. Однако предполагается, что если содержащийся блок width
сам по себе не зависит от замещенного элемента width
, то используемое значение width
вычисляется по уравнению ограничения, используемому для блочных, незаменяемых элементов в нормальном потоке.
Если width
имеет вычисленное значение auto
, а элемент имеет собственный width
, то это внутреннее width
является используемым значением width
.
Если width
имеет вычисленное значение width
, но ни одно из приведенных выше условий не выполняется, тогда используемое значение width
становится 300px
. Но если 300px
слишком велико, чтобы соответствовать устройства, UA должны использовать width
самого большого прямоугольника, который имеет соотношение 2: 1 и подходит для устройства.
Ответ 4
Попробуйте установить маржу на -2px
.
button,
div {
width: 200px;
border: 1px solid red;
display: inline;
margin:-2px -2px -2px -2px;
}
Причина в том, что между элементами все еще остается пространство, потому что даже display:inline;
не удаляет все пространство. Он удаляет стиль по умолчанию для блока, который обычно применяется браузером. Тем не менее, край -2px удаляет все пространство между кнопкой и div.
FIDDLE