Почему встроенные блоки ломаются после неразрывного пространства?

Некоторые HTML-коды:

<p id='one'>Hello World how are you.&nbsp;<span>Entrepreneur</span></p>

<p>Hello World how are you.&nbsp;<span>Entrepreneur</span></p>

Некоторые CSS:

#one span {
  display: inline-block;
}

p {
  font-family: Arial;
  font-size: 16px;
  width: 200px;
}

Второй абзац ведет себя так, как я ожидаю.

Первое, однако, ведет себя по-разному, из-за того, что span является встроенным блоком.

Мой вопрос: почему диапазон inline-block игнорирует строку &nbsp; и прерывает строку между span и предыдущим словом?

Спасибо!

Пример скрипта здесь.

Ответы

Ответ 1

Итак, похоже, что поведение несовместимо в разных браузерах:

  • В IE11 и последних нескольких версиях я смог проверить это, независимо от того, является ли span встроенным ящиком или блоком встроенного блока, IE уважает свободное пространство и не разделяет span из предыдущего слова.

  • Во всех других браузерах поведение такое же, как описано в вопросе. Безразрывное пространство, как представляется, игнорируется, когда span является встроенным блоком; вместо этого он становится вынужденным на свою линию и отделен от предыдущего слова. Обратите внимание, что пространство без разрыва все еще существует; он появляется в конце первой строки сразу после слова, что можно увидеть, выделив строку в Firefox.

Объяснение, данное некоторыми другими, здесь выглядит довольно звуковым: встроенный блок отформатирован как блок-блок, за исключением встроенной строки, поэтому это может быть причиной того, что он не всегда ведет себя так же, как встроенный блок. Однако я не смог найти ничего в спецификации, которая подтверждает это. Также не объясняет, почему IE ведет себя так, как это делает, или действительно, работает ли IE неправильно или просто по-другому.

В спецификации CSS2.1 указано следующее в разделе 9.2.2, которое хорошо объясняется приведенным выше объяснением:

Ящики встроенного уровня, которые не являются встроенными блоками (например, замененными элементами линейного уровня, элементами встроенного блока и элементами inline-table), называются атомарными ящиками на уровне строки, поскольку они участвуют в их встроенном контексте форматирования как единый непрозрачная коробка.

Но он не полностью описывает взаимодействие между разрывами строк и атомными строчными шкафами, не говоря уже о эффекте, которое не имеет места для этого взаимодействия. Поэтому, к сожалению, не представляется достаточным объяснением поведения любого браузера.


Я даже просмотрел текстовый модуль CSS3, но все, что он должен сказать в отношении разрывов строк и атомных строк, this:

  • Поведение нарушения строки замененного элемента или другого атомарного inline эквивалентно поведению символа замены объекта (U + FFFC).

... и когда я пытаюсь использовать U + FFFC, результаты полностью ненадежны:

<p id='one'>Hello World how are you.&nbsp;<span>Entrepreneur</span></p>

<p>Hello World how are you.&nbsp;<span>Entrepreneur</span></p>

<p>Hello World how are you.&nbsp;&#xfffc;</p>

А именно:

  • IE ведет себя наиболее последовательно, разбивая все три абзаца одинаково.

  • Firefox прерывает строку с символом так же, как и второй абзац, учитывая пространство без разрыва.

  • Chrome даже не пытается отобразить символ.

Возможно, я просто неправильно понимаю цитату из текстового модуля CSS3, возможно, браузеры не выполняют определенные контрольные символы правильно, я не могу сказать наверняка. Но, во всяком случае, я начинаю сомневаться, что это поведение действительно определено в любой спецификации CSS вообще.

Ответ 2

В спецификациях нет строгого ответа, поскольку спецификации HTML и CSS не определяют точные правила для разрыва строки. HTML 4.01 говорит: "Иногда авторам может потребоваться предотвратить разрыв строки между двумя словами. Объект &nbsp; (&#160; или &#xA0;) действует как пространство, в котором пользовательские агенты не должны вызывать разрыв строки." Но на самом деле это не требует, чтобы браузеры подчинялись этому.

Браузеры, которые не рассматривают &nbsp; как предотвращение разрыва строки перед встроенным блоком, могут это оправдать, заявив, что &nbsp; просто обозначает символ NO-BREAK SPACE *, который определен (в Unicode) как предотвращающий разрывы строк, когда он появляется между символами. Здесь он находится между символом и элементом встроенного блока, который (неофициально говоря) воспринимается как черный ящик в форматировании строк, т.е. Занимает некоторое пространство, но не рассматривается как символ или как содержащий символы.

Обратите внимание, что ситуация аналогична, если вы удалите &nbsp;. Строка типа "you.Entrepreneur" не нарушена, но если вы сделаете "Предприниматель" встроенным блоком, строка может сломаться.

Аналогичные соображения применимы к изображениям. Браузеры не могут почитать &nbsp; между текстом и изображением, потому что здесь также невозможен ПРОБЕЛ NO-BREAK между символами.

Вы все же можете предотвратить разрывы строк, но вам нужно быть более явным, например.

<p>Hello World how are <nobr>you.&nbsp;<span>Entrepreneur</span></nobr></p>

Im использует nobr в примере для простоты. Вместо этого вы можете использовать стандартный элемент и установить для него white-space: nowrap (это свойство CSS, несмотря на его имя, влияет не только на обработку пробелов, но и на этот параметр, предотвращает разрывы строк в контенте).

Ответ 3

Я бы предположил, что это связано с тем, что внутристрочный блок визуализирует внутреннюю часть элемента как блока. Поскольку у вас нет пробела между текстом и диапазоном, он заставляет перерыв, а затем отбрасывает его на другую строку.

Не заметил этого раньше, хотя в основном это предположение.

Ответ 4

Единственное, что я могу найти, это

Согласно https://developer.mozilla.org/en-US/docs/Web/CSS/display

Для встроенного блока

Элемент создает блок-блок, который будет протекать с окружающим контентом, как если бы он был одним встроенным ящиком (вел себя как замененный элемент)

рядный

Элемент генерирует один или несколько встроенных блоков элементов.

Я предполагаю, что поскольку inline-block генерирует элемент блока, так что неиспользуемое пространство не работает так, как ожидалось, когда пролет обычно равен inline