延迟加载不带回流或孤立边距的列图像

时间:2017-03-15 20:13:45

标签: html css lazy-loading multiple-columns

我已经看到了针对此问题的各个部分的修复,但没有针对集体解决方案的修复。我可以解决所有问题而不需要使用javascript格式,除了元素的边距被转移到下一列的顶部(我无法理解为什么它没有被修复但是它似乎是css3中的一个错误有一段时间阻碍了合成布局12

我将一个响应式div容器分成三列(虽然这可以根据页面的宽度,每个响应式布局而改变),包含不同数量的嵌套图像,每个嵌套图像具有不同的宽高比保证金底部财产。上面的问题非常明显,所以我正在寻找解决方案。

通常,建议涉及使用column-break-inside: avoid;属性以及将margin-bottom切换为padding-bottom。这个hack已经在其他人身上取得了一些成功,这也是我向你提出问题主题的地方。我无法实现这一点,因为我使用单独的黑客来阻止延迟加载(使用lazy sizes插件*)的图像重排到列中(padding-bottom作为比率黑客,{ {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:

3

元素应该在每列的顶部对齐,但是,第一列或第二列底部的元素(imagecontainer)上的margin-bttom被转移到第二列或第三列并且是孤立的,下一个元素具有margin-top值并打破顶部对齐的印象。这对于故意保证金最高价值无法重建的任何情况都没有任何好处。我只是为这个例子随机化了元素的高度,所以偶尔会出现问题(强调它有多大的麻烦。很难刻意展示)。如果它不发生则刷新,因为它经常发生。

3 个答案:

答案 0 :(得分:1)

经过大量的反复思考后,我想出了一个能够解决问题并保留原始CSS属性的答案。似乎有两个问题导致了这一点 1 - 边距正在转换到下一列(但元素保留在自己的列中)
2 - 身高受到限制(解决方案中存在问题)

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

找到实时版本

答案 1 :(得分:1)

这可以使用一个带有填充的额外容器来解决。图像的容器(.imagecontainer)应该只包含 图像,因为它是为其设置的宽高比。可以通过在该块上设置填充来实现块与列中的下一个块之间的空间。然后该块获得样式,以防止发生列中断。

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

特别是,我添加了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
  * https://stackoverflow.com/a/7785711/962603 */
  -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>

答案 2 :(得分:0)

以下是使用弹性框的解决方案

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

以下是基于您的问题的一些建议。

我还建议学习更多有关弹性盒的知识,它非常适合处理这些情况。

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

here is a reference I use on flex-boxes

解决宽高比
您可以使用px和vw / vh(DOM宽度和高度的测量值)来处理纵横比。尝试使用最小/最大/宽度来寻找完美的数量。 (1:2宽高比)

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

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