Maison >interface Web >tutoriel CSS >Comment implémenter la disposition du flux en cascade à l'aide de JS ou CSS, plusieurs solutions sont introduites

Comment implémenter la disposition du flux en cascade à l'aide de JS ou CSS, plusieurs solutions sont introduites

青灯夜游
青灯夜游avant
2021-07-16 19:45:002661parcourir

Cet article vous guidera à travers la disposition du flux en cascade et présentera trois solutions JS fiables et N solutions CSS peu fiables. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il sera utile à tout le monde.

Comment implémenter la disposition du flux en cascade à l'aide de JS ou CSS, plusieurs solutions sont introduites

Dans un esprit pratique, nous allons partager aujourd'hui Disposition du débit de cascade (Un petit frère m'a demandé hier comment faire, et j'ai cherché longtemps mais je ne l'ai pas trouvé. Il s'est avéré à écrire sur l'intranet).

Adresse de démonstration : http://www.lilnong.top/static/html/waterfall.html

Quelle est la disposition du débit de la cascade ?

Par exemple, Petals.com, Mogujie (j'ai posté des photos ci-dessous), ces sites Web utilisent une disposition en cascade lors de l'affichage du contenu.

Nous souhaitons également créer une page qui affiche notre brouillon de conception (largeur fixe, hauteur variable). Le débit en cascade est une excellente solution.

Le cœur de la disposition du flux en cascade est basé sur une disposition en grille, et la hauteur de la liste d'éléments contenue dans chaque ligne est aléatoire (la hauteur change dynamiquement avec son propre contenu). disposés sous forme de pile, ce qui est le plus critique. Le fait est qu'il n'y a pas d'espacement inutile entre les piles. Jetons un coup d'œil à l'image ci-dessus pour voir à quoi ressemble la disposition du flux de cascade dont nous parlons.

网站 蘑菇街 花瓣网 京东 VV
截图 Comment implémenter la disposition du flux en cascade à laide de JS ou CSS, plusieurs solutions sont introduites Comment implémenter la disposition du flux en cascade à laide de JS ou CSS, plusieurs solutions sont introduites Comment implémenter la disposition du flux en cascade à laide de JS ou CSS, plusieurs solutions sont introduites Comment implémenter la disposition du flux en cascade à laide de JS ou CSS, plusieurs solutions sont introduites
方案 分通道 absolute

grid, inline, float Magic solution

peut également être considérée comme une solution CSS pure. En substance, elle repose sur le flux de documents, de gauche à droite, de haut en bas.

Vous pouvez voir qu'il existe un concept très évident de ligne dans la mise en page du flux de documents. Lorsqu'une ligne est étirée, elle laissera un espace vide et les lignes ne se chevaucheront pas. La chose la plus magique ici est la disposition des flotteurs .

Structure DOM

div.list     // 设置 gird 或者 block,注意清除浮动
  div.item   // 设置为 inline 或者 float,使其能流动
    img      // 设置定宽,高度自适应,间距等。

description de la solution de grille

.wrap-waterfall--grid img{vertical-align: top;width: 100px}
.wrap-waterfall--grid .list{
    display: grid;
    grid-gap: 10px;
    /* 可以看到,网格大小,占据位置是需要提前设定的 */
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: minmax(50px, auto);
}

la grille est préférable à utiliser que flex dans certains cas. Par exemple, vous devez dépasser la limite de lignes, mais cela ne s'applique qu'aux mises en page fixes, telles que la mise en page ci-dessous. Comment l'implémenteriez-vous si vous n'utilisez pas de grille ?

Comment implémenter la disposition du flux en cascade à laide de JS ou CSS, plusieurs solutions sont introduites

Il existe un plan pour implémenter la disposition des flux en cascade par GIRD sur Internet, mais j'ai vu que quelques-uns d'entre eux sont soit des blocs de couleur, soit une déformation et un recadrage d'image. Le plan est d'utiliser un nième enfant pour définir. la hauteur, C'est trop effrayant .

Colonnes, implémentation CSS flexible Solution peu fiable

C'est aussi une solution CSS pure. Par rapport à la solution ci-dessus, la solution est déjà acceptable, mais il y a encore quelques problèmes.

  • L'ordre est d'abord vertical, puis horizontal
  • (colonnes) Problèmes de compatibilité
  • (flex) doit recevoir une hauteur fixe, qui dépassera la colonne définie et ne parviendra pas à remplir la colonne définie.
方案 columns flex
截图 Comment implémenter la disposition du flux en cascade à laide de JS ou CSS, plusieurs solutions sont introduites 1Comment implémenter la disposition du flux en cascade à laide de JS ou CSS, plusieurs solutions sont introduites

le schéma de colonnes

est naturellement pris en charge, il vous suffit de le définir sur le parent columns: 4; column-gap: 6px; .

flex solution

flex-flow: column wrap;height: 2300px; est disposé horizontalement par défaut en le modifiant en disposition verticale et en autorisant le retour à la ligne, le contenu sera enveloppé d'une hauteur fixe.

Solution absolue de calcul de la hauteur du canal Solution fiable

方案 absolute 取余分通道 计算高度分通道
头部截图 1Comment implémenter la disposition du flux en cascade à laide de JS ou CSS, plusieurs solutions sont introduites 1Comment implémenter la disposition du flux en cascade à laide de JS ou CSS, plusieurs solutions sont introduites 1Comment implémenter la disposition du flux en cascade à laide de JS ou CSS, plusieurs solutions sont introduites

这里的方案就靠谱起来了,可以满足我们使用要求。

我们来回忆一下我们的需求:展示一些内容,内容有特性定宽,不定高。不定高一般是因为内容长度或者高度不一致导致的,常见内容又分为两种文字和图片

  • 文字的话,在没有异步字体的情况下,可以理解为同步就可以获取到盒子高度。

  • 图片的话,因为加载是异步的,所以获取盒子的真实高度也是异步的。但是这里一般分为两种情况

  • 无高度,那么可以通过onload来监听图片加载完成。等图片加载完成再去获取高度。

  • 有高度,这种方案一般用在封面图、或者文章中,在上传图片的时候会保存原图尺寸,这个时候我们就可以直接使用已有数据。

获取图片高度

// 用于获取图片的真实高度
naturalHeight: 1180
// 用于获取图片的真实宽度
naturalWidth: 1200

//用户获取图片当前的渲染高度(会受 css 影响)
height: 98
//用户获取图片当前的渲染宽度(会受 css 影响)
width: 100

// 可返回浏览器是否已完成对图像的加载。如果加载完成,则返回 true,否则返回 fasle。
complete 属性
// 可以监听到图片加载完成的动作
onload

基于上面的内容,那我们可以先判断 complete 属性,

function getImageSize(img){
    if(img.complete){
        return Promise.resolve({
            naturalHeight: img.naturalHeight,
            naturalWidth: img.naturalWidth,
            height: img.height,
            width: img.width,
        })
    }else{
        return new Promise((resolve, reject)=>{
            img.addEventListener('load', ()=>{
                resolve({
                    naturalHeight: img.naturalHeight,
                    naturalWidth: img.naturalWidth,
                    height: img.height,
                    width: img.width,
                })
            })
        })
    }
}
/*
// 测试用例
el = document.createElement('img');
el.src = 'http://cors-www.lilnong.top/favicon.ico?'+Math.random()

getImageSize(el).then(console.log).catch(console.error)
setTimeout(()=>getImageSize(el).then(console.log).catch(console.error), 1000)
*/

absolute 计算高度方案

因为普通的布局已经无法满足我们的需求,所以我们可以考虑通过 position: absolute 来使内容通过绝对定位来显示

核心操作就是维护每个元素的 left、top,然后使用 left 和 top 去渲染到正确位置。

getListPosition(){
    // 视口宽度 / 每列宽度 得出划分为几列
    let col = this.screenWidth / this.itemWidth >> 0;
    var arr = [];
    for(var i = 0; i < col; i++) arr.push({
        list: [],
        height: 0,
    })
    // 遍历所有元素
    this.listInfo.forEach((item,idx)=>{
        // 找到最低的一列
        var colIndex = 0;
        for(var i = 1; i < col; i++){
            if(arr[colIndex].height > arr[i].height){
                // colItem = arr[i]
                colIndex = i
            }
        }
        // 修改元素的信息
        // 所属列
        item.line = colIndex;
        // 计算之后的 top 距离
        item.top = arr[colIndex].height+ &#39;px&#39;;
        // 计算之后的 left 距离
        item.left = colIndex * (this.itemWidth + 10) + &#39;px&#39;

        // 累加操作
        arr[colIndex].list.push(item);
        arr[colIndex].height += item.height + 10;
    })
    return arr
},

通过计算,我们可以到,瀑布流布局下每个元素的位置,通过绝对定位就可以实现。

根据下标,来渲染到不同的通道 idx % 4

因为上个方案用到了绝对定位,那么有没有不用绝对定位的方案呢?回到我们的问题点上 定宽,不定高,那我们完全可以通过分开渲染放弃 absolute 来实现。

jsGroupList(){
    return this.list.reduce((s,n,idx)=>{
        // 根据下标,直接分配所属列
        s[idx % 4].push({idx: idx, item: n})
        return s
    }, [[],[],[],[],])
},

看开头是实现类似的功能的,但是有一个弊端(快来评论区回复呀)。

通过高度计算,然后分通道,避免 absolute

因为上一个方案是按下标分类的,其实瀑布流是按高度分类的,所以我们分类条件换成最低的列。

jsGroupHeightList(){
    var list = [
        {height: 0, list: []},{height: 0, list: []},
        {height: 0, list: []},{height: 0, list: []},
    ]
    // 遍历每个元素
    for(var i = 0; i < this.list.length; i++){
        // 当元素有大小的时候在进行操作。
        if(!this.listInfo[i].height) return list;
        // 默认第一个通道是最小高度列
        var minHeightItem = list[0];
        // 计算最小高度列
        list.forEach(v=>{
            if(v.height < minHeightItem.height) minHeightItem = v
        })
        // 把新的元素高度累加到列中。
        minHeightItem.height += this.listInfo[i].height
        // 把新的元素push到列中
        minHeightItem.list.push({idx: i, item: this.list[i]})
    }
    return list;
},

总结

好了,到这里我能想到的方案就都介绍了。你还有什么方案吗?咱们可以在评论区讨论一下可行性。接下来就是我们的方案总结了。

方案 优点 缺点 点评
columns 实现简单、纯 CSS 方案 兼容性 -
flex - 需要固定高度,填充难以控制等问题 -
float、inline、bootstrapGrid - - 没点大都用不出这方案
grid - - 可以nth-child模拟实现、或者等待兼容性 masonry
absolute 效果好 - JS计算无限可能
js普通通道 - 填充难以控制 -
js优化通道 效果好、无绝对定位 在出现夸列等操作的时候不是很好控制 -

更多编程相关知识,请访问:编程入门!!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer