Bootstrap 3 fluid grid layout issues? - css

Im using Bootstrap 3 to layout my website with fluid grid, but the boxes in the grid don't line up in a row.
You can see:
When a box is taller than another, the grid is not left aligned.
How can I fix it with some hack ? Thank for help !
Note : the height of box is auto wrap contents.
My html code
<div class="row">
<?php foreach($contens as $content){?>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3">
<div class="contents-block">
<div class="image"><img href="<?php echo $content['image'];?>" />
</div>
................ some code .............
</div>
</div>
<?php } ?>
</div>

I'm not sure exactly what you're trying to accomplish, but the issue is caused because the content of the columns varies in height. There are 3 overall approaches to fix grid alignment / height issues..
1. A CSS only approach (using CSS3 column width) like this..
http://bootply.com/85737
2. A 'clearfix' approach like this (requires iteration every x columns). This is the approach recommended by Bootstrap known as "responsive resets"..
http://bootply.com/89910 (there is also a CSS-only variation to this approach)
3. Finally you may want to use the Isotope/Masonry plugin. Here is a working example that uses Isotope + Bootstrap..
http://bootply.com/61482
Update 2017
Another option is to make the columns the same height (using flexbox):
Since the issue is caused by the difference in height, you can make columns equal height across each row. Flexbox is the best way to do this, and is natively supported in Bootstrap 4.
.row.display-flex {
display: flex;
flex-wrap: wrap;
}
.row.display-flex > [class*='col-'] {
display: flex;
flex-direction: column;
}
Flexbox equal height Demo
Bootstrap 4 uses flexbox so columns in each row are the same height by default (without the extra CSS).
More on Bootstrap Variable Height Columns

Enforce a height for each <div> column.
I would give your columns a class name:
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 outer">
...
</div>
And then do something like this:
.outer {
height: 200px /* Or whatever the height really is */
}
Your columns are being laid out weird because of the varying heights of the boxes. Enforcing a height of the container element will fix that.
The best part is, this doesn't require you to add random <div>'s that don't have anything to do with the content.
EDIT:
You could also enforce the height only when you're using the 'sm' breakpoints and above.
This would ensure that everything lines up when columns are being used, and that there won't be large gaps in between each one when they're full width (i.e. col-xs-12).
#media (min-width: 768px) {
.outer {
height: 200px /* Or whatever */
}
}

I had a similar problem. I fixed with this script pretty quickly and pain free:
<script>
$.getScript('//cdn.jsdelivr.net/isotope/1.5.25/jquery.isotope.min.js',function(){
$('#container').isotope({
itemSelector : '.items',
layoutMode : 'fitRows'
});
});
</script>
in your case, you will need to add a container ID e.g. '#container' and add the class to each item e.g. '.item'

Here's a super simple jQuery solution to get all elements still aligned.
I solved this issue by getting the column with highest height and setting this height to every other columns. Try the snippet below.
setTimeout(function(){
var maxHeight = 0;
$('.item').each(function() {if ($(this).height() > maxHeight){maxHeight = $(this).height()}});
$('.item').each(function() {$(this).height(maxHeight)});
}, 1000);
.item {
border: 1px solid black;
}
.big {
height:50px;
background-color:fuchsia;
}
.normal {
height:40px;
background-color:aqua;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<div class="col-xs-4 item big">I am big</div>
<div class="col-xs-4 item normal">I am normal</div>
<div class="col-xs-4 item normal">I am normal</div>
<div class="col-xs-4 item normal">I am normal</div>
<div class="col-xs-4 item normal">I am normal</div>
<div class="col-xs-4 item normal">I am normal</div>
</div>

I think you need to use clearfix. just put the classclearfix on your parent element (in your case, row, I think) and put this in your css:
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
.clearfix { display: inline-block; }
/* start commented backslash hack \*/
* html .clearfix { height: 1%; }
.clearfix { display: block; }
/* close commented backslash hack */

I agree with Skelly in that a masonry plugin is probably the way to go, but for a quick easy fix you can just make a new row every time you want something left aligned - its a quick and dirty hack and can have some issues on smaller viewports.

My solution:
I worked with the visible- classes of bootstrap 3
<div class="row">
<?php
$indexLg = 1;
$indexSm = 1;
foreach($contens as $content) {?>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3">
<div class="contents-block">
<div class="image"><img href="<?php echo $content['image'];?>" />
</div>
</div>
</div>
<?php
if($indexLg%4 == 0) {
$indexLg = 1;
?>
<div class="clearfix visible-lg visible-md"></div>
<?php
}
if($indexSm%2 == 0) {
$indexSm = 1;
?>
<div class="clearfix visible-sm"></div>
<?php
}
?>
<div class="clearfix visible-xs"></div>
<?php
}
} ?>

Related

How to create a clean four-column, left-aligned, layout using justify-content: space-between

