【问题标题】:Maximum possible size image and div expanding to fill the space最大可能大小的图像和 div 扩展以填充空间
【发布时间】:2017-01-05 09:57:31
【问题描述】:

我确定以前有人问过这个问题,但我找不到确切问题的答案。

我想要一个非常简单的布局:

-------------------
      header
-------------------
         |
 content | graphic
         |
-------------------

地点:

  • 标题高度由字体大小设置;
  • 内容具有固定的最小宽度;
  • 在考虑到这两个约束并保留纵横比的情况下,图形尽可能大(即,它将与屏幕减去标题一样高,除非这会使内容面板太窄);
  • 鉴于这三个限制,内容尽可能广泛。

[编辑添加:]

  • 垂直:当宽度+纵横比约束导致图像小于最大高度时,图像垂直居中
  • 水平:图像始终硬靠在屏幕的右侧(任何手动添加的填充除外),并且内容始终位于图像的左侧(任何手动添加的填充除外)。

我尝试过使用弹性框并满足前三个约束条件,但我无法让内容窗格水平增长以填充图像未使用的空间。我得到的最好结果是使用下面的 HTML 和 CSS,但是,正如您在下面的屏幕截图中看到的那样,这会导致内容 div 和图像占用相同的大小,而不是内容 div 将图像推到右侧. (这是在两者上设置 flex=1 的预期行为,所以我没想到它会起作用;但至少这给了我想要的图像大小)。

我使用的是https://jsfiddle.net/uv566jc3/:

.grid {
  border: solid 1px #e7e7e7;
  height: 95vh;
  display: flex;
  flex-direction: column;
}
.header {
  flex: 0;
}
.grid__row {
  flex: 1;
  display: flex;
  flex-direction: row;
}
.grid__item {
  flex: 1;
  padding: 12px;
  border: solid 1px #e7e7e7;
}
img {
  flex: 1;
  object-fit: contain;
  overflow: hidden;
  border: solid 1px #e7e7e7;
}
<div class="grid">
  <div class="header">Some header stuff
  </div>
  <div class="grid__row">
    <div class="grid__item">1</div>
    <img id="pic" src="https://s27.postimg.org/oc7sozu7n/clouds.png">
  </div>
</div>
  • grid样式是列方向的flexbox,包含header和grid__row;
  • header 的 flex 为 0,即高度由内容设置;
  • grid__row 具有 flex 1,即填充标题后剩余的高度;也是一个包含 grid__item 和 img 的行方向的 flex 容器。
  • grid__item 具有 flex 1,即填充可用宽度;
  • img 具有 flex 1 并使用 object-fit = 1 (它获取我需要的图像大小调整属性)和 overflow=hidden (我不太明白它在做什么,但如果我把它排除在外,img 容器会展开2 倍)。

我没有在 jsfiddle 中的 grid__item 项上明确设置 min-width,但我预计不会有任何区别。

有没有一种简单的方法可以在 CSS 中获得我想要的东西?如有重复请见谅。

