没有回流或孤立边距的延迟加载列图像
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;
}
以下是根据您的问题提出的一些建议。
我还建议您学习更多有关 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>
我已经看到针对此问题的 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;
}
以下是根据您的问题提出的一些建议。
我还建议您学习更多有关 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>