8

努力让事情表现得很好。

我在响应式网站上有一个动态图像列表。生成布局,其中图像可以在行/列或列行中。

这个例子很接近,但是当浏览器调整大小时,配对的图像在底部没有对齐......

<div style="width:100%;">
    <div style="width:60%; display: flex;  margin-left: auto;  margin-right: auto;">
        <div id="outterrow" style="width:100%;  float:left; display: flex; padding-bottom: 1.15%; ">
            <div id="column" style="float: left;overflow: hidden;background-color: inherit;width: 49.35%;">
                <div id="row" style=" padding-right: 2.330294%; "><img title="2.jpeg" src="https://i.postimg.cc/Xv5YsYv7/2.jpg" sizes="100vw" width="100%"> 
                </div>
            </div>
            <div id="column" style="float: left;overflow: hidden;background-color: inherit;width: 50.65%;">
                <div id="row" style=" "><img title="1.jpg" src="https://i.postimg.cc/B6cQG7Dr/1.jpg" sizes="100vw" width="100%"> </div>
            </div>
        </div>
    </div>

    <div style="width:60%; display: flex;  margin-left: auto;  margin-right: auto;">

        <div id="outterrow" style="width:100%;  float:left; display: flex; padding-bottom: 1.15%; ">
            <div id="column" style="float: left;overflow: hidden;background-color: inherit;width: 100%;">
                <div id="row" style=" "><img title="3.jpg" src="https://i.postimg.cc/ZnbYYPxC/3.jpg"  sizes="100vw" width="100%"> </div>
            </div>
        </div>
    </div>
    
    <div style="width:60%; display: flex;  margin-left: auto;  margin-right: auto;">

        <div id="outterrow" style="width:100%;  float:left; display: flex; padding-bottom: 1.15%; ">
            <div id="column" style="float: left;overflow: hidden;background-color: inherit;width: 43.55%;">
                <div id="row" style=" padding-right: 2.640643%; "><img title="5.jpg" src="https://i.postimg.cc/bwsJ2Tcn/5.jpg"  sizes="100vw"  width="100%"> </div>
            </div>
            <div id="column" style="float: left;overflow: hidden;background-color: inherit;width: 56.45%;">
                <div id="row" style=" "><img title="4.jpg" src="https://i.postimg.cc/XJ07m6ZK/4.jpg" sizes="100vw" width="100%"> </div>
            </div>
        </div>
    </div>
    
</div>

我已经尝试过对象匹配,但 Safari 似乎分崩离析。

编辑:供参考这里是问题的一个例子。

在此处输入图像描述

4

3 回答 3

3

您当然可以使用背景图像而不是 HTML img-tag。如果您可以访问图像高度,我建议您通过 JavaScript 或 PHP(或您拥有的任何设置)动态填充该高度。我在包装容器内放置了一个 spacer-div,可用于此目的。

#wrap_all {
  width:100%;
}

#inner {
  max-width:1210px;
  padding:0 50px;
  margin:0 auto;
}

.flexrow {
  display:flex;
  justify-content: space-between;
  background:#f5f5f5;
  flex-wrap:wrap;
}


.flexcol {
  flex:0 0 49%;
  background-repeat: no-repeat;
  background-size: cover;
  background-position:top center;
  margin-bottom: 2%;
}

.spacer.height-80vh {
  height:80vh;
}

.flexcol.fullwidth {
  flex:0 0 100%;
}
<div id="wrap_all">
    
  <div id="inner">
    
    <div class="flexrow">
      
      <div class="flexcol" style="background-image: url('https://i.postimg.cc/Xv5YsYv7/2.jpg')">
        <div class="spacer height-80vh"></div>
      </div>
      
      <div class="flexcol" style="background-image: url('https://i.postimg.cc/B6cQG7Dr/1.jpg')">
        <div class="spacer height-80vh"></div>
      </div>
      
      <div class="flexcol fullwidth" style="background-image: url('https://i.postimg.cc/ZnbYYPxC/3.jpg')">
        <div class="spacer height-80vh"></div>
      </div>
      
      <div class="flexcol" style="background-image: url('https://i.postimg.cc/bwsJ2Tcn/5.jpg')">
        <div class="spacer height-80vh"></div>
      </div>
      
      <div class="flexcol" style="background-image: url('https://i.postimg.cc/XJ07m6ZK/4.jpg')">
        <div class="spacer height-80vh"></div>
      </div>
      
    </div>
    
  </div>  
  