【问题讨论】:

    标签: html css flexbox


    【解决方案1】:

    我已经编辑了代码,您的解决方案是您想要的吗?我不确定..

    https://jsfiddle.net/vjLps7qs/6/

    变成了:

      .container {
        width: calc(100vw);
        height: 100vh;
        overflow: hidden;
      }
    
      .top {
        height: 1.25em;
        padding: 3px;
        background: yellow;
        display: flex;
        flex-direction: row;
      }
    
      .innerCtr {
        height: 100%;
        overflow: hidden;
      }
    
      .left {
        height: 100%;
        background: red;
        overflow: hidden;
      }
    
      .right {
        max-height: 100%;
        max-width: 80%;
        calc(100% - 1.25rem);
        background: blue;
        float: right;
        object-fit: contain;
        overflow: hidden;
        position: relative;
        top: calc(50% - 1.25rem);
        transform: translateY(-52%) scale(0.95);
      }
    

    新增计算,all major browsers支持

      .right {
        calc(100% - 1.25rem);
        top: calc(50% - 1.25rem);
      }
    

    再次,非常抱歉,如果这不是您要查找的内容,但此线程很难导航。

    【讨论】:

    • 好的,谢谢!是 "rem" 使它起作用,我尝试使用 "em" 却一无所获!
    • @WilliamWhyte 是的,我从不使用 em,它太容易出错了。我很惊讶人们不再使用 rem
    【解决方案2】:

    flex: 1 因素

    在您的grid__row flex 容器中,在行方向上,两个flex 项目——grid__itemimg——都应用了flex: 1

    这意味着这两个项目将平均分配容器中的可用空间。换句话说,50/50,就像你的插图一样。

    我的建议:从img 中删除flex: 1


    object-fit: contain 产生的空格

    使用object-fit: contain,图像的纵横比保持不变,并且可以缩放以适应框。

    因此,左侧和/或右侧(纵向适合)或顶部和/或底部(横向适合)可能存在空白。

    这可能是您在图像左侧和右侧看到“填充”空间的原因。

    如果您尝试cover,所有空间都会被使用,但会出现裁剪 (demo)。

    这里有更多关于object-fit的信息:https://stackoverflow.com/a/37127590/3597276


    overflow: hidden 效果

    关于你的旁白:

    ...overflow=hidden (我不太明白它在做什么, 但是如果我把它排除在外,img 容器会水平扩展一个 因子 2)。

    这可能是由于弹性项目的最小尺寸算法

    默认情况下,弹性项目不能小于其内容的大小。

    但是,可以使用overflow: hidden 覆盖此功能。

    更多详情请点击:Why doesn't flex item shrink past content size?

    【讨论】:

    • 与移除 overflow=hidden 一样,移除 flex:1 会使图像变宽大约两倍。就好像自动添加了一些填充,flex 让我们能够减少,溢出标签让我们能够隐藏。
    • 您使用的图像很大 (900 x 1600)。所以它将消耗所有可用空间。也许首先将最小宽度添加到.grid__item。试试这个,而不是 flex: 1: flex: 1 0 200px
    • 不过,它不会占用所有可用空间。问题不在于图像本身,它会按我的预期调整大小。问题是浏览器在图像的两侧对称地添加了大量的空白空间 - 请参阅问题中的屏幕截图。
    • 我有时会通过将图像问题包装在 div 中来解决这些问题。也许这会奏效。您会在这个网站上找到许多在 flex 容器中苦苦挣扎的人提出的问题。
    • 另外,我已经看到了占位符图像特有的问题,所以还要用实际图像进行测试。
    【解决方案3】:

    这个例子使用了浮点概念:

    人像图片:

    * {
      box-sizing: border-box;
    }
    body {
      margin: 0px;
    }
    .header {
      width: 100%;
      height:8vh;
      border: 1px solid #aaa;
    }
    .main-content {
      width: 100%;
      border: 1px solid #aaa;
      padding: 0px;
    }
    .main-content > .left {
      float: left;
      width: 50%;
    }
    .main-content > .right {
      float: right;
      width: 50%;
    }
    .main-content > div {
      min-height: 50%;
      max-height: 90%;
    }
    .main-content > .right > img {
      max-width: 100%;
      max-height: 90vh;
    }
    .main-content:after,
    .main-content:before {
      display: table;
      clear: both;
      content: "";
    }
    <div class="header">
      Some Header stuff..
      <br>
    </div>
    <div class="main-content">
    
      <div class="left">
        Somehitng on the left
      </div>
      <div class="right">
        <img src="https://s-media-cache-ak0.pinimg.com/236x/41/89/8c/41898cae6d9edd8737dfef07ab50ea57.jpg" />
      </div>
    </div>

    风景图片:

    * {
      box-sizing: border-box;
    }
    body {
      margin: 0px;
    }
    .header {
      width: 100%;
      height: 8vh;
      border: 1px solid #aaa;
    }
    .main-content {
      width: 100%;
      border: 1px solid #aaa;
      padding: 0px;
    }
    .main-content > .left {
      float: left;
      width: 50%;
    }
    .main-content > .right {
      float: right;
      width: 50%;
    }
    .main-content > div {
      min-height: 50%;
      max-height: 90%;
    }
    .main-content > .right > img {
      max-width: 100%;
      max-height: 90vh;
    }
    .main-content:after,
    .main-content:before {
      display: table;
      clear: both;
      content: "";
    }
    <div class="header">
      Some Header stuff..
      <br>
    </div>
    <div class="main-content">
    
      <div class="left">
        Somehitng on the left
      </div>
      <div class="right">
        <img src="http://www.w3schools.com/css/img_fjords.jpg" />
      </div>
    </div>

    【讨论】:

    • 谢谢!这在水平方向上很好,但没有给出我正在寻找的垂直行为 - 我已经编辑了问题以使其更清晰。
    • 编辑了答案.. 内容将保持在垂直范围内
    【解决方案4】:

    这可能是您的问题的解决方案吗?见小提琴here

    #pic {
           background: url('http://lorempixel.com/400/200/sports/1/') no-repeat; 
           position: absolute; 
           left: 440px; 
           right: 0; 
           top: 0; 
           bottom: 0; 
         }
    

    我已将图像作为具有cover 属性的背景图像。这样,无论您如何调整图像大小,图像都会占用容器的全宽和全高。

    【讨论】:

    • 感谢您的回答,但是当我单击 jsfiddle 时,图像没有响应容器大小的变化。 (我还看到在 jsfiddle 中,图像容器有 object-fit:contain 而不是 cover - 也许你还没有完成编辑它?)
    • 谢谢!但是图像仍然没有响应容器大小的变化,我希望左侧的内容面板可以扩展以填充图像约束的可用空间。我已经编辑了这个问题,试图让它更清楚。
    【解决方案5】:

    您应该从图像中删除 flex 并将其包装在容器中以满足您的要求。

    我已经稍微修改了您的代码以达到同样的效果。请检查更改。

    更新

    我已经更新了我的答案并现在使用display: inline-flex。应该满足您的所有要求。

    .grid {
      border: solid 1px #e7e7e7;
      height: 95vh;
      display: flex;
      flex-direction: column;
    }
    
    .header {
      flex: 0;
    }
    
    .grid__row {
      flex: 1;
      display: flex;
      flex-direction: row;
    }
    
    .grid__item {
      flex: 1;
      padding: 12px;
      border: solid 1px #e7e7e7;
    }
    
    .img_ctr {
      border: solid 1px #e7e7e7;
      display: inline-flex;
    }
    
     img {
      height: 100%;
    } 
    <div class="grid">
      <div class="header">Some header stuff
      </div>
      <div class="grid__row">
        <div class="grid__item">1</div>
        <div class="img_ctr">
          <img id="pic" src="https://s-media-cache-ak0.pinimg.com/236x/41/89/8c/41898cae6d9edd8737dfef07ab50ea57.jpg">
        </div>
      </div>
    </div>

    【讨论】:

    • 感谢您的回答,但它不会放大或缩小图像 - 请记住,目标是使图像尽可能大,但受 (a) 方面的限制比例被保留,(b)它不高于从标题底部到屏幕底部的距离,并且(c)它至少在左侧为内容留下了最小宽度。
    • 不垂直缩放 :-)
    【解决方案6】:

    我使用max-widthmax-height 对图像应用限制,但保留纵横比。我还将图像包含在独立的div 中,以允许缩小和扩大两个单独的部分。

    这可能是您正在寻找的东西吗? https://jsfiddle.net/johnnykb/pu1vpL3q/2/

    极高和极宽的图像都可以完美缩放以适应图像容器,如果图像足够小,图像容器就会缩小,而不会超过内容部分的最小宽度所允许的范围。

    HTML:

    <div class="grid">
      <div class="header">Some header stuff
      </div>
      <div class="grid__row">
        <div class="content">1</div>
        <div class="image">
          <img id="pic" src="http://placekitten.com/200/2000">
        </div>
      </div>
    </div>
    

    CSS:

    .grid {
      border: solid 1px #e7e7e7;
      height:95vh;
      display: flex;
      flex-direction: column;
    }
    
    .header {
      flex: 0;
    }
    
    .grid__row {
      flex: 1;
      display: flex;
      flex-direction:row;
    }
    
    .content {
      flex-grow: 1;
      padding: 12px;
      border: solid 1px #e7e7e7;
      min-width: 400px;
    }
    
    .image {
      flex-shrink: 1;
      padding: 12px;
      border: solid 1px #e7e7e7;
      text-align: center;
    }
    
    img {
      overflow: hidden;
      border: solid 1px #e7e7e7;
      max-height: 100%;
      max-width: 100%;
    }
    

    【讨论】:

    • 不完全——受我列出的限制,图像没有尽可能大。试试placekitten.com/900/1600placekitten.com/1600/900,这些是我将使用的比率。顺便说一句,谢谢你把我介绍给placekitten!
    • @WilliamWhyte 很高兴成为给小猫带来欢乐的人 :) 我不确定我是否理解它是如何不满足要求的。它使用两个值(高度和宽度)中较大者的最大可能大小。始终取决于视口大小并考虑.contentmin-width。如果您能详细解释缺少的内容,我可能会提供更多帮助。
    • 嗨,约翰尼——看看我刚刚添加的答案,看看我在寻找什么。在您的小提琴中,您在左右两侧都有 flex,这意味着右侧不是尽可能大:它的大小是与左侧大小的权衡。对于您选择的 2000 宽度图像,在 jsfiddle 窗口中查看时,左侧应该始终是最小宽度,因为它们的宽度始终小于 2000 像素;相反,左边随着窗口增长。这能解释问题吗?
    【解决方案7】:

    注意:这是迄今为止我找到的最佳答案,但赏金仍然开放——见下文。

    我使用浮点数找到了答案。看 https://jsfiddle.net/wwhyte/vjLps7qs/;将图片替换为 http://placekitten.com/1600/900 以查看横向行为。

    CSS:

      .container {
        width: calc(100vw);
        height: 100vh;
        overflow: hidden;
      }
    
      .top {
        height: 1.25em;
        background: yellow;
      }
    
      .innerCtr {
        height: 100%;
        overflow: hidden;
      }
    
      .left {
        height: 100%;
        background: red;
        overflow: hidden;
      }
    
      .right {
        max-height: 100%;
        max-width: 80%;
        background: blue;
        float: right;
        object-fit: contain;
        overflow: hidden;
        position: relative;
        top: 50%;
        transform: translateY(-52%) scale(0.95);
      }
    

    HTML:

    <div class="container">
      <div class="top">
      </div>
      <div class="innerCtr">
        <img class="right" src="http://placekitten.com/1600/900">
        <div class="left">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</div>
      </div>
    </div>
    

    认为正在发生的事情是:

    • 在正确的类中:
      • max-height、max-width 和 object-fit 为我提供了所需的缩放比例。
      • float:right 给出了我需要的位置。 (我从昨天找到的一篇文章中得到这个但现在丢失了,如果我重新找到它,我会编辑这个答案以提供归属)。
      • 变换的灵感来自于垂直对齐的文章:http://zerosixthree.se/vertical-align-anything-with-just-3-lines-of-css/
      • 95% 的比例提高了图像的可见度。
    • 在左侧类中,height:100% 给出了我想要的面板尺寸
    • innerCtr 类为图像提供父级以计算其高度
    • 容器类适合浏览器窗口的视口。

    即使这样也不是很理想。顶部栏的高度和图像的高度之间存在一些奇怪的相互作用,因此图像的底部被推出了显示器。推出的数量小于但与顶栏的高度有关——我还没有完全调查过。如果您删除顶部栏,则上面的 CSS 表现完美。我通过 95% 的比例和对 Y 变换的轻微调整来解决这个问题,但这仍然不能在小窗口尺寸下完全正确——图像不是完全垂直居中。我原以为在容器类上设置 height=calc(100vh-1.25em) 可能会解决这个问题,但实际上它破坏了图像的垂直缩放,所以它现在只能水平缩放。这是完全意想不到的行为! 因此,赏金仍然开放,如果有人可以让垂直居中完全正确地工作。

    感谢大家的建议!

    【讨论】:

      【解决方案8】:

      关于从图像中删除 flex 的答案是正确的,flex 用于容器而不是内容。这是一个工作示例..

      .grid {
        border: solid 1px #e7e7e7;
        height:95vh;
        display: flex;
        flex-direction: column;
      }
      
      .header {
        flex: 0;
      }
      
      .grid__row {
        flex: 1;
        display: flex;
        flex-direction:row;
      }
      
      .grid__item {
        white-space:nowrap;
        padding: 12px;
        border: solid 1px #e7e7e7;
      }
      
      img {
        object-fit:contain;
        border: solid 1px #e7e7e7;
        max-width:75%;
      }
      

      Fiddle

      【讨论】:

      • 这与我原来的问题中的 CSS 有相同的问题——当图像在给定窗口尺寸的情况下处于其最大高度时,左侧面板应扩展为最大可能宽度,并且图像应该很难靠在右侧。但是,在您的建议和我最初的问题中,我们最终会在图像的左侧和右侧进行填充。对不起...
      【解决方案9】:

      我已经在你的回答中修正了一些细节,现在我相信它工作正常。

      演示有 2 个版本,一个用于横向图像,另一个用于纵向。

      我在图像悬停时设置了一个动画,以显示它正确缩放并保持居中

      body {
          margin: 0px;
        }
      
        .container {
          width: calc(100vw);
          height: 50vh;
        }
      
        .top {
          height: 1.25em;
          background: yellow;
        }
      
        .innerCtr {
          height: calc(100% - 1.25em);  /* important to have the heuight ok */
          position: relative;     /* make the dimension inheritable */
        }
      
        .left {
          height: 100%;
          background: red;
          overflow: hidden;
        }
      
        .right {
          max-height: 100%;
          max-width: 80%;
          background: blue;
          float: right;
          object-fit: contain;
          top: 50%;
          position: relative;
          transform: translateY(-50%) scale(0.95) ;
      }
      
      .right:hover {
          animation: zoom 4s infinite;  
      }
      
      @keyframes zoom {
          from {transform: translateY(-50%) scale(0.98) }
          to {transform: translateY(-50%) scale(0) }
      }
      <div class="container">
        <div class="top">
        </div>
        <div class="innerCtr">
          <img class="right" src="http://placekitten.com/1600/900">
          <div class="left">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</div>
        </div>
      </div>
      <div class="container">
        <div class="top">
        </div>
        <div class="innerCtr">
          <img class="right" src="http://placekitten.com/900/1600">
          <div class="left">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</div>
        </div>
      </div>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-10
        • 2018-12-26
        • 2014-06-12
        • 1970-01-01
        • 1970-01-01
        • 2013-02-19
        • 1970-01-01
        相关资源
        最近更新 更多