首页 文章

Chrome / Safari不会填充100%高度的flex父级

提问于
浏览
161

我想要一个具有特定高度的垂直菜单 .

每个孩子必须填写父母的高度并且具有中间对齐的文本 .

孩子的数量是随机的,所以我必须使用动态值 .

Div .container 包含一个随机数的子节点( .item ),它们总是必须填充父节点的高度 . 为了实现这一点,我使用了flexbox .

为了使文本链接与中间对齐,我正在使用 display: table-cell 技术 . 但使用桌面显示需要使用100%的高度 .

我的问题是 .item-inner { height: 100% } 无法在webkit(Chrome)中运行 .

  • 这个问题有解决方法吗?

  • 或者是否有一种不同的技术可以使所有 .item 填充父级的高度,文本垂直对齐到中间?

Example here jsFiddle, should be viewed in Firefox and Chrome

.container {
  height: 20em;
  display: flex;
  flex-direction: column;
  border: 5px solid black
}
.item {
  flex: 1;
  border-bottom: 1px solid white;
}
.item-inner {
  height: 100%;
  width: 100%;
  display: table;
}
a {
  background: orange;
  display: table-cell;
  vertical-align: middle;
}
<div class="container">
  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>
</div>

4 回答

  • 4

    问题

    我的问题是.item-inner {height:100%}在webkit(Chrome)中不起作用 .

    它不起作用,因为你使用的百分比高度不符合规范的传统实现 .

    10.5内容高度:高度属性百分比指定百分比高度 . 百分比是根据生成的框的包含块的高度计算的 . 如果未明确指定包含块的高度且此元素未绝对定位,则该值将计算为auto . auto高度取决于其他属性的值 .

    换句话说,对于在流入子项上工作的百分比高度,父项必须具有设置的高度 .

    在您的代码中,顶级容器具有已定义的高度: .container { height: 20em; }

    第三级容器具有已定义的高度: .item-inner { height: 100%; }

    但是在它们之间,第二级容器 .item 没有定义的高度 . Webkit将其视为缺失的链接 .

    .item-inner 告诉Chrome:给我 height: 100% . Chrome会向父母( .item )查询并作出回应:100%的内容是什么?我没有看到任何东西(忽略那里的 flex: 1 规则) . 因此,它根据规范应用 height: auto (内容高度) .

    另一方面,Firefox现在接受父亲的弹性高度作为孩子的百分比高度的参考 . IE11和Edge也接受弹性高度 .

    此外,如果与 flex-basis 一起使用,Chrome将接受 flex-grow 作为适当的父参考(任何值都有效,包括 flex-basis: 0 ) . 但是,在撰写本文时,此解决方案在Safari中失败 .

    #outer {
      display: flex;
      flex-direction: column;
      height: 300px;
      background-color: white;
      border: 1px solid red;
    }
    #middle {
      flex-grow: 1;
      flex-basis: 1px;
      background-color: yellow;
    }
    #inner {
      height: 100%;
      background-color: lightgreen;
    }
    
    <div id="outer">
      <div id="middle">
        <div id="inner">
          INNER
        </div>
      </div>
    </div>
    

    解决方案

    1. Specify a height on all parent elements

    可靠的跨浏览器解决方案是在所有父元素上指定高度 . 这可以防止缺少链接,基于Webkit的浏览器认为这违反了规范 .

    请注意, min-heightmax-height 是不可接受的 . 它必须是 height 属性 .

    更多细节:Working with the CSS height property and percentage values

    2. CSS Relative & Absolute Positioning

    position: relative 应用于父级,将 position: absolute 应用于子级 .

    使用 height: 100%width: 100% 调整子项的大小,或使用偏移属性: top: 0right: 0bottom: 0left: 0 .

    使用绝对定位时,百分比高度在父级上没有指定高度的情况下工作 .

    3. Remove unnecessary HTML containers (recommended)

    button 周围是否需要两个容器?为什么不删除 .item.item-inner ,或两者都删除?虽然button elements sometimes fail as flex containers,但它们可以是弹性项目 . 考虑使 button 成为 .container.item 的子项,并删除无偿标记 .

    这是一个例子:

    .container {
        height: 20em;
        display: flex;
        flex-direction: column;
        border: 5px solid black
    }
    
    a {
        flex: 1;
        background: orange;
        border-bottom: 1px solid white;
        display: flex;                   /* nested flex container (for aligning text) */
        align-items: center;             /* center text vertically */
        justify-content: center;         /* center text horizontally */
    }
    
    <div class="container">
        <a>Button</a>
        <a>Button</a>
        <a>Button</a>
    </div>
    

    4. Nested Flex Containers (recommended)

    摆脱百分比高度 . 摆脱表属性 . 摆脱 vertical-align . 避免绝对定位 . 只需坚持使用flexbox .

    display: flex 应用于弹性项目( .item ),使其成为弹性容器 . 这会自动设置 align-items: stretch ,它告诉孩子( .item-inner )扩展父级的完整高度 .

    重要说明:从弹性项中删除指定的高度,以使此方法起作用 . 如果孩子指定了一个身高(例如 height: 100% ),那么它将忽略来自父亲的 align-items: stretch . 要使 stretch 默认工作,子项的高度必须计算为 auto (full explanation) .

    试试这个(不修改HTML):

    .container {
        display: flex;
        flex-direction: column;
        height: 20em;
        border: 5px solid black
    }
    
    .item {
        display: flex;                      /* new; nested flex container */
        flex: 1;
        border-bottom: 1px solid white;
    }
    
    .item-inner {
        display: flex;                      /* new; nested flex container */
        flex: 1;                            /* new */
    
        /* height: 100%;                    <-- remove; unnecessary */
        /* width: 100%;                     <-- remove; unnecessary */
        /* display: table;                  <-- remove; unnecessary */  
    }
    
    a {
        display: flex;                      /* new; nested flex container */
        flex: 1;                            /* new */
        align-items: center;                /* new; vertically center text */
        background: orange;
    
        /* display: table-cell;             <-- remove; unnecessary */
        /* vertical-align: middle;          <-- remove; unnecessary */
    }
    
    <div class="container">
      <div class="item">
        <div class="item-inner">
          <a>Button</a>
        </div>
      </div>
    
      <div class="item">
        <div class="item-inner">
          <a>Button</a>
        </div>
      </div>
    
      <div class="item">
        <div class="item-inner">
          <a>Button</a>
        </div>
      </div>
    </div>
    

    jsFiddle

  • 0

    解决方案:在.item-inner中删除 height: 100% 并在.item中添加 display: flex

    演示:https://codepen.io/tronghiep92/pen/NvzVoo

  • 290

    我在iOS 8,9和10中遇到了类似的问题,上面的信息无法修复它,但是经过一天的努力,我确实发现了一个解决方案 . 当然,它不适用于所有人,但在我的情况下,我的物品堆放在一列中,当它应该是内容高度时,它的高度为0 . 将css切换为行并换行修复问题 . 这只适用于你有一个项目,他们堆叠,但因为我花了一天时间找到这个,我想我应该分享我的修复!

    .wrapper {
        flex-direction: column; // <-- Remove this line
        flex-direction: row; // <-- replace it with
        flex-wrap: wrap; // <-- Add wrapping
    }
    
    .item {
        width: 100%;
    }
    
  • 0

    对于Mobile Safari有一个浏览器修复程序 . 你需要为iOS设备添加 -webkit-box .

    防爆 .

    display: flex;
    display: -webkit-box;
    flex-direction: column;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -webkit-flex-direction: column;
    align-items: stretch;
    

    如果您对父元素使用 align-items: stretch; 属性,请从子元素中删除 height : 100% .

相关问题