如何在 Bootstrap 3 中将多个项目彼此对齐?

How to align multiple items below each other in Bootstrap 3?

我正在使用 Meteor 创建一个应用程序,使用 alethes:pages 包进行分页,Bootstrap 3 用于样式。 在主页中,我使用无限滚动显示多个项目(每行 3 个)。

当一个项目高于他的相邻项目时,问题就来了,使下一行有一个空闲 space 并向右浮动一个项目,而不是出现在更高的项目下方。在这里你可以看到问题:

我为分页包要使用的项目制作了一个 HTML 模板。 因此,对于图中所示的示例,生成的代码将是:

<div class="col-md-10 col-lg-10 col-md-offset-2 col-lg-offset-2">
    <div class="pagesCont">
        <div class="col-md-4 col-lg-4">
            <div class="col-md-12 col-lg-12 well">
                <h4 class="break-word">
                    <a href="#">Item 1</a>
                </h4>
                <a href="#">
                    <img src="/cfs/files/images_publications/jvtQWo4KSziMXCryh/300x340.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&amp;store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
                </a>
                <h5 class="col-md-8 col-lg-8 break-word">
                    <a href="#">Category</a>
                </h5>
                <h4 class="col-md-4 col-lg-4 text-right"> 1 €</h4>
                <div>
                    <div class="col-md-12 col-lg-12">
                        <a href="#" class="break-word">UserName UserLastName</a>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-4 col-lg-4">
            <div class="col-md-12 col-lg-12 well">
                <h4 class="break-word">
                    <a href="#">Item 2</a>
                </h4>
                <a href="#">
                    <img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&amp;store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
                </a>
                <h5 class="col-md-8 col-lg-8 break-word">
                    <a href="#">Category</a>
                </h5>
                <h4 class="col-md-4 col-lg-4 text-right"> 2 €</h4>
                <div>
                    <div class="col-md-12 col-lg-12">
                        <a href="#" class="break-word">UserName UserLastName</a>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-4 col-lg-4">
            <div class="col-md-12 col-lg-12 well">
                <h4 class="break-word">
                    <a href="#">Item 3</a>
                </h4>
                <a href="#">
                    <img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&amp;store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
                </a>
                <h5 class="col-md-8 col-lg-8 break-word">
                    <a href="#">Category</a>
                </h5>
                <h4 class="col-md-4 col-lg-4 text-right"> 3 €</h4>
                <div>
                    <div class="col-md-12 col-lg-12">
                        <a href="#" class="break-word">UserName UserLastName</a>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-4 col-lg-4">
            <div class="col-md-12 col-lg-12 well">
                <h4 class="break-word">
                    <a href="#">Item 4</a>
                </h4>
                <a href="#">
                    <img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&amp;store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
                </a>
                <h5 class="col-md-8 col-lg-8 break-word">
                    <a href="#">Category</a>
                </h5>
                <h4 class="col-md-4 col-lg-4 text-right"> 4 €</h4>
                <div>
                    <div class="col-md-12 col-lg-12">
                        <a href="#" class="break-word">UserName UserLastName</a>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-4 col-lg-4">
            <div class="col-md-12 col-lg-12 well">
                <h4 class="break-word">
                    <a href="#">Item 5</a>
                </h4>
                <a href="#">
                    <img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&amp;store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
                </a>
                <h5 class="col-md-8 col-lg-8 break-word">
                    <a href="#">Category</a>
                </h5>
                <h4 class="col-md-4 col-lg-4 text-right"> 5 €</h4>
                <div>
                    <div class="col-md-12 col-lg-12">
                        <a href="#" class="break-word">UserName UserLastName</a>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-4 col-lg-4">
            <div class="col-md-12 col-lg-12 well">
                <h4 class="break-word">
                    <a href="#">Item 6</a>
                </h4>
                <a href="#">
                    <img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&amp;store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
                </a>
                <h5 class="col-md-8 col-lg-8 break-word">
                    <a href="#">Category</a>
                </h5>
                <h4 class="col-md-4 col-lg-4 text-right"> 6 €</h4>
                <div>
                    <div class="col-md-12 col-lg-12">
                        <a href="#" class="break-word">UserName UserLastName</a>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-4 col-lg-4">
            <div class="col-md-12 col-lg-12 well">
                <h4 class="break-word">
                    <a href="#">Item 7</a>
                </h4>
                <a href="#">
                    <img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&amp;store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
                </a>
                <h5 class="col-md-8 col-lg-8 break-word">
                    <a href="#">Category</a>
                </h5>
                <h4 class="col-md-4 col-lg-4 text-right"> 7 €</h4>
                <div>
                    <div class="col-md-12 col-lg-12">
                        <a href="#" class="break-word">UserName UserLastName</a>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-4 col-lg-4">
            <div class="col-md-12 col-lg-12 well">
                <h4 class="break-word">
                    <a href="#">Item 8</a>
                </h4>
                <a href="#">
                    <img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&amp;store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
                </a>
                <h5 class="col-md-8 col-lg-8 break-word">
                    <a href="#">Category</a>
                </h5>
                <h4 class="col-md-4 col-lg-4 text-right"> 8 €</h4>
                <div>
                    <div class="col-md-12 col-lg-12">
                        <a href="#" class="break-word">UserName UserLastName</a>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-4 col-lg-4">
            <div class="col-md-12 col-lg-12 well">
                <h4 class="break-word">
                    <a href="#">Item 9</a>
                </h4>
                <a href="#">
                    <img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&amp;store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
                </a>
                <h5 class="col-md-8 col-lg-8 break-word">
                    <a href="#">Category</a>
                </h5>
                <h4 class="col-md-4 col-lg-4 text-right"> 9 €</h4>
                <div>
                    <div class="col-md-12 col-lg-12">
                        <a href="#" class="break-word">UserName UserLastName</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