I am trying to create a display blog post component with Flexbox that primarily uses justify-content: space-between. In a 4-column layout, it looks great when there are 4 posts to fill the row. The issue is when there are not 4 posts, but 2 or 3. At this point, the posts get spread out and it just looks sloppy. I want to use flexbox without any JavaScript, and I want to be able to have the layout be fully responsive. So at other breakpoints the column layout will drop to 3, 2, or even 1.
One of the things that I found that works great is adding an :after pseudo element to the wrapper with a set width that will fill in the empty space. The problem with that is it is not dynamic enough and will not work properly if I have a different number of post then the one I planned for.
For example: If I have 2 posts, each at 25% width, and then a pseudo element at 50% width, everything looks great. Once I have 3 posts it is not so great because the 50% pseudo element now needs to be 25%. Finally, if there is 4 I wouldn't need a pseudo element at all.
I am trying to work with using some of the SASS selectors, but for some reason when I try to target the parent with my :after element, it targets something else way up the DOM tree.
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.entry:nth-child( 2 ):last-of-type {
:after & {
content: "";
flex-grow: 0;
width: 50%;
}
}
.entry:nth-child( 3 ):last-of-type {
:after & {
content: "";
flex-grow: 0;
width: 50%;
}
}
}
At this point I expected the :after element to target the parent class "content" but it doesn't. I also didn't think about how I would adjust it to be more dynamic and be able to handle multiple rows. I guess I could just do the math and make it something like .entry:nth-child( 3n+4 ):last-of-type {}, but I haven't even gotten there yet.
CSS-Grid would seem to be a better fit than flexbox here.
.content {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 1em;
margin-bottom: 1em;
}
.red .entry {
background: red;
}
.blue .entry {
background: blue;
}
.green .entry {
background: green;
}
.entry {
height: 50px;
}
<div class="content red">
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
</div>
<div class="content blue">
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
</div>
<div class="content green">
<div class="entry"></div>
<div class="entry"></div>
</div>
Here is a grid solution in Code Pen
For this to work in your query template it would look like this:
<div class="post-grid>
//while loop here
<div class="each-post">
<img src="<?php get_the_post_thumbnail() ?>">
<h2><?php get_the_title() ?></h2>
<p><?php get_the_excerpt() ?></p>
</div>
// end loop here
</div>

Bootstrap 4 text-center in flexbox not working

I am trying to split my webpage into two vertical columns which can be clicked on to take you to the right pages. I've gotten this far.
HTML
<!-- Choices -->
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-xs-12 vertical-center webd">
<h1 class="text-muted text-center">Web Design</h1>
</div>
<div class="col-md-6 col-xs-12 vertical-center circ">
<h1 class="text-muted text-center">Circus</h1>
</div>
</div>
</div>
CSS
.vertical-center {
min-height: 100%;
min-height: 100vh;
display: flex;
align-items: center;
}
.webd {
background-image: url('webd.jpg');
}
.circ {
background-image: url(circ.JPG);
}
My issue is, no matter where I put the text-center class. My <h1>s stay left aligned on the page. Can anybody help?
It is because you have added display flex to the parent container. This means the children are not full width anymore.
If you add the following style, it will fix your error:
.vertical-center > .text-center
{
flex-grow: 1;
}
Example bootply
If you don't want to grow the children, you can just add the following to your vertical center: justify-content: center;
Example bootply 2

Make Bootstrap 3 columns have equal height, visible gutters, and background color

I want to make my Bootstrap 3 columns to be:
of the same height (edit: equal to the highest column, which could change)
have visible gutters separating them
have a background color that matches their equal height
So far I was able to either make them of equal height (with no visible gutter) or give them a gutter and a background. I've been fiddling with this for the past 2 hours to no avail. Naturally, I've read through everything I could find but couldn't solve this riddle. Would highly appreciate your help!
Here is code and codepen with my problem.
HTML
<div class="container">
<div class="flex-row row">
<div class="col-sm-5">
<div class="inner">
<p>Some text and probably an image over here. Not as much as on the other side, but still..</p>
</div>
</div>
<div class="col-sm-7">
<div class="inner">
<p>More content on this side. How can I make the two columns have the same height and have a gutter in between?</p>
<img src="...">
</div>
</div>
</div>
</div>
CSS
div[class^='col-sm-'],
div[class*=' col-sm-'] {
background-color: green;
}
#media only screen and (min-width : 768px) {
.flex-row.row {
display: flex;
flex-wrap: wrap;
}
.flex-row.row > [class*='col-'] {
display: flex;
flex-direction: column;
}
.flex-row.row:after,
.flex-row.row:before {
display: flex;
}
}
http://codepen.io/anon/pen/QEozAj
I don't want columns to be of fixed height because contents will change.
And ideally I would like to have as little extra divs as possible. :)
Edit: Column heights now look okay, thanks to a helpful reply. Still need the visible gutter.

