【问题标题】:Prevent child element from stretching parent: portable solution for both Chrome & Safari?防止子元素拉伸父元素:Chrome 和 Safari 的便携解决方案?
【发布时间】:2021-05-13 17:32:07
【问题描述】:

我有一个包含文本的元素,其中的文本可能很长。我想隐藏溢出文本,我不希望文本增加元素或其父/祖先的大小。

将以下内容添加到元素 CSS 一开始似乎有效(来自this question,但高度不是宽度):

      height: 0;
      min-height: 100%;

这适用于 Chrome;但是,它似乎不太适用于 Safari(移动或桌面)。 这是一个例子:

图片显示了 Chrome(左)和 Safari(右)的并排比较。 文本应该垂直居中,但可以看出,Safari 文本不是。 最终,如果页面高度太小,文本就会完全消失。

HTML 在这篇文章的底部(抱歉我没能把它写得更短)。 在 Mac 上通过 Chrome(版本 88.0.4324.146)和 Safari(版本 13.1.3)上的 devtools 检查,问题似乎是 Safari 上的 inner 元素过大。 这似乎是由 height:0;min-height:100% 技巧直接引起的,因为将这些行替换为 height:100% 会导致 Safari 中的居中问题消失(但当文本较长时,Chrome 中的布局会受到干扰)。

据我了解,min-height:100% 应该将inner 元素的高度设置为包含块的高度,其中(因为inner 具有position:relative 并且其父级card 具有display:flex),应该是父card 元素的内容框,如here 所述。

这似乎按照 Chrome 中的描述工作,但不是 Safari。我不确定 Safari 是从哪里获得 inner 元素的高度,但它显然比 card 高。

对于上下文,这是我遇到的原始问题的样子(当青色框中有很多文本时,Chrome 中的布局混乱了)。这是我试图用height:0;min-height:100% 解决的问题。对于这个屏幕截图,我删除了这些行,只输入了height:100%。看起来是这样的(同样,左侧是 Chrome,右侧是 Safari)

如您所见,橙色框已在 Chrome 中消失(左)。 重新添加height:0;min-height:100% 会导致它正确呈现(但由于上述问题,文本在 Safari 中未垂直居中 - 它看起来居中,但这只是因为溢出被​​隐藏,因此卡片显示为充满文本):

感谢任何见解。这只是Safari中的一个错误吗?有解决方法吗?或者(更有可能)我只是一个 CSS 笨蛋……

更新:这是它在 Safari 开发工具中的样子。父 card 元素的高度为 938px,但 inner 的高度为 1121px,并将 bottombar 推离屏幕。

<html>
  <head>
    <style>
      html, body {
      height: 100%;
      overflow: hidden;
      margin: 0;
      padding: 0;
      }

      body {
      position: relative;
      }

      .page {
      background: midnightblue;

      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: row;
      justify-content: center;
      }

      .central-column {
      display: flex;
      flex-direction: column;
      }

      .bottombar {
      background: orange;

      height: 80px;
      z-index: 30;
      display: flex;
      flex-direction: column;
      justify-content: space-around;

      font-size: 2vh;
      text-align: center;
      }

      .foo {
      background: pink;
      position: relative;
      flex-grow: 1;

      display: flex;
      flex-direction: column;
      }

      .foo,
      .central-column {
      width: 800px;
      max-width: 800px;
      height: 100%;
      }

      .foo .topbar {
      background: red;
      position: relative;
      display: flex;
      flex-direction: row;
      justify-content: space-around;
      min-height: 90px;
      height: 15vh;
      max-height: 90px;
      }

      .foo .cardbar {
      position: relative;
      
      flex-grow: 1;
      display: flex;
      flex-direction: column;

      padding: 4px 20px;
      }

      .foo .cardtable {
      background: green;
      
      position: relative;

      flex-grow: 1;
      display: flex;
      flex-direction: column;

      padding: 4px;
      }

      .foo .stack {
      flex-grow: 1;
      display: flex;
      flex-direction: column;
      justify-content: space-around;
      z-index: 6;
      position: relative;
      padding: 4px 20px;
      }

      .foo .stack .card {
      background: cyan;
      position:relative;
      max-height: 160vw;
      flex-grow: 1;
      display: flex;
      flex-direction: column;
      overflow: hidden;
      border-radius: 2vh;
      border-width: 1px;
      border-style: solid;
      }

      .foo .stack .card .inner {

      position: relative;
      display: flex;
      flex-direction: column;
      justify-content: space-evenly;

      height: 0;
      min-height: 100%;
/*
  Replacing the previous two lines with this line fixes the centering on Safari,
  but then longer text (that would overflow the cyan box) breaks the layout in Chrome

      height: 100%;
*/
      
      text-align: center;
      overflow: hidden;

      margin: 4px;
      }
    </style>
  </head>

  <body>
    <div class="page">
      <div class="central-column">
    <div class="foo">
      <div class="topbar">
      </div>
      <div class="cardbar">
        <div class="cardtable">
          <div class="stack">
        <div class="card">
          <div class="inner">
            <div class="content">
              this text should be vertically centered in the cyan box
            </div>
          </div>
        </div>
          </div>
        </div>
      </div>
      <div class="bottombar"></div>
    </div>
      </div>
    </div>
  </body>

</html>

