Подтвердить что ты не робот

Flexbox размер шрифта не работает правильно при использовании FontAwesome

Я сталкиваюсь с очень странным поведением flexbox для моего макета страницы. Я использую FontAwesome для отображения определенных символов.

В принципе, у меня есть 2 flexbox элемента внутри другого элемента flexbox, и эти дочерние элементы отображают более широкий, чем родительский элемент.

1) У меня есть объект .content__header, который отображается как объект flexbox внутри другой серии объектов flexbox.

2) Объект .content__header содержит 2 дочерних объекта: .breadcrumb и .page_tools. Эти дочерние объекты также отображаются как элементы гибкости.

3) Внутри объекта .breadcrumb у меня есть несколько объектов span (.breadcrumb__test), содержимое которых заменяется FontAwesome значок. Замена выполняется с использованием абсолютного позиционирования псевдоэлемента ::after.

4) Когда я удаляю все HTML-элементы .breadcrumb__text или просто удаляю определение .breadcrumb__text::after из моей таблицы стилей - которое определяет использование шрифта FontAwesome - дочерних объектов (.breadcrumb и .page_tools) рендеринга на их правильной ширине. Поэтому я предполагаю, что это имеет какое-то отношение к замене значком FontAwesome.

.breadcrumb__text::after {
  font-family: "FontAwesome";
  font-weight: 400;
}

Визуальное представление проблемы

Зеленая линия указывает разницу между шириной родителя и фактическим содержимым.

Визуальное представление проблемы

Код и скрипт ниже.

Браузер: Google Chrome 47.0.2526.106 м


Скрипки:

https://jsfiddle.net/44gymmw2/6/


Update

Когда я удаляю text-indent: 100%; из определения CSS .breadcrumb__text, .breadcrumb отображает как предполагалось. Однако, когда я оставляю text-indent на месте и удаляю определение .breadcrumb__text::after в верхней части таблицы стилей (как описано выше), он также корректно отображает.

Возможно, эта проблема имеет какое-то отношение к FontAwesome или text-indent и flexbox?


Код

HTML

<body>

  <div class="layout_wrapper">

    <div class="layout_container__content">
      <div class="content">
        <header class="content__header">

          <div class="breadcrumb">
            <span class="breadcrumb__text  breadcrumb__text--first">From </span><a class="breadcrumb__link" href="#">Dashboard</a><span class="breadcrumb__text"> to </span><a class="breadcrumb__link" href="#">Find records</a><span class="breadcrumb__text"> to </span>
            <h1 class="breadcrumb__current">Kylo Ren’s Command Shuttle™</h1>
          </div>

          <ul class="page_tools">
            <li class="page_tools__item">
              <button type="button" class="button  button--primary">Save</button>
            </li>
            <li class="page_tools__item">
              <button type="button" class="button">Cancel</button>
            </li>
          </ul>

        </header>

      </div>
    </div>

    <div class="layout_container__sidebar">

      <div class="sidebar">
        <article class="widget">
          <h2 class="widget__title">Widget</h2>
        </article>
      </div>

    </div>

  </div>
</body>

CSS

/* Removing this makes it work */
.breadcrumb__text::after {
  font-family: "FontAwesome";
  font-weight: 400;
}

