Ошибка Firefox с float и nowrap?

В этой скрипке, почему B выпадает из желтого контейнера?

http://jsfiddle.net/en7qfto1/

Это не происходит в Chromium.

Это ошибка Firefox?

Это код:

<style>
.a, .b
{
    display: inline-block;
    background: lightblue;
}

.b
{
    float: right; 
}

.c
{
    background: yellow;
    white-space: nowrap;
}
</style>

<div class=c>
    <a class=a>A</a>
    <a class=b>B</a>
</div>

Ответ 1

Да, это ошибка. Вы можете найти билет Bugzilla здесь.

Дэвид Барон указывает на причину, которая указывает в самом коде, что это связано с известным ограничением:

Причина этого кода в nsLineLayout:: ReflowFrame:

    if (psd->mNoWrap) {
      // If we place floats after inline content where there's
      // no break opportunity, we don't know how much additional
      // width is required for the non-breaking content after the float,
      // so we can't know whether the float plus that content will fit
      // on the line. So for now, don't place floats after inline
      // content where there no break opportunity. This is incorrect
      // but hopefully rare. Fixing it will require significant
      // restructuring of line layout.
      // We might as well allow zero-width floats to be placed, though.
      availableWidth = 0;
    }

Интересно, правильно ли это сделать:

  • вообще не использовать доступную ширину или
  • сделать доступную ширину бесконечной, так как содержимое nowrap никогда не собирается обтекать float в любом случае

(Теоретически правильное решение - не пытаться разместить float до следующей возможности разрыва. Интересно, делают ли другие браузеры.)

Я на самом деле думаю, что это вполне выполнимо; мы уже откладываем компоновку поплавков в mBelowCurrentLineFloats; нам просто нужно сделать что-то подобное и сообщить о макете линии при разрыве. Однако это далеко не тривиально. (Мы также должны немедленно поместить float, если у нас сейчас есть возможность перерыва... Я думаю.)

Я тоже удивляюсь, что это делают другие браузеры (Chrome и IE ведут себя одинаково, помещая float в ту же строку, что и встроенный блок). К сожалению, я не полностью понимаю взаимодействие между поплавками и разрывы строк, поэтому я больше не могу комментировать.

Ответ 2

Я столкнулся с той же ошибкой, и для меня лучшим решением было использовать эквивалентный макет flexbox: http://jsfiddle.net/nquyefaq/.

В Chrome, Firefox и IE11 он работает одинаково:

  • Оба объекта отображаются в одной строке с поведением типа inline-block.
  • Второй элемент выравнивается по правому краю. (Вместо float: right он использует margin-left: auto.)
  • Если элементы имеют фиксированную ширину (my do), второй элемент опускается на следующую строку, если контейнер становится слишком узким.

Я надеюсь, что это поможет кому-то еще найти способ обхода.