没有回流或孤立边距的延迟加载列图像

Lazy load column images without reflow or orphaned margins

我已经看到针对此问题的 div 两个部分的修复,但没有一个针对集体解决方案。我可以在不求助于 javascript 格式的情况下解决所有问题,除了元素的边距被转移到下一列的顶部(我不明白为什么它没有被修复,但它似乎是 css3 有一段时间阻碍合成布局 1, 2)

我有一个响应式 div 容器,它分为三列(尽管这可能会根据页面宽度、每个响应式布局而改变),其中包含 div 数量不等的不同宽高比的嵌套图像,每个图像都有一个 margin-bottom 属性。上面的问题非常明显,所以我正在寻找解决方案。

通常,该建议涉及使用 column-break-inside: avoid; 属性,同时将我的 margin-bottom 切换为 padding-bottom。这个 hack 已经在其他人身上取得了一些成功,这就是我向您指出我的问题主题的地方。我无法实现这一点,因为我正在使用单独的 hack 来防止回流延迟加载的图像(使用 lazy sizes plugin*) into the columns (the padding-bottom as a ratio hack, 3)。

因此,如果我使用 padding-bottom 来确保我的列元素在没有孤立边距的情况下对齐,我将无法更正因将元素延迟加载到列中而导致的回流。我不能使用固定大小的元素,因为列布局是响应式的,并且元素会随着列大小动态缩小和放大。

有没有人在没有 javascript 格式化的情况下成功地同时解决了这两个问题?

出于此问题范围之外的原因,我热衷于坚持使用这个特殊的延迟加载插件。

HTML代码:

<div id='columncontainer'>
    <div class='imagecontainer' style='padding-bottom:reflowPaddingAmountFromPHPvar;'>
        <img class='lazyload'>
        <div class='imagetextcontainer'>
            <div class='vertaligncontainer'>
                <p class='imagename'>Text</p>
                <p class='imagedesc'>Text</p>
            </div>
        </div>
    </div>
</div>

CSS代码:

#myContent  {
    position: relative;
    width: 100%;
    column-count: 3;
    column-gap: 20px;
    column-break-inside: avoid;
    -moz-column-break-inside:avoid;
    -webkit-column-break-inside:avoid;
}

.imagecontainer {
    position: relative;
    margin-bottom: 20px;
    img {
        position: absolute;
        top: 0;
        left: 0;
        height: auto;
        width: 100%;
    }
}

示例 jsFiddle:

https://jsfiddle.net/g0yjd9ov/1/

元素应在每列的顶部对齐,但第一列或第二列底部的元素 (imagecontainer) 上的 margin-bttom 被转移到第二列或第三列并成为孤立元素,给人的印象是下一个元素具有 margin-top 值并打破了顶部对齐。这对无法重新创建有意保证金顶部值的任何情况都没有好处。我只是为了这个例子随机化了元素的高度,所以偶尔不会显示问题(强调它是多么令人讨厌。很难故意显示)。没有就刷新一下,因为经常出现。

这是一个使用 flex-boxes 的解决方案

HTML

<div id='columncontainer'>

    <div class='imagecontainer'>
        <img class='lazyload'>
        <div class='imagetextcontainer'>
            <div class='vertaligncontainer'>
                <p class='imagename'>Text</p>
                <p class='imagedesc'>Text</p>
            </div>
        </div>
    </div>

    <div class='imagecontainer'>
        <img class='lazyload'>
        <div class='imagetextcontainer'>
            <div class='vertaligncontainer'>
                <p class='imagename'>Text</p>
                <p class='imagedesc'>Text</p>
            </div>
        </div>
    </div>

    <div class='imagecontainer'>
        <img class='lazyload'>
        <div class='imagetextcontainer'>
            <div class='vertaligncontainer'>
                <p class='imagename'>Text</p>
                <p class='imagedesc'>Text</p>
            </div>
        </div>
    </div>

    <div class='imagecontainer' style=''>
        <img class='lazyload'>
        <div class='imagetextcontainer'>
            <div class='vertaligncontainer'>
                <p class='imagename'>Text</p>
                <p class='imagedesc'>Text</p>
            </div>
        </div>
    </div>