</div>

于 2019-10-29T19:27:09.147 回答
2

这称为像素舍入或亚像素问题,这是一个基本的数学问题:

您有两个相对宽度约为 50% 的容器位于响应式父级内部。当父元素的宽度是奇数时会发生什么?说 211 像素。211px 的 50% 是 105.5px。但是,没有 .5px 这样的东西——你的屏幕不能只打开那个物理定义一个像素的小灯泡的一半。浏览器将其四舍五入为更大或更小的数字。

如果仔细观察,布局由以下部分组成:

  • 宽度为小数百分比值的列 (49.35%)
  • 间距的小数百分比(填充:2.330294%)
  • 具有随机宽度和高度的图像
  • 没有为任何列定义高度。
  • 全部由响应式 div 包裹,这意味着任何地方都没有绝对宽度或高度。

没有解决方案可以在 % 导向布局内的不同尺寸的 div 中插入不同尺寸的图像。这只是太多的像素四舍五入。如果你仔细观察,这个布局在 100% 的时间里都是“损坏的”……它要么留下空白像素,要么缩小/扭曲内部的图像。

无论任何人在场的任何黑客都会生成那个小的空白像素,扭曲图像(再次,它们没有相同的高度或宽度)或秘密地隐藏图像中的某个像素。

现在,对您展示的特定片段进行快速破解:

  • 使用绝对像素向左填充
  • 使用 :after 向 padding-bottom 添加一个空格

img {
  vertical-align: bottom;
}

.column {
  position: relative;
}

.column:after {
  content: '';
  display: block;
  position: absolute;
  bottom: 0;
  width: 100%;
  background: #fff;
  height: 6px; /* this will fake padding bottom */
}

.row {
  padding-left: 6px;
}
<div style="width:100%;">
  <div style="width:60%; display: flex;  margin-left: auto;  margin-right: auto;">
    <div id="outterrow" style="width:100%;  float:left; display: flex;">
      <div class="column" style="float: left;overflow: hidden;background-color: inherit;width: 49.35%;">
        <div class="row" ><img title="2.jpeg" src="https://i.postimg.cc/Xv5YsYv7/2.jpg" sizes="100vw" width="100%">
        </div>
      </div>
      <div class="column" style="float: left;overflow: hidden;background-color: inherit;width: 50.65%;">
        <div class="row" style=" "><img title="1.jpg" src="https://i.postimg.cc/B6cQG7Dr/1.jpg" sizes="100vw" width="100%"> </div>
      </div>
    </div>
  </div>

  <div style="width:60%; display: flex;  margin-left: auto;  margin-right: auto;">

    <div id="outterrow" style="width:100%;  float:left; display: flex;">
      <div class="column" style="float: left;overflow: hidden;background-color: inherit;width: 100%;">
        <div class="row" style=" "><img title="3.jpg" src="https://i.postimg.cc/ZnbYYPxC/3.jpg" sizes="100vw" width="100%"> </div>
      </div>
    </div>
  </div>

  <div style="width:60%; display: flex;  margin-left: auto;  margin-right: auto;">

    <div id="outterrow" style="width:100%;  float:left; display: flex; ">
      <div class="column" style="float: left;overflow: hidden;background-color: inherit;width: 43.55%;">
        <div class="row"><img title="5.jpg" src="https://i.postimg.cc/bwsJ2Tcn/5.jpg" sizes="100vw" width="100%"> </div>
      </div>
      <div class="column" style="float: left;overflow: hidden;background-color: inherit;width: 56.45%;">
        <div class="row" style=" "><img title="4.jpg" src="https://i.postimg.cc/XJ07m6ZK/4.jpg" sizes="100vw" width="100%"> </div>
      </div>
    </div>
  </div>

</div>

同样,在这些条件下不存在“解决方案”,只是有缺陷的黑客攻击。

*公平地说,浏览器在处理像素舍入方面做得非常好,以至于大多数开发人员甚至都没有意识到这是一个问题。

