【问题标题】:Centering Items with Flexbox and Overflow使用 Flexbox 和溢出使项目居中
【发布时间】:2015-12-08 07:22:55
【问题描述】:

问题总结

我想要的布局是能够在页面上居中(垂直和水平)未知大小的图像。如果图像太大而无法适应任一方向,我想显示滚动条,以便用户可以滚动查看完整图像。我遇到的问题是,当图像太大而无法容纳时,图像的顶部和左侧(取决于被切断的部分)将永远无法滚动到。

尝试的解决方案

我正在尝试使用 flexbox 来实现所需的布局,但 flexbox 不是必需的。这是一个重现问题的小示例(请注意,我没有在 CSS 中放置任何浏览器前缀,因此您可能希望在 Chrome [或者也可能是 Firefox 中查看?]):

.body {
  height: 600px;
}

.container {
  margin: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid red;
  height: 100%;
  overflow: auto;
}

img {
  border: 5px solid black;
}
<div class="body">
  <div class="container">
    <img src="http://placehold.it/700x700" />
  </div>
</div>

您应该能够完全看到图像周围的边框,但是随着窗口的缩小,图像的左侧和/或顶部会被截断。随着窗口继续缩小,越来越多的图像将变得不可见。

请注意,那里是否有图像似乎并不重要。这是一个 sn-p,只是使用普通的 div 来显示问题:

.body {
  height: 600px;
  margin-top: 80px;
}

.container {
  margin: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid red;
  height: 100%;
  overflow: auto;
}

.content {
  border: 5px solid black;
  width: 600px;
  height: 600px;
  background-color: gray;
}
<div class="body">
  <div class="container">
    <div class="content"></div>
  </div>
</div>

再一次,整个 div 应该始终可以通过滚动到达,但事实并非如此。

问题

我如何才能实现上述所需的布局仅使用 HTML 和 CSS(不接受 JS 答案)? Flexbox 不是解决问题所必需的,但它会是一个不错的选择。

谢谢!

【问题讨论】:

  • 如果您将大于视口的图像居中,则顶部和左侧将始终被截断。您不能滚动超出视口的顶部或左侧。您需要更改以这些尺寸处理图像的方式,以防止这种情况发生,可能是通过防止图像居中或普通缩小图像以适应视口的媒体查询。如果它必须始终居中,则您必须不居中图像并使用js在视口缩小时滚动到中心。
  • 你能澄清你的意思@brouxhaha吗?如果图像对于视口来说太大并且容器元素设置了滚动,我希望能够滚动到容器中的所有内容。
  • 您可以使用 min-contentmax-contentfit-content 等内在测量值。但是它们并不为人所知或经常使用……我不知道为什么。我敢肯定还有其他方法,但它们让我望而却步。

标签: html css flexbox


【解决方案1】:

找到了双弹性容器的解决方案:

.body {
  height: 600px;
  overflow: auto;
  display: flex;
  flex-direction: column;
}
.container {
  display: flex;
  align-items: center;
  flex-grow: 1;
}
.content {
  flex-grow: 1;
  text-align: center;
}
img {
  border: 1px solid red;
}
<div class="body">
 <div class="container">
    <div class="content">
      <img src="http://placehold.it/700x700" />
    </div>
  </div>
</div>