/* Don't remove anything below */
.breadcrumb__text--first {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

* {
    box-sizing: inherit;
}

html {
    box-sizing: border-box;
}

html, body {
    padding: 0;
    margin: 0;
}

body {
  display: flex;
  flex-flow: column nowrap;
  align-items: stretch;
}

.layout_wrapper {
  flex: 1 1 auto;
  display: flex;
  flex-flow: row nowrap;
  align-items: stretch;
}

.layout_container__content {
  flex: 0 0 75vw;
}

.layout_container__sidebar {
  flex: 0 0 25vw;
}

.content {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
  align-items: stretch;
}

.content__header {
  outline: 1px solid blue;
  background-color: #434649;
  color: #ffffff;
  flex: 0 0 100%;
  display: flex;
  flex-flow: row nowrap;
}

.breadcrumb {
  outline: 3px dashed purple;
  flex: 1 1 auto;
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
}

.breadcrumb__text {
  flex: 0 0 2em;
  overflow: hidden;
  text-indent: 100%;
  white-space: nowrap;
  position: relative;
  text-align: center;
}

.breadcrumb__text::after {
  content: '\f105';
  padding: 0;
  text-indent: 0;
  position: absolute;
  top: 0;
  right: 0;
  width: 100%;
}

.breadcrumb__text--first {
  flex: 0 0 0;
}

.breadcrumb__text--first::after {
  content: none;
}

.breadcrumb__link {
  flex: 0 0 auto;
  display: inline-block;
  font-size: 0.8571rem;
}

.breadcrumb__current {
  flex: 0 0 100%;
  margin: 0;
}

.page_tools {
  outline: 3px dashed red;
  flex: 0 0 auto;
  display: flex;
  flex-flow: row nowrap;
  list-style: none outside none;
}
4b9b3361

Ответ 1

Я только что просмотрел ваш код и заметил следующее:

  • Есть ненужные (вложенные) контейнеры flex (вызванные использованием display: flex;).
  • Есть ненужные объявления, связанные с гибкостью (просто объявление поведения по умолчанию, например flex-flow: row no-wrap; и align-items: stretch).
  • Существует несколько ненужных объявлений в контексте различных несвязанных селекторов. Вероятно, при тестировании/отладке остаются декларативные объявления.

Тем не менее, давайте продолжим вашу проблему. Это не очевидно, так что это требует некоторого введения.

Pangloss представляет важный компонент вашей проблемы, который влияет на использование text-indent. Из W3:

Коробка имеет отступ по отношению к левому (или правому, для правого налево) краю строки строки. Пользовательские агенты должны отображать этот отступ в виде пробела.

[...]

Если значение text-indent либо отрицательно, либо превышает ширину блока, это первое поле, описанное выше, может переполнять блок. Значение overflow будет влиять на видимость текста, который переполняет блок.

Другими словами: text-indent влияет на размеры окна, к которому вы его применили.

Вы объявили overflow: hidden; на .breadcrumb__text. Очевидно, что для того, чтобы эта декларация имела желаемый эффект, для поля, к которому вы применили его, требуется width, иначе он не будет иметь обрезающий край.

.breadcrumb__text должен получить свою ширину от объявления flex-basis (в частности, flex: 0 0 2em;), примененного к нему. Ну... это не происходит, по крайней мере, не так, как вы ожидали. Несмотря на то, что его ширина кажется 2em, по какой-то причине она не вызывает поведение переполнения, как должно. Это, кажется, ошибка в конкретной версии Chrome, которую вы используете, поскольку она исправлена ​​в Canary (например, версия 49 и выше).

Итак: похоже, это проблема с реализацией flexbox в Chrome. Тем не менее, с учетом этих знаний, ваша проблема может быть исправлена ​​несколькими способами. Некоторые примеры:

text-indent: -100%

Использование text-indent: -100% устраняет вашу проблему, поскольку она устраняет лишние пробелы в правой части затронутых элементов. (→ jsfiddle)

width: 2em

Вы можете добавить объявление width: 2em в .breadcrumb__text. Это устранит непредвиденное поведение объявления flex-basis. (→ jsfiddle)

overflow: hidden; в родительском контейнере

Добавление overflow: hidden; в .breadcrumbs устраняет вашу проблему. Теперь родительский контейнер имеет обрезающий край и обрабатывает пробелы, вызванные использованием text-indent: 100%. (→ jsfiddle)

Заключительные замечания

Flexbox - это мощный режим компоновки, и с ним очень удобно экспериментировать. Но алгоритмы сложны, а реализации браузеров еще не освобождены. Обязательно учитывайте это при использовании flexbox.

Еще одна проблема, когда вы смотрите на свой код, - это то, как вы используете flexbox. flexbox есть для вас, но вам не обязательно заменять любой другой способ работы с макетом. display: inline-block; или display: table;, или даже float может выполнить задание, не введя сложность вложенных контейнеров flex.

Ответ 2

шрифт FontAwesome не является основной причиной. Это определение макета H1 "block", установленное по умолчанию в вашем браузере. Добавьте этот стиль в свой класс breadcrumb__current. См. https://jsfiddle.net/44gymmw2/9/

 word-wrap:break-word 

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

h1 { display: inline; }

Или вы можете обернуть этот текст в другой элемент, например, span.

Ответ 3

Я думаю, что проблема вызвана правилом text-indent:100%, которое добавило лишнее пространство в правой руке.

Свойство text-indent указывает, сколько горизонтального пространства должно следует оставить перед началом первой строки текстового содержимого элемент. <percentage> значение относительно содержащего блока Ширина. - MDN

Смотрите это простое демо:

body {
  width: 200px;
  border: 1px solid red;
}
span {
  text-indent: 100%;
  display: inline-block;
}
<span>text</span>

Ответ 4

Попробуйте witn свойство встроенного блока, он работает хорошо.

.content {
  display:inline-block;
  flex-flow: row wrap;
  justify-content: space-between;
  align-items: stretch;
}