使用 FontAwesome 时 Flexbox 大小调整无法正常工作

Flexbox sizing doesn't work correctly when using FontAwesome

我的页面遇到了非常奇怪的 flexbox 行为 layout.I 我正在使用 FontAwesome 来呈现某些符号。

基本上,我在另一个 flexbox 项目中有 2 个 flexbox 项目,这些子项目渲染得比父项目宽。

1) 我有一个 .content__header 对象,它在另一系列 flexbox 对象中呈现为 flexbox 对象。

2).content__header 对象包含 2 个子对象:.breadcrumb.page_tools。这些子对象也呈现为弹性项目。

3) 在 .breadcrumb 对象中,我有一些 span 对象 (.breadcrumb__test),其内容被 FontAwesome 图标替换。替换是使用 ::after 伪元素的绝对定位完成的。

4) 当我删除所有 .breadcrumb__text HTML 元素或只是从我的样式中删除 .breadcrumb__text::after 定义时 sheet - 它定义了使用FontAwesome 字体 - 子对象(.breadcrumb.page_tools)以正确的宽度呈现。 所以我想这与用 FontAwesome 图标替换有关。

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

问题的可视化表示

绿线表示父级宽度与其实际内容之间的差异。

代码 & Fiddle 下面。

浏览器: Google Chrome 47.0.2526.106 m


Fiddle:

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


更新

当我从 .breadcrumb__text CSS 定义中删除 text-indent: 100%; 时,.breadcrumb 按预期呈现。但是,当我保留 text-indent 并删除样式 sheet 顶部的 .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;
}

FontAwesome 字体不是根本原因。这是浏览器默认设置的 H1 "block" 布局定义。将此样式添加到您的 breadcrumb__current class。参见 https://jsfiddle.net/44gymmw2/9/

 word-wrap:break-word 

H1 标签是一个块级元素,它将使其将该块的内容推送到整个页面。另一个修复方法是将其从块更改为内联,如下所示:

h1 { display: inline; }

或者您可以将该文本包装在另一个元素中,例如 span。

我认为问题是由 text-indent:100% 规则引起的,该规则在右侧添加了额外的 space。

The text-indent property specifies how much horizontal space should be left before the beginning of the first line of the text content of an element. <percentage> value relative to the containing block width. -MDN

查看这个简单的演示:

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

在您的示例中,您只需将 text-indent:100% 更改为 text-indent:-9999px,它的工作原理类似,并且不会造成溢出。

Updated jsfiddle

我刚刚审查完您的代码并注意到以下内容:

  • 存在不必要的(嵌套的)弹性容器(由使用 display: flex; 引起)。
  • 有不必要的 flex-related 声明(只是声明默认行为,例如 flex-flow: row no-wrap;align-items: stretch)。
  • 在各种不相关的选择器的上下文中有几个不必要的声明。测试/调试时可能 left-over 声明。

也就是说,让我们继续你的问题。这不是很明显,所以需要一些介绍。

introduces an important ingredient of your issue, which affects using text-indent. From W3:

The box is indented with respect to the left (or right, for right-to-left layout) edge of the line box. User agents must render this indentation as blank space.

[...]

If the value of text-indent is either negative or exceeds the width of the block, that first box, described above, can overflow the block. The value of overflow will affect whether such text that overflows the block is visible.

换句话说:text-indent 影响应用它的框的尺寸。

您已在 .breadcrumb__text 上声明 overflow: hidden;。显然,要使该声明具有预期的效果,您应用它的框需要一个 width,否则它不会有剪裁边。

.breadcrumb__text 应该从应用于它的 flex-basis 声明(特别是 flex: 0 0 2em;)中获取它的宽度。好吧……这并没有发生,至少,没有像您期望的那样完全。尽管它的宽度似乎是 2em,但出于某种原因,它并没有像它应该的那样触发溢出行为。这似乎是您使用的特定 Chrome 版本中的错误,因为它已在 Canary 中修复(例如版本 49 及更高版本)。

所以:这似乎是 Chrome 中 flexbox 实现的问题。也就是说,有了这些知识,您的问题可以通过多种方式解决。一些例子:

text-indent: -100%

使用 text-indent: -100% 解决了您的问题,因为它消除了受影响元素右侧的额外空白。 (→ jsfiddle)

width: 2em

您可以将声明 width: 2em 添加到 .breadcrumb__text。这将修复 flex-basis 声明的意外行为。 (→ jsfiddle)

overflow: hidden; 在父容器上

.breadcrumbs 上添加 overflow: hidden; 可以解决您的问题。现在父容器有一个裁剪边并处理使用 text-indent: 100% 引起的空白。 (→ jsfiddle)

最后的评论

Flexbox 是一种功能强大的布局模式,值得尝试。但是,算法很复杂,浏览器实现也并非没有问题。确保在使用 flexbox 时考虑到这一点。

查看代码时的另一个问题是使用 flexbox 的方式。 Flexbox 可供您使用,但它不一定要取代所有其他处理布局的方式。 display: inline-block;display: table;,甚至 float 都可以在不引入嵌套 flex 容器的复杂性的情况下完成这项工作。

尝试 inline-block 属性 效果很好。

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