【讨论】:

    【解决方案2】:

    您可以通过将图像包装在 flex 容器内的容器中来实现此目的,如下所示:

    • 弹性容器
      • display: flex
      • height: 100vh
    • 内容器
      • margin: auto

    这将允许您获得在视口中垂直和水平居中的未知大小的图像,而不会失去滚动到图像任何部分的能力,以防它不适合任何方向的视口。

    示例 1:(图像在视口中居中)

    body {
      margin: 0;  /* Override user agent styles */
    }
    
    .flex {
      display: flex;
      height: 100vh;
    }
    .container {
      margin: auto;
    }
    <body class="flex">
      <main class="container">
        <img src="http://placehold.it/100x100">
      </main>
    </body>

    示例 2:(图像不适合视口,但仍可滚动)

    body {
      margin: 0;  /* Override user agent styles */
    }
    
    .flex {
      display: flex;
      height: 100vh;
    }
    .container {
      margin: auto;
    }
    img {
      border: 1px solid red;
    }
    <body class="flex">
      <main class="container">
        <img src="http://placehold.it/1000x1000">
      </main>
    </body>

    它适用于最新版本的 Chrome、Firefox、Opera 和 Edge。

    【讨论】:

      【解决方案3】:

      只需从您的 .container 中删除 justify-content 并将 margin: auto 添加到您的图像中。

      .body {
        height: 600px;
      }
      
      .container {
        margin: auto;
        display: flex;
        /* align-items: center; // no need for this anymore */
        /* justify-content: center; // remove this */
        border: 1px solid red;
        height: 100%;
        overflow: auto;
      }
      
      img {
        border: 5px solid black;
        margin: auto;  /* add this */
      }
      <div class="body">
        <div class="container">
          <img src="http://placehold.it/700x700" />
        </div>
      </div>

      【讨论】:

        【解决方案4】:

        所以标准是你总是想要一个垂直和水平居中的图像,并且不管视口有多大或多小,它都可以滚动?看看这个 sn-p,让我知道我是否接近。如果我完全错了,那么我有 B 计划。如果我成功或几乎成功了,我会解释我做了什么。

        摘要

        1. 定义&lt;body&gt;,因为如果你不这样做,你就不能决定你的滚动条能走多远。

          position: relativetop, bottom, right,left 在 0 处拉伸 &lt;body&gt; 以覆盖视口。

          ♦ 主体的widthheight100vw100vh&lt;body&gt; 实施限制

          ♦ 由于&lt;body&gt; 是一个容器,所有flexbox 属性都会影响.x 的水平居中。

          由于您强调了滚动条的使用,overflow: scroll 滚动条即使不需要也会持续存在。这在涉及动态内容的情况下很好,因为不会有任何跳跃。

        2. 外部容器.x 具有flexbox 属性以使内部容器.y 居中。 此外,您还会注意到一个鲜为人知的属性。

        3. .yflex-flow: column nowrap 使图像居中。

        4. bodymin-content 应用于heightwidth,这将迫使其内容的边界进入一个紧凑的包中。这样您就可以在没有通常截断的情况下看到图像的边框。

        更新

        这个demo有一些简单的JS来演示任意大小的图片是:

        1. 水平居中
        2. 垂直居中
        3. 可以以任何尺寸查看所有侧面。

        注意:DEMO下的任何内容都可以完全安全地删除或注释掉。

        // DEMO 
        var s = document.getElementById('s');
        s.addEventListener('click', function(event) {
          event.preventDefault();
          var w = document.getElementById('w'),
            h = document.getElementById('h'),
            pic = document.getElementById('pic'),
            wv = w.value,
            hv = h.value;
          pic.src = "http://placehold.it/" + wv + "x" + hv + "/";
        }, false);
        /* RESET */
        
        html {
          box-sizing: border-box;
          font: small-caps 400 16px/1.45'Source Code Pro';
        }
        *,
        *:before,
        *:after {
          box-sizing: inherit;
          margin: 0;
          padding: 0;
          border: 0 solid transparent;
        }
        /* REQUIRED */
        
        body {
          position: relative;
          top: 0;
          left: 0;
          bottom: 0;
          right: 0;
          width: 100vw;
          height: 100vh;
          overflow: auto;
          margin: auto;
          width: -moz-min-content;
          width: -webkit-min-content;
          width: min-content;
          height: -moz-min-content;
          height: -webkit-min-content;
          height: min-content;
        }
        .x {
          height: 600px;
          flex-flow: row nowrap;
          display: flex;
          align-items: center;
          justify-content: center;
          align-content: center;
        }
        .y {
          margin: auto;
          display: flex;
          flex-flow: column nowrap;
          align-items: center;
          justify-content: center;
          align-content: center;
          border: 2px dashed red;
        }
        /* DEMO */
        
        .ui {
          position: fixed;
          top: 1em;
          left: 1em;
          width: 500px;
          line-height: 1.3;
          z-index: 1;
        }
        fieldset {
          border: 1px solid lightgrey;
          border-radius: 6px;
        }
        input {
          width: 48px;
          line-height: 1.2;
          border: 1px solid grey;
          border-radius: 6px;
          padding: 2px;
          margin: 2px 1px;
        }
        label {
          margin: 2px 0 2px 2px;
        }
        <!doctype html>
        <html>
        
        <head>
          <meta charset="utf-8">
          <title>C.R.A.P.D. -=- Changing Rectangle Alignment, Position, and Dimensions</title>
        </head>
        
        <body>
          <!-- DEMO -->
          <header class="ui">
            <fieldset>
              <legend>Changing Rectangle Alignment Position and Dimensions</legend>
              <label for="w">Width
                <input id="w" type="text" value="300" />
              </label>
              <label for="h">Height
                <input id="h" type="text" value="300" />
              </label>
              <input id="s" type="submit" value="Submit" />
            </fieldset>
          </header>
          <!-- REQUIRED -->
          <main class="x">
            <section class="y">
              <img id="pic" src="http://placehold.it/300x300/" />
            </section>
          </main>
        </body>
        
        </html>

        【讨论】:

        • 谢谢@zer00ne。此解决方案似乎没有垂直居中。
        • 查看整页。顶部和底部处于全视口,本质上是居中的。
        • 我的错。你是对的,先生!我只是在我的手机纵向上查看了 sn-p,实际上它不是垂直居中的。我已纠正此问题,请参阅更新的 sn-p。
        • 我仍然没有看到它垂直居中。例如,尝试将图像高度更改为 300px。
        • @ChandlerKent 我也有一个 2400x2400 的演示
        猜你喜欢
        • 2013-04-13
        • 2013-03-21
        • 1970-01-01
        • 1970-01-01
        • 2014-10-21
        • 1970-01-01
        • 1970-01-01
        • 2017-12-11
        相关资源
        最近更新 更多