css - 在应用包含/覆盖之前调整背景图像的大小

标签 css flexbox background-image background-size

一般问题:

我想调整 CSS 背景图像的大小(不保持纵横比),然后background-size: contain 应用于同一图像。以相反的方式进行操作会在某种程度上抵消 contain 选项的影响。

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

我的用例:

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

我有一些图片,我想以改变的纵横比从一边到另一边或从上到下显示,具体取决于是横向还是纵向模式处于事件状态。上面的 JSFiddle 缺少大小更改。

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

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

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

最佳答案

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

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

这是一个工作代码片段,其中 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>

关于css - 在应用包含/覆盖之前调整背景图像的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51785634/

相关文章:

html - 在我的 div 中调整背景图片的大小

javascript - 隐藏第一个面板上的导航 - PanelSnap 插件

html - 样式化媒体查询,忽略/覆盖父样式

html - flex 元素缩小并隐藏其内容

css - 使一个 div 跨越网格中的两行

javascript - 基于时间的特定背景

javascript - 使用 JavaScript 更改背景图像

html - 无法使div在html中 float

javascript - 界面网页 View 。使用 javascript 替换 css 属性

javascript - CSS Flexbox - 当容器有更多 child 时宽度中断