【问题标题】:Resize background-image before applying contain/cover在应用包含/覆盖之前调整背景图像的大小
【发布时间】:2019-01-18 00:25:41
【问题描述】:

一般问题:

我想调整 CSS 背景图像的大小(不保持纵横比)并然后background-size: contain 应用于同一张图像。反过来做会在一定程度上抵消contain 选项的效果。

这可以用 HTML/CSS 来完成,还是有必要将 Javascript 引入其中?在我的用例中,事先手动编辑图像是不可行的。

我的用例:

http://jsfiddle.net/h5a2nxfd/68/

我有一些图片想要以横向或纵向模式改变纵横比显示。上面的 JSFiddle 没有改变大小。

我曾尝试使用transform 来应用缩放,但在当前解决方案中,div.item 的宽度/高度是可变的,因此不太可行。

我愿意接受您的建议。我可能试图从错误的角度解决这个问题。但我宁愿不使用 Javascript。

编辑:在 JSFiddle 中使用的示例 SVG 图像中添加了圆圈。

【问题讨论】:

  • 请注意:在您的代码 sn-p 中使用类似于圆形或其他东西的示例背景图像可能会更有帮助,因为使用纯色矩形无法区分外观无论他们是被倾斜到不同的纵横比还是被简单地剪裁。
  • 你如何决定你想要改变的纵横比?
  • @kenS 好点。我更新了 JSFiddle。
  • @vals 所需的纵横比是恒定的并且事先已知,并且当前对于所有相关图片都是相同的。当前所需的宽高比为 4:3。

标签: css flexbox background-image background-size


【解决方案1】:

我不知道你到底想要达到什么目的,尝试将 background-size 设置为 100% 而不是包含

【讨论】:

    【解决方案2】:

    如果您可以使用 HTML 和 CSS 解决方案,而不仅仅是纯 CSS 解决方案,则以下工作通过将图像嵌套在 div 中来工作,让您更有效地拆分 flex 项目大小样式和图像大小样式。您可以在弹性项目上设置样式以确定.image 将包含在其中的框的大小,和/或在.image 本身上设置宽度和高度以倾斜图像的纵横比。请注意,为了更快速地执行此操作,而不是在容器上设置固定宽度和高度,我为.image 创建了fixed-aspect-ratio 容器。您可以根据需要更改纵横比。我还使用了imgs 而不是divs 与背景图像,这使您可以对开箱即用的纵横比进行更多控制(即,与div 不同的是显式宽度和height: auto; on img 将保留纵横比,width: auto; 和显式高度也将保留,当您的布局从基于行的弹性盒布局切换到基于列的布局时,这可能很有用)。

    使用img 标签而不是divs 与背景图像将启用的另一个潜在好处是使用object-fit: contain; 属性(或object-fit: scale-down;,如果您希望图像只缩小而不是放大)而不是而不是将图像的宽度和高度设置为限制为适当纵横比的容器的 100%,或者在带有背景图像的 div 上使用 background-size: contain;。请参阅 MDN 以获取有关 object-fit 的参考信息,包括浏览器支持信息。

    这是一个工作代码 sn-p,带有 img 标记放置在纵横比框中,它们的纵横比没有被保留为问题请求:

    document.body.addEventListener("click", function() {
      document.body.classList.toggle("portrait");
    });
    html,
    body {
      height: 100%;
    }
    
    .container {
      height: auto;/*you had this as 100%. If you are going to constrain the height of your container, then you need to constrain the height of the items too to make sure they still fit inside, ie put max-height: 50%; on the items inside the container.*/
      width: 100%;
      display: flex;
      flex-flow: row wrap;
      /*align-items: stretch;*//*align-items: stretch; will cause potential problems with your layout if you intend for there to be more than 1 item per row/column*/
    }
    
    /*body.portrait .container {
      flex-direction: column;
    }*/
    
    .item {
      /*flex-grow: 1;*//*flex-grow: 1; will likewise cause potential problems with your layout if you intend for there to be more than 1 item per row/column*/
      width: 50%;/*can use width auto with images that have an intrinsic width to let image size determine width, or can set an explicit width as I have done here (for 1 image per row 100%, for 2 images per row 50%, etc)*/
    }
    
    .aspect-ratio-box-outer {
      position: relative;
      width: 100%;
      height: 0;
      padding: 0 0 75%;
      margin: 0;
    }
    
    .aspect-ratio-box-inner {
      position: absolute;
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
    }
    
    .item .image {
      background-repeat: no-repeat;
      background-position: center;
      background-size: 100% 100%;
      width: 100%;
      height: 100%;
    }
    
    body.portrait .aspect-ratio-box-outer {
      padding: 0 0 133.33333%;
    }
    
    
    /* The images are inline SVG for demonstration purposes only */
    /*.item.first {
      background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='500' height='400'><rect width='100%' height='100%' style='fill: red' /><circle cx='50%' cy='50%' r='150' style='fill: black' /></svg>");
    }*/
    /*.item.second {
      background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='500' height='400'><rect width='100%' height='100%' style='fill: blue' /><circle cx='50%' cy='50%' r='150' style='fill: black' /></svg>");
    }*/
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <title>Stackoverflow question</title>
    </head>
    
    <body>
      <p>
        Click to toggle between landscape and portrait mode.
      </p>
      <div class="container">
        <div class="item first">
          <div class="aspect-ratio-box-outer">
            <div class="aspect-ratio-box-inner">
              <!--<div class="image"></div>-->
    		  <img class="image" src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='500' height='400'><rect width='100%' height='100%' style='fill: red' /><circle cx='50%' cy='50%' r='150' style='fill: black' /></svg>" alt="" />
            </div>
          </div>
        </div>
        <div class="item second">
          <div class="aspect-ratio-box-outer">
            <div class="aspect-ratio-box-inner">
              <!--<div class="image"></div>-->
    		  <img class="image" src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='500' height='400'><rect width='100%' height='100%' style='fill: blue' /><circle cx='50%' cy='50%' r='150' style='fill: black' /></svg>" alt="" />
            </div>
          </div>
        </div>
      </div>
    </body>
    
    </html>

    【讨论】:

    • 感谢您的回答。不过,我发现您为其提供代码的解决方案存在一些问题。我需要图像尽可能多地占据容器的空间,同时仍被“包含”,但您的解决方案不会响应调整大小的窗口(请参阅我的 JSFiddle 如何响应调整大小)。一个更容易解决的问题是,在纵向模式下,纵横比仍应为 4:3,但不是 3:4。但是,再次感谢您的想法。我也有兴趣查看固定纵横比框和 img 标签解决方案。
    • 是的,这意味着您应该在我当前的 sn-p 中使用纵横比框而不是固定宽度框。请根据我帖子中的 css-tricks 链接随意尝试一下。我今天大部分时间都很忙,但如果有机会,我会更新我的答案以包含纵横比框的演示
    • 我已经更新了我的答案以使用宽高比框和 img 标签,而不是 divs 和背景图片。 sn-p 做了我理解你所要求的,倾斜图像而不保留它们的纵横比,而不是剪裁它们以适应你想要的 4:3 纵横比容器。
    • 我在这里对您的解决方案进行了修改:jsfiddle.net/h5a2nxfd/74 不幸的是,该解决方案无法处理屏幕高度不足以容纳图像的情况。如果屏幕高度不够,则应调整图像大小以适合容器(就像它们在原始帖子的 JSFiddle 中一样)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 2012-04-10
    相关资源
    最近更新 更多