Почему процентная маржа вызывает новую строку?
<div style = "float : left; background-color: #dd3fb8;">
<a style = "margin-left : 10%;">a</a>
<a>b</a>
<a>c</a>
</div>
В приведенном выше примере буква "c" будет на новой строке, но если бы я установил единицу "margin-left" to px, "c" был бы на той же строке, что и "a" и "b". Почему это происходит?
Ответы
Ответ 1
К сожалению, спецификация CSS2.1, похоже, не имеет четкого ответа на этот вопрос. Фактически, я бы сказал, что это хорошо в сфере поведения undefined.
Вот соответствующие пункты, которые я могу найти:
-
Поплавки без указанной ширины будут сжиматься, чтобы соответствовать их содержимому. В случае поплавков с только встроенным контентом float нужно сделать достаточно широким, чтобы соответствовать его содержимому на одной строке (несмотря на явные разрывы строк) и не более.
-
Процентные отчисления рассчитываются в зависимости от ширины содержащего блока.
Обратите внимание, что в нем говорится:
Если ширина этого блока зависит от этого элемента, то результирующий макет undefined в CSS 2.1.
... но, насколько я вижу, поведение согласовано во всех браузерах.
При этом причина, по которой эта инструкция применяется, заключается в том, что, поскольку край встроенного элемента попадает в пределы содержимого поплавка, можно сказать, что ширина поплавка (содержащего блок встроенных элементов) зависит на этом элементе (элемент с запасом).
Вот что я могу вывести на основе вышеперечисленных пунктов:
-
Когда маржа указана в процентах, ширина поплавка рассчитывается без учета маржи, поскольку невозможно рассчитать маржу до тех пор, пока не будет определена ширина поплавка.
Затем рассчитывается маржа на основе используемой ширины поплавка, а буква "c" обертывается на новую строку в результате продвижения вперед по краю на "a". Ширина поплавка не изменяется.
Опять же, ни одно из этих действий не указано вообще, и поэтому технически это не нарушает спецификацию. Однако это кажется разумным.
-
Когда маржа указана как значение пикселя, сначала вычисляется маржа. Затем вычисляется ширина поплавка с учетом этого поля (помните, что горизонтальные поля применимы к встроенным элементам как обычно). В соответствии с алгоритмом усадки в соответствие, это предпочтительная ширина: достаточно широкая, чтобы содержать все встроенные элементы в одной строке.
В отличие от процентных полей, это очень четко, поскольку в реализациях не должно быть проблем с вычислением вычислений абсолютных значений для полей вначале.
Мне было бы сложно называть это ошибкой в любом из браузеров, тем более, что все они ведут себя последовательно.
Наконец, конечно, вы можете избежать этого поведения undefined полностью, просто по возможности используя ваши поплавки с явной шириной. Это помогает понять, почему вы должны это делать.
Ответ 2
Поскольку ваш div
плавает, а его width
- auto
(неявно), применяется http://www.w3.org/TR/CSS21/visudet.html#float-width:
Если "width" вычисляется как "auto", используемое значение представляет собой ширину "shrink to-fit".
"shrink-to-fit" width в основном означает, что элемент должен быть таким же широким, как и его содержимое.
Теперь без margin-left
это не проблема: все три из ваших a
элементов являются встроенными элементами, которые содержат определенный символ каждый - достаточно легко определить их индивидуальную ширину и добавить их.
Но теперь вы хотите margin-left
в процентах, и здесь все усложняется - если мы посмотрим на определение для margin-left
, он говорит:
Проценты: см. ширину содержащего блока
Теперь это оставляет нас в немного рассола, так как ширина содержащего блока (который устанавливается элементом floated div
) вычисляется на основе его содержимого - но теперь этот margin-left
будет меняться общая ширина этого содержимого, но сама по себе зависит от width
содержащего блока, который он сам влияет...
Это классическая проблема двух измерений, которые зависят друг от друга... и что в этом случае в основном неразрешимы.
http://www.w3.org/TR/CSS21/box.html#margin-properties говорит,
Процент вычисляется по ширине сгенерированного блока, содержащего блок. [...]
Если ширина этого блока зависит от этого элемента, то итоговый макет undefined в CSS 2.1.
Изменить: В основном то же, что и в BoltClock, сказанное в его ответе, просто взяло меня немного дольше...
Ответ 3
Ссылка имеет левый край 10%, 10% от насколько? Родительский элемент плавает слева, что означает, что он не имеет собственной ширины, вместо этого он расширяет столько, сколько его содержимое. Если вы попытаетесь подражать тому, как браузер вычислит полученный в результате поле, и вы окажетесь в исправлении:
- Пусть ширина содержимого (и, следовательно, контейнера) равна 30px
- Добавить 10% от 30px = 3px левого поля к ссылке
- Полученная ширина контейнера равна 30 + 3 = 33px
Это создает цикл, в котором маржа увеличивается по мере увеличения внешней ширины и увеличивается внешняя ширина с увеличением поля (10% от 33 пикселей = 3.3 пикселей означает, что ширина контейнера изменяется с 33 пикселей до 33,3 пикселей и т.д.). Для таких вычислений полученное поведение undefined (как указано CBroe).
Браузер, похоже, избегает цикла и придерживается ширины 30 пикселей. Поля 3px, введенные после вычисления, приводят к тому, что третье звено переходит во вторую строку. Браузер снова избегает цикла, придерживаясь ширины 30 пикселей.