【问题讨论】:

    标签: html css google-chrome safari


    【解决方案1】:

    这是一个简化的示例(我从您的代码中删除了几个元素,只是为了使其更易于阅读)。滚动元素需要两件事:具有溢出:隐藏的父级和具有高度属性(不能是自动)的祖先。然后将非溢出内容居中,只需在父元素上使用 flexbox,在内容元素上使用 margin:auto。

    ***更新

    更好地解释您的代码发生了什么:

    1. 您希望内容块居中,同时让父级隐藏其溢出(如果有)。
    2. 要让溢出工作,它需要一个带有height 的父级,否则它将不知道在哪里截断内容。
    3. 要在可用空间内垂直居中内容框,请将父级设置为display:flex
    4. 重要部分:内容块必须使用margin:auto居中,否则当溢出时,它将保持居中,其顶部和底部被父级的overflow:hidden截断。

    body,
    html {
      margin: 0;
      padding: 0;
      height: 100%;
    }
    
    .page {
      /* Set height for overflow element ancestor */
      height: 100%;
      max-height: 100vh;
      display: flex;
      background: blue;
      justify-content: center;
    }
    
    .central-column {
      flex-basis: 100%;
      max-width: 90%;
      display: flex;
      flex-direction: column;
      height: 100%;
    }
    
    .topbar {
      height: 20%;
      flex-shrink: 0;
      background: red;
    }
    
    .cardbar {
      flex-grow: 1;
      display: flex;
      /* Parent of the scroll element hide overflow */
      overflow: hidden;
    }
    
    .cardtable {
      padding: 20px;
      background: white;
      display: flex;
      flex-basis: 100%;
    }
    
    .card {
      background: cyan;
      padding: 30px;
      /* Margin auto to center the content */
      margin: auto;
      text-align: center;
    }
    
    .bottombar {
      height: 20%;
      flex-shrink: 0;
      background: red;
    }
    <div class="page">
      <div class="central-column">
        <div class="topbar">
        </div>
        <div class="cardbar">
          <div class="cardtable">
            <div class="card">
              <div class="content">
                Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
              </div>
            </div>
          </div>
        </div>
        <div class="bottombar"></div>
      </div>
    </div>

    *** 更新 2

    这是您的 HTML。

    body,
    html {
      padding: 0;
      margin: 0;
      min-height: 100%;
    }
    
    .page {
      width: 100%;
      display: flex;
      justify-content: center;
      background: navy;
      height: 100vh;
    }
    
    .central-column {
      flex-basis: 100%;
      max-width: 900px;
      display: flex;
      flex-direction: column;
      align-items: stretch;
    }
    
    .foo {
      display: flex;
      flex-direction: column;
      flex-grow: 1;
      align-items: stretch;
      height: 100%;
    }
    
    .topbar,
    .bottombar {
      height: 20%;
      background: coral;
      flex-shrink: 0;
    }
    
    .cardbar {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      padding: 10px 20px;
      background: pink;
      flex-grow: 1;
      overflow: hidden;
    }
    
    .cardtable {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      padding: 10px 20px;
      background: forestgreen;
      flex-grow: 1;
      overflow: hidden;
    }
    
    .stack {
      border-radius: 10px;
      display: flex;
      flex-direction: column;
      align-items: stretch;
      background: lightblue;
      flex-grow: 1;
      overflow: hidden;
    }
    
    .card {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      flex-grow: 1;
    }
    
    .inner {
      display: flex;
      flex-direction: column;
      align-items: center;
      flex-grow: 1;
    }
    
    .content {
      margin: auto;
      padding: 10px;
      text-align: center;
    }
    <div class="page">
      <div class="central-column">
        <div class="foo">
          <div class="topbar">
          </div>
          <div class="cardbar">
            <div class="cardtable">
              <div class="stack">
                <div class="card">
                  <div class="inner">
                    <div class="content">
                      this text should be vertically centered in the cyan box
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div class="bottombar"></div>
        </div>
      </div>
    </div>

    【讨论】:

    • 谢谢;但是,当我将答案中的注释元素添加到我的示例中并在 Safari 上运行时,文本仍然垂直不居中。如果可能,您可以在不删除元素的情况下使用我的示例吗?旁注:(1)card上的margin:auto似乎不影响内容是否居中,它只是减少了边距,这是我不想要的; (2) 看起来你在cardtable 中添加了overflow-y:scroll,并且还谈到了“滚动元素”?我不想滚动行为。话虽如此,我看不到任何滚动条,所以也许我误解了。
    • 我投了反对票,因为这个答案似乎不适用于我的示例,并且显然引入了无关的样式(如滚动条) - 抱歉,如果这看起来不公平,我很乐意收回反对票如果你能修改答案
    • 老兄,如果您不希望溢出滚动,那么只需从代码中删除该行。我继续为您删除它。您需要在要居中的元素上设置 margin:auto 否则会在溢出时中断。
    • 滚动条并不是真正的问题,问题是当我尝试在我提供的代码 sn-p 中实现您的建议时,它 (a) 明显缩小了边距并且 (b) 确实不能解决 Safari 上的居中问题。但是,我非常感谢您的解释清晰,因此,虽然我还不能将此答案标记为已接受(因为它似乎无法解决问题),但我赞成它。谢谢!
    • 这个答案对你有用吗?我用你的代码更新了它。
    猜你喜欢
    • 2013-05-20
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    • 2012-06-13
    • 2019-05-23
    • 1970-01-01
    相关资源
    最近更新 更多