Flexbox 在 iOS 移动浏览器和 OS X Safari 上的奇怪行为

mrC*_*ean 5 webkit sass flexbox angularjs

我对 Flexbox 很陌生,因为我的工作需要支持 IE8,所以在这个项目之前我从来没有真正关心过它。

我试图弄清楚如何使“卡片”网格具有相同的高度。这些卡片内部包含不同数量的文本以及图像。由于我使用 AngularJS,JavaScript 解决方案的复杂性超出了我的时间,因此我选择了 flexbox。

这是我的卡片包装器的相关代码(如果您需要更多,请告诉我):

.card-grid {
    display: -webkit-box;      /* OLD - iOS 6-, Safari 3.1-6 */
    display: -moz-box;         /* OLD - Firefox 19- (buggy but mostly works) */
    display: -ms-flexbox;      /* TWEENER - IE 10 */
    display: -webkit-flex;     /* NEW - Chrome */
    display: flex;             /* NEW, Spec - Opera 12.1, Firefox 20+ */

    -ms-flex-wrap: wrap;
    -webkit-flex-wrap: wrap;
    flex-wrap: wrap;

    ...

    .data-card {
        height: auto;
        //IE fallback
        display: inline-block;
        //Modern Browsers
        display: -webkit-box;      /* OLD - iOS 6-, Safari 3.1-6 */
        display: -moz-box;         /* OLD - Firefox 19- (buggy but mostly works) */
        display: -ms-flexbox;      /* TWEENER - IE 10 */
        display: -webkit-flex;     /* NEW - Chrome */
        display: flex;             /* NEW, Spec - Opera 12.1, Firefox 20+ */

        ...

    }
}
Run Code Online (Sandbox Code Playgroud)

以下是上述选择器的相关 Angular HTML:

<div class="card-group">
    <ol class="cards card-grid invisible grid-row">
        <li ng-repeat... class="data-card col xs-6 md-4 lg-3">
            <a class="card" href="javascript:void(0)" ... >
                ...
            </a>
        </li>
    </ol>
</div>
Run Code Online (Sandbox Code Playgroud)

这是 iOS 中 Chrome 和 Safari 上发生的情况的屏幕截图: 问题是它显示了第一张卡,然后由于某种原因,第二张卡位于下一行...... 我面临的问题是,它显示第一张卡“Axial”,然后下一张卡“Motor Start”应该就在它旁边。

我尝试过的事情:

  • 将包装属性放在项目本身上,而不是包装器上,这看起来很糟糕
  • 定义宽度并使用flex-grow轴向宽度即可达到 100%,因此最后一张(未描绘)卡片旁边没有任何内容。
  • 但这wrap-reverse只是颠倒了内容并给了我同样的问题。

然后我在 OS X 上打开 Safari 并得到以下信息: 与 iOS 相同的问题

它适用于:

  • Chrome(桌面版)
  • 火狐(桌面版)
  • Internet Explorer Edge(桌面)
  • 铬(安卓)

它唯一无法工作的地方是 Apple 浏览器(即 Chrome iOS 和 Safari Mobile 等)

所以我认为这是一-webkit-件事,但这很明显。我只是不知道我的代码中做错了什么。我无法发布我的工作代码,因为该项目正在进行中。

是否有一个我应该在 Flexbox 中使用但我没有使用的特殊属性?提前感谢您的帮助。

mrC*_*ean 4

好吧,我已经舔完了。因此,对于任何 Google 员工来说,我解决此问题的方法是将 CSS 更改为:

.card-grid {
  display: flex;
  display: -webkit-flex;
  flex-wrap: wrap;
  -webkit-flex-wrap: wrap;
  -ms-flex-wrap: wrap;

  .data-card {
    /**
     * Height AUTO is important, because adding flex to the child makes it vertically 
     * stretch by default. So that means height: 100% won't work.
     */
    height: auto;
    //IE fallback
    display: inline-block;
    //Modern Browsers
    display: flex;
    display: -webkit-flex;

    ...

    /**
     * For some unknown reason, it still didn't work until I subracted 1% from
     * the width of each breakpoint I was using.
     */
    @media screen and (min-width: map_get($grid-breakpoints, 'lg')) {
      width: percentage((3 / 12)) - 1%;
    }

    @media screen and (min-width: map_get($grid-breakpoints, 'md')) {
      width: percentage((4 / 12)) - 1%;
    }

    @media screen and (max-width: map_get($grid-breakpoints, 'sm')) {
      width: percentage((6 / 12)) - 1%;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

即使1%实际宽度被减去,这个解决方案在 Chrome 中仍然可以很好地呈现。我发现的一些事情是:

  1. 简单地在父级上放置弹性(以使子级的高度对齐)是不够的。我在这里读到了一篇非常精彩的演练 。
  2. 当我知道我必须对父母和直系子女保持灵活性后,我又回到了原点。直到我将子项的宽度设置为49%它才被修复。我仍然不知道为什么会这样,因为它与 no 而box-sizing: content-box不是我正在使用的 which is一致box-sizing: border-box。我有一个星形选择器放在border-box每个元素上,但也许我需要在子元素上手动指定它?
  3. 我不需要添加的所有额外供应商前缀,因为就我而言,display: inline-block当 Flexbox 不可用时,我将其用作后备。不过,如果我愿意的话,我可以使用下面的内容。

    @supports not (flex-wrap: wrap) {
      ...
    }
    
    Run Code Online (Sandbox Code Playgroud)

    然后在里面放一些代码。这是另一篇关于CSS Tricks 的文章 ,其中讨论了一些关于使用 flexbox 和后备的内容。尽管与我的用例不同,但它仍然很有帮助。这是一个很好的视觉参考,我想我会保留下来。

希望所有这些信息对某人有帮助。我知道它救了我的培根。

更新:添加box-sizing: border-box到子元素没有任何效果。看起来1%从宽度中减去是可行的方法,除非有一些我不知道的东西,这是完全可能的。

更新 2:由于朋友的建议和这篇文章,我稍微更改了代码,开始使用该flex属性,并使用 HTML 上的列类作为后备。以 mixin 的形式重新包含供应商前缀。我还发现我必须减去百分比的原因是因为我在父级上方有一个网格容器,该容器具有负边距和清除修复。一旦删除,下面的 CSS 就可以工作了:

.card-grid {
  @include displayFlex;
  @include flexWrap(wrap);

  .data-card {
    /**
     * Height AUTO is important, because adding flex to the child makes it vertically 
     * stretch by default. So that means height: 100% won't work.
     */
    height: auto;
    //IE fallback
    display: inline-block;
    @include flexboxDisplay;
    @include flex(0 0 auto);

  }
}
Run Code Online (Sandbox Code Playgroud)