I'm creating an app with Meteor using alethes:pages package for the pagination and Bootstrap 3 for the styles.
In the main page I'm displaying multiple items (3 per row) using infinite scroll.
The problem comes when an item is higher than his neighbour items, making the next row to have a free space and floating one item to the right, instead of appearing below the higher one. Here you can see the problem:
I made an HTML template for the item to be used by the pagination package.
So, for the example shown in the image, the generated code will be this one:
<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">
Item 1
</h4>
<a href="#">
<img src="/cfs/files/images_publications/jvtQWo4KSziMXCryh/300x340.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
</a>
<h5 class="col-md-8 col-lg-8 break-word">
Category
</h5>
<h4 class="col-md-4 col-lg-4 text-right"> 1 €</h4>
<div>
<div class="col-md-12 col-lg-12">
UserName UserLastName
</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">
Item 2
</h4>
<a href="#">
<img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
</a>
<h5 class="col-md-8 col-lg-8 break-word">
Category
</h5>
<h4 class="col-md-4 col-lg-4 text-right"> 2 €</h4>
<div>
<div class="col-md-12 col-lg-12">
UserName UserLastName
</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">
Item 3
</h4>
<a href="#">
<img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
</a>
<h5 class="col-md-8 col-lg-8 break-word">
Category
</h5>
<h4 class="col-md-4 col-lg-4 text-right"> 3 €</h4>
<div>
<div class="col-md-12 col-lg-12">
UserName UserLastName
</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">
Item 4
</h4>
<a href="#">
<img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
</a>
<h5 class="col-md-8 col-lg-8 break-word">
Category
</h5>
<h4 class="col-md-4 col-lg-4 text-right"> 4 €</h4>
<div>
<div class="col-md-12 col-lg-12">
UserName UserLastName
</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">
Item 5
</h4>
<a href="#">
<img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
</a>
<h5 class="col-md-8 col-lg-8 break-word">
Category
</h5>
<h4 class="col-md-4 col-lg-4 text-right"> 5 €</h4>
<div>
<div class="col-md-12 col-lg-12">
UserName UserLastName
</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">
Item 6
</h4>
<a href="#">
<img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
</a>
<h5 class="col-md-8 col-lg-8 break-word">
Category
</h5>
<h4 class="col-md-4 col-lg-4 text-right"> 6 €</h4>
<div>
<div class="col-md-12 col-lg-12">
UserName UserLastName
</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">
Item 7
</h4>
<a href="#">
<img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
</a>
<h5 class="col-md-8 col-lg-8 break-word">
Category
</h5>
<h4 class="col-md-4 col-lg-4 text-right"> 7 €</h4>
<div>
<div class="col-md-12 col-lg-12">
UserName UserLastName
</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">
Item 8
</h4>
<a href="#">
<img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
</a>
<h5 class="col-md-8 col-lg-8 break-word">
Category
</h5>
<h4 class="col-md-4 col-lg-4 text-right"> 8 €</h4>
<div>
<div class="col-md-12 col-lg-12">
UserName UserLastName
</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">
Item 9
</h4>
<a href="#">
<img src="/cfs/files/images_publications/woTuL4hS6SkSYRSb3/300x300.png?token=eyJhdXRoVG9rZW4iOiJsQU55dkttNWNxR0twVjJDWmpad1kzMHhOYS1IMGhTNDdiV0t5Vjd4M1lDIn0%3D&store=images_publications" alt="NO VA" class="img-responsive img-thumbnail">
</a>
<h5 class="col-md-8 col-lg-8 break-word">
Category
</h5>
<h4 class="col-md-4 col-lg-4 text-right"> 9 €</h4>
<div>
<div class="col-md-12 col-lg-12">
UserName UserLastName
</div>
</div>
</div>
</div>
</div>
</div>
I could make the items to have the same hight but I want to have different image sizes and multiline text without leaving free space inside the item.
I want something like the items list shown in this web: http://es.wallapop.com/
But the problem with that list is that uses absolute positions in order to display an item below each other. I would like to avoid absolute positions since I think it wouldn't be so easy to integrate with the package mentioned before.
I don't know if something like this is possible in Bootstrap 3 without using absolute positions.
This has little to do with meteor or pagination I believe.
What you are looking for is to probably implement masonyjs with bootstrap. Layouts like these can get really interesting and tricky. I would definitely look into that combo.
Following the conversation in the comments:
After a lot of research and testing I finally got Masonry to work perfectly with the alethes:pages package. I know, in my last comment I said that I gave up on this, but after some time with my homemade infinite scroll I realized that it wasn't reacting to the mongodb changes, it was static. I didn't want to spend more time on that...
Before showing you the code that makes the magic you have to have some things in mind:
The best way to use Masonry is by using Isotope, at least for me that was the case. I recommend you to install this meteor package: isotope:isotope
You will also need the ImagesLoadead library: iamkevingreen:imagesloaded
The alethes:pages package uses the document.body.offsetHeight DOM property as the total page height, in order to load new items when scrolling. If you are using Bootstrap that property may not represent the total page height, so every scroll made can add new items no matter what you set in the infiniteTrigger option. The way to fix this is by adding a clearfix before closing the body:
<template name="MasterLayout">
...
{{> yield}}
<div class="clearfix"></div>
</template>
The items container used by Masonry must have padding: 0 (at least left and right) in order to be displayed correctly using Bootstrap.
Now, let's see the code.
This is the server code:
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
});
These are the templates used by the pagination object:
<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"> {{name}} </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>
These is the code used by the ItemList template:
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
});
});
And finally, this is the usage of the template:
<template name="myTemplate">
<div class="col-md-12 col-lg-12">
{{> ItemsList}}
</div>
</template>
That's how I made it. Hope this helps someone ;)
EDIT
I have found a better way to do all this (without a MutationObserver I mean). Instead, I'm using the _uihooks object provided by Meteor:
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();
});
}
};
});
Related
I've made bootstrap cards that appear on two different pages. One on the landing page which I want to increase the spacing and one on the books page which I want to increase the width of the cards. Here's the code that I've written and used in both pages. The only thing that I've changed is on the 6th line from '...col-lg-3' to '...col-lg-2'. If anyone can assist me in adding the spacing and increasing the with of the card, help me if you can. d-flex justify-content-evenly doesn't work when i use col-lg-3.
<section id="about" class="ts-block" >
<div id="cards_landscape_wrap-2">
<div class="container " style="width:70%">
<div class="row d-flex justify-content-around">
#foreach($products as $product)
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3">
<a href="{{route("products.show",$product->slug)}}">
<div class="card-flyer ">
<div class="text-box">
<div class="image-box">
<img src="{{asset($product->image)}}" alt="{{$product->title}}" class="img-fluid rounded mx-auto d-block" width="100%"/>
</div>
<div class="card-footer">
<i class="text-muted"><strike>Ksh.{{$product->old_price}}</strike></i>
<span class="text-primary font-weight-bold">Ksh.{{$product->price}}</span><br>
<span class="mybuttonoverlap btn btn-primary">View</span>
</div>
</div>
</div>
</a>
</div>
#endforeach
</div>
</div>
</div>
</section>
Try including d-flex justify-content-around to a direct parent containing the cards instead of
<div class="row d-flex justify-content-around">. And add margin to the card.
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 d-flex justify-content-around">
<a href="{{route("products.show",$product->slug)}}">
<div class="card-flyer m-2">
<div class="text-box">
<div class="image-box">
<img src="{{asset($product->image)}}" alt="{{$product->title}}" class="img-fluid rounded mx-auto d-block" width="100%"/>
</div>
<div class="card-footer">
<i class="text-muted"><strike>Ksh.{{$product->old_price}}</strike></i>
<span class="text-primary font-weight-bold">Ksh.{{$product->price}}</span><br>
<span class="mybuttonoverlap btn btn-primary">View</span>
</div>
</div>
</div>
</a>
</div
I have this template that is working fine.
But when I want to separate the single-course (or product) in a component, row-class not working fine and items are under each other...
This is my code:
<div class="col-lg-9">
<div class="row">
<app-single-course></app-single-course>
<app-single-course></app-single-course>
</div>
</div>
Update
this is the code without single component and its working fine if I copy it they appear side by side.
<div class="col-lg-9">
<div class="row">
<div class="col-lg-4 col-md-6">
<div class="single-course-inner style-two">
<div class="thumb">
<img src="assets/img/course/2.png" alt="img">
<div class="rating">4.9/5 <i class="fa fa-star"></i></div>
<i class="fa fa-bookmark-o"></i>
</div>
<div class="details">
<div class="meta">
<div class="row">
<div class="col-6">
<p>5,957 students</p>
</div>
<div class="col-6 text-right">
<p>01h 49m</p>
</div>
</div>
</div>
<h5>Motion Graphics: Create a Nice Typography Animation</h5>
<div class="price-inner">
<div class="row">
<div class="col-6">
<p>$33.99</p>
</div>
<div class="col-6 text-right">
<i class="fa fa-shopping-cart"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
I think you might talk about the bootstrap grid system.
Well first of all the col class comes inside the row class or else you'll always have item "under each other".
Here is the documentation with examples : https://getbootstrap.com/docs/4.5/layout/grid/
guys so I'm pulling in content from a JSON file to populate a grid of images. when the data loads it displays all the images in 1 column instead of in a grid. ideally, i would like a 4 wide image grid. All the CSS for this part of from default Bootstrap 4 values
HTML
<div id="UHD" ng-controller="Content-folders-4K">
<div id="UHD-frames" class="d-flex">
<div ng-repeat="friend in UHD" class="row">
<div id="img-frame" class="col-md-3 col-sm-6 col-xs-12">
<a href="/4k/{{friend.name}}.html">
<img alt="{{friend.name}}" src="assets/images/4k-thumbs/{{friend.name}}.jpg" class="img-fluid">
</a>
<p class="font-weight-bold text-center">{{friend.name}}</p>
</div>
</div>
</div>
</div>
Current result
Expected (simulated) result
I think You didn't wrap Your Grid with container and row class
Follow below example
<div class="container">
<div class="row">
<div class="col"> 1 of 2 </div>
<div class="col"> 2 of 2 </div>
</div>
</div>
**Wrap Your column div with container and row class **
You want to iterate the columns instead of the row...
<div id="UHD" ng-controller="Content-folders-4K">
<div id="UHD-frames" class="d-flex">
<div class="row">
<div class="col-md-3 col-sm-6 col-xs-12" ng-repeat="friend in UHD">
<a href="/4k/{{friend.name}}.html">
<img alt="{{friend.name}}" src="assets/images/4k-thumbs/{{friend.name}}.jpg" class="img-fluid">
</a>
<p class="font-weight-bold text-center">{{friend.name}}</p>
</div>
</div>
</div>
</div>
here's the code I used to get it to work.
<div id="UHD" ng-controller="Content-folders-4K" class="row">
<div ng-repeat="friend in UHD" class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
<a href="{{friend.link}}">
<div id="tiles" class="tiles">
<img src="thumbs/111/{{friend.name}}.png" alt="" />
</a>
<p class="text-center">{{friend.name}}</p>
</div>
</div>
</div>
This question already has answers here:
Bootstrap Rows and Columns - Do I need to use row?
(4 answers)
Bootstrap 4.0 Grid System Layout not working
(1 answer)
Closed 4 years ago.
I'm building a simple website with gallery. Below code, to my understanding, when the width of the website is of medium devices (768px and up to 992px) should result in showing two columns of photos. However, only one column shows on the screen. I cannot group images in rows since I need them to be responsive and adapt to the device screen' width. What could be the cause of such behaviour?
<div class="container-fluid">
<h1 class="text-center pb-4">Gallery</h1>
<div id="lightgallery" class="text-center no-gutter">
<a data-src="img/img-1.jpg">
<img class="img-fluid col-lg-3 col-md-6 col-sm-12" src="img/img-1.jpg">
</a>
<a data-src="img/img-2.jpg">
<img class="img-fluid col-lg-3 col-md-6 col-sm-10" src="img/img-2.jpg">
</a>
<a data-src="img/img-3.jpg">
<img class="img-fluid col-lg-3 col-md-6 col-sm-10" src="img/img-3.jpg">
</a>
<a data-src="">
<img class="img-fluid col-lg-3 col-md-6 col-sm-10" src="img/img-4.jpg">
</a>
<a data-src="">
<img class="img-fluid col-lg-3 col-md-6 col-sm-10" src="img/img-5.jpg">
</a>
<a data-src="">
<img class="img-fluid col-lg-3 col-md-6 col-sm-10" src="img/img-6.jpg">
</a>
</div>
</div>
When I set medium columns to col-md-5 they work, but considering bootstrap maxium amount of columns, which is 12, left me with this question.
Col should directly embed inside a row. I believe it should be solved if you change your code to:
<div class="container-fluid">
<h1 class="text-center pb-4">Gallery</h1>
<div id="lightgallery" class="text-center no-gutter row">
<a data-src="img/img-1.jpg" class="col-lg-3 col-md-6 col-sm-12">
<img class="img-fluid" src="img/img-1.jpg">
</a>
I managed to find a solution. Despite my thoughts of not using row, it was needed. I added div with class="row" and another div, one for each picture, with column classes. Below is fixed code:
<div class="container-fluid">
<h1 class="text-center pb-4">Galeria</h1>
<div id="lightgallery">
<div class="row">
<div class="col-lg-4 col-md-6 col-sm-10 mx-auto">
<a data-src="img/img-1.jpg">
<img class="img-fluid" src="img/img-1.jpg">
</a>
</div>
<div class="col-lg-4 col-md-6 col-sm-10 mx-auto">
<a data-src="img/img-2.jpg">
<img class="img-fluid" src="img/img-2.jpg">
</a>
</div>
<div class="col-lg-4 col-md-6 col-sm-10 mx-auto">
<a data-src="img/img-3.jpg">
<img class="img-fluid" src="img/img-3.jpg">
</a>
</div>
<div class="col-lg-4 col-md-6 col-sm-10 mx-auto">
<a data-src="img/img-4.jpg">
<img class="img-fluid" src="img/img-4.jpg">
</a>
</div>
<div class="col-lg-4 col-md-6 col-sm-10 mx-auto">
<a data-src="img/img-5.jpg">
<img class="img-fluid" src="img/img-5.jpg">
</a>
</div>
<div class="col-lg-4 col-md-6 col-sm-10 mx-auto">
<a data-src="img/img-6.jpg">
<img class="img-fluid" src="img/img-6.jpg">
</a>
</div>
</div>
</div>
</div>
I am facing an issue while trying to create a page contain N cards(single or multiple)
while in multiple all cards are as I want them to be, when it is a single card it shrinks and is not presented as I want it to be :
and a single card looks like this:
I am trying to understand what I am doing wrong.
this is the card HTML :
<div class="card text-white bg-danger">
<div class="card-header">
<div class="row">
<div class="col col-xs-3">
<i class="fa fa-euro">{{expenseItem.amount}}</i>
</div>
<div class="col col-xs-9 text-right">
<div class="d-block huge">{{count}}</div>
<div class="d-block">{{label}}</div>
<div class="card-body">
<div class="row">
</div>
</div>
</div>
</div>
</div>
<div class="card-footer">
<span class="float-left">Details </span>
<a href="javascript:void(0)" class="float-left card-inverse">
<span ><i class="fa fa-arrow-circle-left"></i></span>
</a>
</div>
</div>
and it is located inside acomponent that should be a list :
<div class="container">
<div class="row">
<hr>
</div>
<div class="row">
<div class="page-header">
<h1 >Comp header</h1>
<h4> total epenses per month {{expenses.total}}</h4>
<app-pagination [paginationSize]="limit" [total]="total" (requierdPage)="getPage($event)"></app-pagination>
</div>
</div>
<hr>
<!--<div class="row" >
<div class="col-xs-3 col-lg-4" *ngFor="let expense of expensesList" >
<app-expnses-item [expenseItem]="expense"></app-expnses-item>
</div>
</div>-->
<!--<div class="container">
<div class="row">
<div class="card-deck" *ngFor="let expense of expensesList">
<app-expnses-item [expenseItem]="expense"></app-expnses-item>
<!– <div class="card">
<div class="card-block">
<h4 class="card-title">Card title</h4>
<p class="card-text">This is a wider
card with supporting text below as a natural lead-in to additional content.
This content is a little bit longer.This is a wider
card with supporting text below as a natural lead-in to additional content.
This content is a little bit longer.</p>
<p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
</div>
</div>–>
</div>
</div>
</div>-->
<div class="row" >
<div class="col-sm-6 col-xs-6 col-xl-6 col-md-6 col-lg-6" *ngFor="let expense of expensesList">
<app-expnses-item [expenseItem]="expense"></app-expnses-item>
</div>
</div>
<div class="row add">
<div class="col-xs-1 offset-xs-1 align-self-sm-end">
<i class="fa fa-plus-square-o fa-4x" aria-hidden="true" (click)="Uopen()"></i>
</div>
<app-add-expense (onFormSubmitted)="onDataSubmit($event)"></app-add-expense>
</div>
</div>
what am I missing here?
The .card-deck should be placed directly in container instead of row. Remove the .row as it's flexbox, and should be used only to contain grid columns (col-*) which you're not using for the .card-deck.
<div class="container">
<div class="card-deck">
<div class="card text-white bg-danger">
</div>
<div class="card text-white bg-danger">
</div>
(repeat 1..n cards)
</div>
</div>
https://www.codeply.com/go/Gmch54KdgL