Bootstrap align Columns of different height

I would like to be able to align an unknown number of columns with an unknown height. Since I do not know how many columns there will be it is not ideal for me to use multiple rows to split up the columns. I can almost achieve the outcome I want by using list items.
The one thing I don't like about using list items is that once the page hits the resize point I am left with the extra space on the right hand side. The top set is using list items and the bottom set is using bootstrap's col's. The problem with the bottom set is when the col's break they don't align to the furthest left position.
Is there a way to achieve this using bootstrap?
<div class="container-fluid">
<div class="row">
<ul>
<li class="list-item" style="height:200px;"></li>
<li class="list-item" style="height:120px;"></li>
<li class="list-item" style="height:100px;"></li>
</ul>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-3">
<div class="box" style="height:200px"></div>
</div>
<div class="col-xs-12 col-sm-6 col-md-3">
<div class="box" style="height:120px"></div>
</div>
<div class="col-xs-12 col-sm-6 col-md-3">
<div class="box" style="height:100px"></div>
</div>
<div class="col-xs-12 col-sm-6 col-md-3">
<div class="box"></div>
</div>
</div>
</div>
jsFiddle
Try this :
.row {
display: flex;
flex-wrap: wrap;
}
Another way to handle it, and still maintain Bootstrap's responsive columns is to use CSS to force a clear:left every x columns. For example, when you have 4 columns in a row:
.row > .col-md-3:nth-child(4n+1) {
clear: left;
}
http://codeply.com/go/OHg5vB0Xg3
You really don't need bootstrap to handle this. Here's one potential solution using inline-block. I imagine it's compatible with bootstrap.
.box {
margin: 15px;
width: 80px;
background-color: grey;
display: inline-block;
vertical-align: top;
}
<div>
<div class="box" style="height: 120px;"></div>
<div class="box" style="height: 20px;"></div>
<div class="box" style="height: 40px;"></div>
<div class="box" style="height: 60px;"></div>
<div class="box" style="height: 80px;"></div>
</div>
<div>
<div class="box" style="height: 20px;"></div>
<div class="box" style="height: 60px;"></div>
<div class="box" style="height: 80px;"></div>
</div>
Yes! There is a way. And it's a css-only solution. Try this:
.col-xs-6:nth-of-type(2n+3),
.col-xs-4:nth-of-type(3n+4),
.col-xs-3:nth-of-type(4n+5),
.col-xs-2:nth-of-type(6n+7),
.col-xs-1:nth-of-type(12n+13)
{
clear: both;
}
#media (min-width: 768) {
[class*="col-xs"][class*="col-sm"],
[class*="col-xs"][class*="col-md"],
[class*="col-xs"][class*="col-lg"]
{
clear: none;
}
.col-sm-6:nth-of-type(2n+3),
.col-sm-4:nth-of-type(3n+4),
.col-sm-3:nth-of-type(4n+5),
.col-sm-2:nth-of-type(6n+7),
.col-sm-1:nth-of-type(12n+13)
{
clear: both;
}
}
#media (min-width: 992) {
[class*="col-sm"][class*="col-md"],
[class*="col-sm"][class*="col-lg"]
{
clear: none;
}
.col-md-6:nth-of-type(2n+3),
.col-md-4:nth-of-type(3n+4),
.col-md-3:nth-of-type(4n+5),
.col-md-2:nth-of-type(6n+7),
.col-md-1:nth-of-type(12n+13)
{
clear: both;
}
}
#media (min-width: 1200) {
[class*="col-md"][class*="col-lg"]
{
clear: none;
}
.col-lg-6:nth-of-type(2n+3),
.col-lg-4:nth-of-type(3n+4),
.col-lg-3:nth-of-type(4n+5),
.col-lg-2:nth-of-type(6n+7),
.col-lg-1:nth-of-type(12n+13) {
clear: both;
}
}
// use .col-nobreak class to deactivate this fix
.col-nobreak {
clear: none !important;
}
First of all we begin with the column type for the smallest resolution (< 768) (col-xs-*). If the row breaks for the several column widths, we set the css property clear to clear: both.
In the next step we reset for the first breakpoint the css property clear with clear: both for all columns, which has a column width for higher resolutions (all columns width additional col-sm-x,col-md-x,col-lg-x) and set the break of one column-row for the col-sm-* type.
And so on...
With the .col-nobreak class you can deactivate the css hack.
You have to fulfill these requirements:
The cols for the parent row container must have the same size
The cols for the parent row must have the same html tag type (div, secion)

Change the order of col-*-12 columns in Bootstrap using push/pull