于 2019-10-30T04:04:38.463 回答
0

当 CSS 失败时,我会去 vanillaz:

document.addEventListener('DOMContentLoaded', function() {
  [...document.querySelectorAll('.flex-fill')].forEach(div => {
    [...div.querySelectorAll('img')].forEach(img => {
      img.addEventListener('load', () => {
        const box = document.createElement('div');
        const basis = img.height ? img.width * 100 / img.height : 0;
        box.style.background = `url('${img.src}') center /cover no-repeat`;
        box.style.flexBasis = `${basis}%`;
        box.setAttribute('data-basis', basis);
        div.insertBefore(box, img);
        box.appendChild(img);
      })
    })
  });
  const resizeFlexFills = _.throttle(() => {
    [...document.querySelectorAll('.flex-fill')].forEach(div => {
      const gutter = (div.currentStyle || window.getComputedStyle(div))
        .marginBottom.match(/\d+/)[0] || 0;
      const children = [...div.querySelectorAll('div')];
      const basisSum = children.map(e => e.dataset.basis)
        .reduce((a, b) => Number(a) + Number(b));
      div.style.height = `${(div.offsetWidth - ((children.length - 1) * gutter)) * 100 / basisSum}px`;
      [...div.querySelectorAll('div:not(:last-child)')].forEach(div => {
        div.style.marginRight = `${gutter}px`
      })
    })
  }, 100, {
    leading: true,
    trailing: true
  });
  window.addEventListener('load', resizeFlexFills);
  window.addEventListener('resize', resizeFlexFills);
});
.flex-fill {
  width: 100%;
  display: flex;
  height: 0;
  transition: height .3s cubic-bezier(.4, 0, .2, 1);
  /* gutter size (remove if you don't want any space between them) */
  margin-bottom: 8px;
}

.flex-fill img {
  display: none;
}

@media(max-width: 600px) {
  .flex-fill {
    height: auto !important;
    display: block;
  }
  .flex-fill img {
    display: block;
    width: 100%;
   /* needs to be same as gutter size, above */
    margin-bottom: 8px;
  }
  .flex-fill div {
    margin-right: 0 !important;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

<div class="flex-fill">
  <img title="1.jpg" src="https://i.postimg.cc/B6cQG7Dr/1.jpg">
  <img title="5.jpg" src="https://i.postimg.cc/bwsJ2Tcn/5.jpg">
  <img title="4.jpg" src="https://i.postimg.cc/XJ07m6ZK/4.jpg">
  <img title="2.jpeg" src="https://i.postimg.cc/Xv5YsYv7/2.jpg">
  <img title="3.jpg" src="https://i.postimg.cc/ZnbYYPxC/3.jpg">
</div>
<div class="flex-fill">
  <img title="2.jpeg" src="https://i.postimg.cc/Xv5YsYv7/2.jpg">
  <img title="1.jpg" src="https://i.postimg.cc/B6cQG7Dr/1.jpg">
</div>
<div class="flex-fill">
  <img title="3.jpg" src="https://i.postimg.cc/ZnbYYPxC/3.jpg">
</div>
<div class="flex-fill">
  <img title="5.jpg" src="https://i.postimg.cc/bwsJ2Tcn/5.jpg">
  <img title="4.jpg" src="https://i.postimg.cc/XJ07m6ZK/4.jpg">
</div>

笔记:

  • 它的特别之处在于,无论有没有装订线,图像比例都保持不变,正如您所见,它是完美的像素
  • 然而,要做到这一点,resizeFlexFills()需要绑定loadresize更新高度
  • 因此我使用 lodashthrottle只允许每次运行它100ms
  • 排水沟是通过 CSS 设置的,并且仅适用于px. 它可以做得更聪明,但是将 CSS 单元解析为像素超出了这个问题的范围(恕我直言)。
  • transition是完全可以抛弃的
  • 它不是“响应式”,但可以很容易地做到这一点。为此,我会将<img>s 保留在其中,将它们显示为所需设备宽度下的块,同时flex-directioncolumn.
    实际上,我让它响应。如果您不想要它,请删除@media查询代码。
于 2019-10-31T02:10:34.330 回答