我可以使项目具有相同的高度,但我想要具有不同的图像大小和多行文本,而不在项目内留下空闲 space。

我想要类似于此网站中显示的项目列表的内容:http://es.wallapop.com/

但该列表的问题在于使用绝对位置来显示彼此下方的项目。我想避免绝对位置,因为我认为与前面提到的包集成起来并不那么容易。

我不知道在 Bootstrap 3 中是否可以在不使用绝对位置的情况下实现类似的功能。

我认为这与流星或分页无关。

您正在寻找的可能是用 bootstrap 实现 masonyjs。像这样的布局会变得非常有趣和棘手。我肯定会研究那个组合。

关注评论中的对话:

经过大量研究和测试,我终于让 Masonryalethes:pages 包完美配合。我知道,在我上次的评论中我说过我放弃了这个,但是在我自制的无限滚动一段时间后我意识到它没有对 mongodb 变化做出反应,它是静态的。我不想花更多时间在这上面...

在向您展示神奇的代码之前,您必须牢记以下几点:

  • 使用Masonry的最佳方式是使用Isotope,至少对我来说是这样。我推荐你安装这个流星包:isotope:isotope

  • 您还需要 ImagesLoadead 库:iamkevingreen:imagesloaded

  • alethes:pages 包使用 document.body.offsetHeight DOM 属性 作为总页面高度,以便在滚动时加载新项目。如果你使用的是Bootstrap,那属性可能并不代表页面的总高度,所以无论你在infiniteTrigger选项中设置什么,每次滚动都会添加新的项目。解决这个问题的方法是在关闭正文之前添加一个 clearfix

    <template name="MasterLayout">
        ...
        {{> yield}}
        <div class="clearfix"></div>
    </template>
  • Masonry使用的项目容器必须有padding: 0(至少左边和右边)才能使用Bootstrap正确显示。

现在,让我们看一下代码。

这是服务器代码:

Items =  new Meteor.Collection('items');

ItemsPagination = new Meteor.Pagination(Items, {
    templateName: "ItemsList",
    itemTemplate: "Item",
    divWrapper: 'container',
    infinite: true,
    infiniteTrigger: 0.8,
    pageSizeLimit: 1512,
    dataMargin: 0,
    perPage: 21
});

这些是分页对象使用的模板:

<template name="ItemsList">
    {{> pages}}
</template>

<template name="Item">

    <div class="ms-item col-md-4 col-lg-4">

        <div class="well clearfix">

            <h4>{{name}}</h4>

            <!-- Using CFS package in a global helper to retrieve the item image -->
            {{#with getPhoto photo}}
                <a href="#">
                    <img src="{{url store='images_items'}}" alt="No photo" class="img-responsive img-thumbnail" />
                </a>
            {{/with}}

            <!-- Using a global helper to get the item category -->
            {{#with getCategory category}}
                <h5 class="col-md-8 col-lg-8"> <a href="#">{{name}}</a> </h5>
            {{/with}}

            <h4 class="col-md-4 col-lg-4 text-right"> {{price}} €</h4>

            <div>
                <div class="col-md-12 col-lg-12">
                    <!-- Using a global helper to get the item owner -->
                    {{#with getUser owner}}
                        {{#with profile}}
                            <a href="#" class="break-word">
                                {{ [first-name] }} {{ [last-name] }}
                            </a>
                        {{/with}} 
                    {{/with}}
                </div>
            </div>
        </div>
    </div>

</template>

这些是 ItemList 模板使用的代码:

var observer, container;

Template.ItemList.onRendered(function() {

    container = $('#container');

    //Load Isotope with Masonry
    container.imagesLoaded(function() {
        container.isotope({
            layoutMode: 'masonry',
            itemSelector: '.ms-item',
            transitionDuration: '0.1s'
        });

        container.isotope('layout');
    });

    //Using a MutationObserver to readapt the layout when a new item is added
    observer = new MutationObserver(function(mutations) {
        container.imagesLoaded(function() {
            container.isotope('reloadItems').isotope('layout').isotope();
        });
    });

    //Adding the MutationObserver to the items container
    observer.observe(container.get(0), {
        attributes: false, 
        childList: true, 
        characterData: false
    });

});

最后,这是模板的用法:

<template name="myTemplate">
    <div class="col-md-12 col-lg-12">
        {{> ItemsList}}
    </div>
</template>

我就是这样做的。希望这对某人有所帮助 ;)

编辑

我找到了一个更好的方法来完成这一切(我的意思是没有 MutationObserver)。相反,我使用的是 Meteor 提供的 _uihooks 对象:

Template.ItemList.onRendered(function() {

    var container = $('#container');

    //Load Isotope with Masonry
    container.imagesLoaded(function() {

        container.isotope({
            layoutMode: 'masonry',
            itemSelector: '.ms-item',
            transitionDuration: '0.1s'
        }).isotope('layout').isotope();
    });

    //Using uihooks instead of MutationObserver
    container[0]._uihooks = {

        insertElement: function(node, next) {

            $(node).insertBefore(next);

            container.imagesLoaded(function() {
                container.isotope('reloadItems').isotope('layout').isotope();
            });
        },

        removeElement: function(node, next) {

            $(node).remove();

            container.imagesLoaded(function() {
                container.isotope('reloadItems').isotope('layout').isotope();
            });
        }
    };
});