I have two columns of the same size (.col-xs-12) and I would change their place when the screen size correspond to that of a mobile device. I would place them in the reverse order.
I have read that push and pull bootstrap directives help to accomplish that, but is it possible to change the place of two columns of the same size with the following classes?
div.col-xs-12.col-xs-push-12
p test1
div.col-xs-12.col-xs-pull-12
p test2
Actually you can not reorder the columns having .col-*-12 by push/pull helper classes. The sum of columns exceeds the default 12 columns which is defined by #grid-columns.
You could either change the order of columns in HTML and then use the ordering classes on larger screens as follows:
EXAMPLE HERE
<div class="row">
<div class="col-xs-12 col-sm-6 col-sm-push-6">
<p>test2</p>
</div>
<div class="col-xs-12 col-sm-6 col-sm-pull-6">
<p>test1</p>
</div>
</div>
Or use this fancy approach to reverse the ordering of the columns that are placed vertically under each other:
EXAMPLE HERE
#media (max-width: 767px) {
.row.reorder-xs {
transform: rotate(180deg);
direction: rtl; /* Fix the horizontal alignment */
}
.row.reorder-xs > [class*="col-"] {
transform: rotate(-180deg);
direction: ltr; /* Fix the horizontal alignment */
}
}
It's worth noting that CSS transforms are supported in IE9 as well; Just don't forget to add vendor prefixes.
In Bootstrap 4, you can change the order of full-width (12 unit) columns using the flexbox ordering classes.
Update 2017 - Bootstrap 4 alpha 6
In 3.x you could only push/pull columns left or right (horizontally). With the new flexbox ordering utils in 4.x, it's now possible to change the order of columns vertically...
<div class="container">
<div class="row">
<div class="col-12">1</div>
<div class="col-sm-12 flex-first flex-sm-unordered">2 (first on xs)</div>
</div>
</div>
http://www.codeply.com/go/7RUJORgxBK
Update Bootstrap 4 Beta
The alpha flex- ordering classed have changed to order- classes.
<div class="container">
<div class="row">
<div class="col-12 order-sm-1 order-2">1</div>
<div class="col-sm-12 order-1">2 (first on xs)</div>
</div>
</div>
https://www.codeply.com/go/VUjKsM3cUD
You can totally do it, see Bootstrap's Grid Column Ordering
But of course your example will have no effect since xs-12 is a full width column, so this will apply only to models where the sum of the columns is 12 (or if 16 or whatever if you customize your Bootstrap grid). See the Bootstrap example on that same page for illustrative purposes:
<div class="row">
<div class="col-md-9 col-md-push-3">.col-md-9 .col-md-push-3</div>
<div class="col-md-3 col-md-pull-9">.col-md-3 .col-md-pull-9</div>
</div>
If you need to reorder cols for a responsive case like
div.col-xs-12.col-sm-9 # this should be on the bottom for col-xs-12
p test1
div.col-xs-12.col-sm-3 # this should be on the top for col-xs-12
p test2
you could use a .pull-right class and reverse the column order.
div.col-xs-12.col-sm-3.pull-right
p test2
div.col-xs-12.col-sm-9
p test1
then they are in order for col-xs-12 and appear correctly for the other breakpoints.
In case anyone comes here with a similar issue like me, only finding push/pull doesn't fit your needs, because either col-xs-12 wont pull/push or using more than 2 columns makes it tougher to figure out the push/pull values here is my solution.
Below is the fancy solution by #hashemquolami
#media (max-width: 767px) {
.row.reorder-xs {
transform: rotate(180deg);
direction: rtl; /* Fix the horizontal alignment */
}
.row.reorder-xs > [class*="col-"] {
transform: rotate(-180deg);
direction: ltr; /* Fix the horizontal alignment */
}
}
Although this approach works fine, I have a different solution:
The bootstrap grid works by floating the columns left, this can easily be altered with css. Look at the markup below, as bonus col-md-offset-1 reversed to emulate 5 centered columns.
HTML
<div class="container">
<div class="row reverseOrder">
<div class="col-md-2 col-md-offset-1">A</div>
<div class="col-md-2">B</div>
<div class="col-md-2">c</div>
<div class="col-md-2">d</div>
<div class="col-md-2 ">e</div>
</div>
</div>
CSS
#media screen and ( min-width: 992px) {
.reverseOrder [class^="col-"] {
float: right;
}
.reverseOrder .col-md-offset-1 {
margin-right: 8.333333333333332%;
margin-left: 0px;
}
}
JSFIDDLE
I had same problem and solved it this way:
HTML
<div class="col-md-10 col-sm-10 col-xs-12 more-than" style="display: none;">
<p>test</p>
</div>
<div class="col-md-2 col-sm-2 col-xs-12">
<p>test</p>
</div>
<div class="col-md-10 col-sm-10 col-xs-12 less-than">
<p>test</p>
</div>
CSS
#media (max-width: 767px){
.less-than {
display: none;
}
.more-than {
display: block !important;
}
}

Resources