</div>

CSS

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}

#columncontainer  {
    position: relative;
    width: 100%;
    display: flex;
    height: 40%;
    /* use this if you want containter wrapping
    flex-wrap: wrap; */
    /* use this if you want container scrolling
    overflow: auto; */
    /* use this if you want container scrolling
    justify-content: center; */ 
}

.imagecontainer {
    min-width: 250px;
    position: relative;
    background-color: red;
    overflow: hidden;
    height: 100%;
    margin: 5px;
    z-index: 1;
}

example in jsfiddle

以下是根据您的问题提出的一些建议。

我还建议您学习更多有关 flex-boxes 的知识,它非常适合处理此类情况。

默认情况下,html 和正文元素的默认大小为宽度 100%,没有高度。

here is a reference I use on flex-boxes

处理宽高比
您可以使用 px 和 vw/vh(DOM 宽度和高度的测量值)处理纵横比。尝试使用 min/max/width 来找到最合适的数量。 (1:2 纵横比)

element {
  min-width: 10vw;
  min-height: 20vh;
  width: 50px;
  height: 100px;
}

css size units 在我的版本中,您可以编辑“.imagecontainer”。

经过多次来回,我想出了一个解决问题并保持原始 CSS 属性的答案。似乎有两个问题导致了这个。
1 - 边距转换到下一列(但元素保留在其自己的列中)
2 - 高度受限(解决方案中存在问题)

解决方案: 因为整个元素都在自己的列中,但边距在技术上不是元素的一部分(可以使用大纲进行测试) 这个问题可以通过将 .imagecontainer 放入另一个具有填充而不是边距的 div 来解决。 (因此它被认为是一个对象,因此避免了保证金问题) 您还需要将 column-break-inside 移动到父元素,以便它在没有边距的情况下注册。 可以在以下位置找到实时版本:https://jsfiddle.net/36pqdkd3/6/

这可以使用一个额外的容器来解决,容器上有填充物。图像的容器 (.imagecontainer) 应包含 图像,因为这是设置其宽高比的原因。一个块和列中下一个块之间的 space 可以通过在该块上设置填充来实现。然后该块获得防止出现分栏符的样式。

我创建了一个基于问题中的示例代码的演示,但也包括一些仅在问题文本中描述的内容。这是因为我想确保一切都按照我认为应该的方式进行(如果我误解了这个问题,请告诉我)。

特别是,我添加了 lazy sizes 插件并让它加载一些占位符图像。我还添加了一些样式并添加了包含多个图像的块。对于防止元素内部中断的规则,我使用了一些略有不同的规则,根据 this answer。最后,我按照问题评论中的讨论定位了 .imagetextcontainer

可在 JSFiddle 上找到该演示。我还将其作为代码片段包含在此处。

#columncontainer  {
  width: 100%;
  column-count: 3;
  column-gap: 10px;
}

.block-wrap {
  width: 100%;
  padding-bottom: 10px;
  
  /* prevent column breaks in item
  *  */
  -webkit-column-break-inside: avoid; /* Chrome, Safari */
  page-break-inside: avoid;           /* Theoretically FF 20+ */
  break-inside: avoid-column;         /* IE 11 */
  display:table;                      /* Actually FF 20+ */
}

.block {
  width: 100%;
  background-color: #ffff7f;
}

.block > p {
  margin: 0;
  padding: 10px;
}

.imagecontainer {
  position: relative;
  width: 100%;
  height: 0;
  background-color: #a00;
}

.imagecontainer > img {
  width: 100%;
}

.imagetextcontainer {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
<script src="https://afarkas.github.io/lazysizes/lazysizes.min.js"></script>

<div id='columncontainer'>

  <div class="block-wrap">
    <div class="block">
      <div class='imagecontainer' style='padding-bottom: 50%;'>
        <img class='lazyload'
             data-sizes='auto'
             data-srcset='https://placehold.it/100x50/a00/fff  100w,
                          https://placehold.it/200x100/050/fff 200w,
                          https://placehold.it/400x200/057/fff 400w' />
        <div class='imagetextcontainer'>
          <div class='vertaligncontainer'>
            <p class='imagename'>Name</p>
            <p class='imagedesc'>Description</p>
          </div>
        </div>
      </div>
      <p>Some text. Followed by another figure.</p>
      <div class='imagecontainer' style='padding-bottom: 100%;'>
        <img class='lazyload'
             data-sizes='auto'
             data-srcset='https://placehold.it/100x100/a00/fff 100w,
                          https://placehold.it/200x200/050/fff 200w,
                          https://placehold.it/400x400/057/fff 400w' />
        <div class='imagetextcontainer'>
          <div class='vertaligncontainer'>
            <p class='imagename'>Name</p>
            <p class='imagedesc'>Description</p>
          </div>
        </div>
      </div>
    </div>
  </div>

  <div class="block-wrap">
    <div class="block">
      <div class='imagecontainer' style='padding-bottom: 50%;'>
        <img class='lazyload'
             data-sizes='auto'
             data-srcset='https://placehold.it/100x50/a00/fff  100w,
                          https://placehold.it/200x100/050/fff 200w,
                          https://placehold.it/400x200/057/fff 400w' />
        <div class='imagetextcontainer'>
          <div class='vertaligncontainer'>
            <p class='imagename'>Name</p>
            <p class='imagedesc'>Description</p>
          </div>
        </div>
      </div>
      <p>Some text. No figure here.</p>
    </div>
  </div>

  <div class="block-wrap">
    <div class="block">
      <p>Only text here.</p>
    </div>
  </div>

  <div class="block-wrap">
    <div class="block">
      <div class='imagecontainer' style='padding-bottom: 50%;'>
        <img class='lazyload'
             data-sizes='auto'
             data-srcset='https://placehold.it/100x50/a00/fff  100w,
                          https://placehold.it/200x100/050/fff 200w,
                          https://placehold.it/400x200/057/fff 400w' />
        <div class='imagetextcontainer'>
          <div class='vertaligncontainer'>
            <p class='imagename'>Name</p>
            <p class='imagedesc'>Description</p>
          </div>
        </div>
      </div>
    </div>
  </div>

  <div class="block-wrap">
    <div class="block">
      <div class='imagecontainer' style='padding-bottom: 100%;'>
        <img class='lazyload'
             data-sizes='auto'
             data-srcset='https://placehold.it/100x100/a00/fff 100w,
                          https://placehold.it/200x200/050/fff 200w,
                          https://placehold.it/400x400/057/fff 400w' />
        <div class='imagetextcontainer'>
          <div class='vertaligncontainer'>
            <p class='imagename'>Name</p>
            <p class='imagedesc'>Description</p>
          </div>
        </div>
      </div>
    </div>
  </div>

  <div class="block-wrap">
    <div class="block">
      <p>Only text here.</p>
      <p>Tow lines now.</p>
    </div>
  </div>

  <div class="block-wrap">
    <div class="block">
      <div class='imagecontainer' style='padding-bottom: 200%;'>
        <img class='lazyload'
             data-sizes='auto'
             data-srcset='https://placehold.it/100x200/a00/fff 100w,
                          https://placehold.it/200x400/050/fff 200w,
                          https://placehold.it/400x800/057/fff 400w' />
        <div class='imagetextcontainer'>
          <div class='vertaligncontainer'>
            <p class='imagename'>Name</p>
            <p class='imagedesc'>Description</p>
          </div>
        </div>
      </div>
    </div>
  </div>

</div>