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
I have a grid with multiple columns. All columns are in one row and the number of columns may vary.
Since I needed some vertical space between columns, I added margin-bottom on columns.
However, I want equal space between wrapper and the columns so I need to remove margin-bottom on last few columns in the row.
See sample here: https://jsfiddle.net/aucovic/rhhyu6h2/6/
How would I dynamically remove bottom-margin on those last few columns?
<style>
.wrapper {
background:#000;
padding:10px;
}
.box {
background: #fff;
}
.mb {
margin-bottom:10px;
}
</style>
<div class="wrapper">
<div class="row">
<div class="col-md-4 col-xs-6 mb">
<div class="box">
Box 1
</div>
</div>
<div class="col-md-4 col-xs-6 mb">
<div class="box">
Box 2
</div>
</div>
<div class="col-md-4 col-xs-6 mb">
<div class="box">
Box 3
</div>
</div>
<div class="col-md-4 col-xs-6 mb">
<div class="box">
Box 4
</div>
</div>
<div class="col-md-4 col-xs-6 mb">
<div class="box">
Box 5
</div>
</div>
</div>
</div>
Well, in case you want the wrapper to have some padding, a super quick-fix would be to set the bottom padding to be equal (initial padding - margin bottom of columns). On your example it's just gonna be padding-bottom: 0 for your wrapper. This is definitely not an ultimate fix, but is super simple and works in described case.
Here's a fiddle: https://jsfiddle.net/kLr8sog6/
Assuming you don't change the number of columns, nth child selectors could help:
//mobile and tablet view
#media(max-width:992px) {
.mb:nth-last-child(-n+2) {
margin-bottom:0px;
}
}
//wider views
#media(min-width:993px) {
.mb:nth-last-child(-n+3) {
margin-bottom:0px;
}
}
EDIT: Updated your fiddled to show this in effect: https://jsfiddle.net/rhhyu6h2/8/
Again, only for this specific layout. For variable columns layouts, you have to solve in a wrapper or through JS.
EDIT2: from reading your other comments, you could use a wrapper adjustment class on selective rows: https://jsfiddle.net/rhhyu6h2/9/
This doesn't require any new HTML.
#Antonio, in order to remove the bottom-margin dynamically you gotta use jQuery/JavaScript. On appropriate event add the class which has margin-bottom:0px.
Example:
CSS Code:
.removeBottomPadding{
margin-bottom:0px !important;
}
JavaScript Code: [Ensure to add an id to the wrapper]
window.onload = function() {
document.getElementById('wrapper').className = 'removeBottomPadding';
};
OR
jQuery Code:
$(function() {
$('.wrapper').addClass('removeBottomPadding');
});
That's all.
Good luck & hope that helps.
I have been using bootstrap responsive 12 column grid layout for my website.
I have the layout like follows (stripped down version for example purpose)
<div class='container-fluid'>
<div class='row'>
<div class='col-md-1'>
Left side contents go here
</div>
<div class='col-md-11'>
Right side contents go here
</div>
</div>
</div>
What I need now, is that the left side column is wider than what I want. How can I make it fixed-length narrow and still use Bootstrap layout?
Any help is appreciated!
A clean solution would be customizing bootstrap to have more columns, like this answer:
How to use bootstrap with 16 or 24 columns
Other alternative is using nested rows, but that could end up with problems like unused space, so my suggestion is customizing bootstrap.
you can make a nested row within a column
For eg-
<div class="row">
<div class="col-md-1">
<div class="row">
<div class="col-md-offset-9 col-md-3"><!-- offset-9 leave space in left and start in last three of column --></div>
</div>
</div>
<div class="col-md-11"></div>
</div>
The issue you're having is an issue with how grid systems work. What they're designed to do is describe a fixed set of column widths: the content of those columns should expand to fill them. What you want is the inverse of this: you want the content to define the width.
You've effectively got three good options, and in order from least -> best in terms of getting what you want with the simplest markup:
Live with it (or have more columns as suggested, say 24).
Put the two columns of content in a block[1], apply display:table; width: 100%;. Make the two child items display:table-cell, use white-space:nowrap on the left-hand one and make the right-hand one width: 99%.
Put the two columns of content in a block[1], apply display:flex, and apply flex:1 to the right-hand child item.
Flex is the best solution, but needs IE10+ if that's an issue.
.container {
max-width: 400px;
margin: 0 auto;
}
[class^="row-"] {
margin: 10px 0;
}
.row-1 {
display: table;
width: 100%;
}
[class^="col-1-"] {
display: table-cell;
}
.col-1-left {
white-space: nowrap;
}
.col-1-right {
width: 99%;
}
.row-2 {
display: flex;
}
.col-2-right {
flex: 1;
}
<div class='container'>
<div class='row-1'>
<div class='col-1-left'>Some content</div>
<div class='col-1-right'>Some content</div>
</div>
<div class='row-2'>
<div class='col-2-left'>Some content</div>
<div class='col-2-right'>Some content</div>
</div>
</div>
I am creating a responsive template using Bootstrap. I have multiple items located in a row, so that depending on a resolution there can be different amount of items in one row and a different amount of rows accordingly.
<div class="row">
<div class="col-xs-6 col-sm-4 col-md-3">
<div class="item"> ... </div>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<div class="item"> ... </div>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<div class="item"> ... </div>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<div class="item"> ... </div>
</div>
...
</div> <!-- / .row -->
Every item has a bottom margin, so that they don't stick together vertically:
.item {
margin-bottom: 20px;
}
Is there any way to set the bottom margin to "0" for all the items of the last row? (taken that we don't know which items will be in that last row on different resolutions).
PS: Don't get confused with the .row container. This doesn't mean that the divs inside are a single row. This is just a wrapper for the .col- containers.
JSFiddle: http://jsfiddle.net/m668fska/
Add a negative margin-bottom to the row - that way all your items (including the last row) will push down, the row will pull it back.
Use media queries that match bootstrap's, so something like
/* Large desktop */
#media (min-width: 768px) {
div.row>div.col-xs-6.col-sm-4.col-md-3:nth-last-child(-n+4)>div.item{
margin-bottom:0;
}
}
Then ditto for the following, except using nth-last-child(-n+3) and nth-last-child(-n+2) instead:
/* Landscape phone to portrait tablet */
#media (max-width: 767px) { ... }
/* Landscape phones and down */
#media (max-width: 480px) { ... }
Technically, since you are trying to replicate a table you just need to add a style to the row;
.row {
margin-bottom:20px;
}
then overwrite the final row of the table;
.table:last-child {
margin-bottom:0px;
}
each .row, except the last one, will have some margin and only at the bottom.
As far as I know there is no pure CSS solution …
… so here's my take on a JavaScript solution: compare each item's offset top with the last item's offset top and distribute classnames accordingly.
// tries to adjust margin-bottom of last-row elements.
function manage_last_row_items(){
$('.last_row_management').each(function(){
var
$context = $(this),
item_selector = $context.data('item_selector'),
$last_item = $context.find(item_selector +':last-of-type').addClass('last_row_item'),
final_top = $last_item.offset() ? $last_item.offset().top : 0
;
$context.find(item_selector)
.not($last_item)
.removeClass('last_row_item')
.filter(function(){
var
o = $(this).offset(),
decision = false
;
if (o) {
decision = o.top === final_top;
}
return decision;
})
.addClass('last_row_item')
;
}); // end of ( each )
}
$(document).ready(function(){
manage_last_row_items();
$(window).resize(manage_last_row_items);
});
Assuming this DOM:
<ul class="last_row_management" data-item_selector="li">
…
</ul>
<form class="last_row_management" data-item_selector="fieldset">
…
</form>
Fiddle
(At this point, one could actually also take care of the last-column items …) (¬_¬ )
I'll start off by stating that I know this question has been asked a lot, but none of the answers I saw seemed to work for me.
Basically, I have some divs inside of a larger div. They'll have dynamic text, so I don't know how many lines each will be. The problem is that I can't seem to get the divs to size themselves to the parent's height. I want the column divs to take up the entire height of the row div (basically, I want that blue part to fill all the space between the bars).
HTML:
<div class="container">
<div class="row divOne">
<div class="col-xs-3 divTwo">Some Text</div>
<div class="col-xs-3">
Some text that could wrap to multiple lines
</div>
</div>
<div class="row divOne">
<div class="col-xs-3 divTwo">Different Text</div>
<div class="col-xs-3 divThree">
With some more text
</div>
</div>
</div>
CSS:
.divOne
{
border-top:10px solid black;
}
.divTwo
{
background-color: #32649b;
height:100%;
color:white;
}
jsfiddle:
Now, what I've learned from other versions of this question are that
float:left might be screwing it up
height:100% doesn't work if the parent's height is defined
position:relative might help on the parent
The problem with the float is that I'm using bootstrap, and that's where the float is coming from, so I don't really want to mess with that.
I can't really define parent height, because it'll be dynamic based on the children.
I also tried messing around with position:relative on the parent and absolute on the child, but that seemed to get really screwy. I'm also guessing this won't work because I'm using bootstrap. It's possible that I'm just missing something, though. I'll admit to not being the greatest with CSS.
I don't know if I'm having these issues because I'm using bootstrap, or because I'm just being an idiot right now.
Something else that seems to be throwing a wrench into things: These columns will be laid out differently on smaller screens vs. larger ones. I actually want something along the lines of col-xs-12 col-md-3 for these.
The short answer is that you can't really achieve this within the constraints of the bootstrap framework. There are plenty of articles that explain why div elements can't stretch to the height of their container, and how to get around this problem. One of the solutions I'm most fond of is Faux Columns.
But, let's get a little more creative then that.
I came up with something that might work for your scenario, but requires a bit of change to your markup. Here's a solution that wraps the bootstrap grid with display: table.
http://jsfiddle.net/Wexcode/13Lfqmjo/
HTML:
<div class="table-container">
<div class="table-row divOne">
<div class="col-xs-3 divTwo">Some Text</div>
<div class="col-xs-3">
Some text that could wrap to multiple lines
</div>
<div class="col-xs-6"></div>
</div>
</div>
CSS:
.table-container {
margin: 0 -15px;
}
.table-row {
display: table;
width: 100%;
}
.table-row [class^="col"] {
display: table-cell;
padding: 0 15px;
float: none;
}
Note that for this solution to work, you must include enough col elements to stretch it all 12 columns (see that I added an empty .col-xs-6 div).
You can add
display:flex;
to divOne , and will act like you wanted.
in bootstrap 4 'row' class applies this on div, but in ealier versions you need to add manually if you expect such behavior.
Give .divOne a display: flex and remove the height: 100% from .divTwo:
.divOne
{
border-top:10px solid black;
display: flex;
}
.divTwo
{
background-color: #32649b;
/*height:100%;*/
color:white;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row divOne">
<div class="col-xs-3 divTwo">Some Text</div>
<div class="col-xs-3">
Some text that could wrap to multiple lines
</div>
</div>
<div class="row divOne">
<div class="col-xs-3 divTwo">Different Text</div>
<div class="col-xs-3 divThree">
With some more text
</div>
</div>
</div>
I am building a Bootstrap 3 grid that will become a portfolio page eventually. In the following bootply, in the first example, you can see it works perfectly stacking from 6 to 4 to 3 in my bootply
However in the second example, on the same bootply, there is an item where the tile for the item is longer and it causes a gap in the grid when it stacks.
What is the best bootstrap friendly ,solution to this? Any help much appreciated.
There are a couple of ways to handle this:
Give all of the elements in your portfolio a set height.
Use something like masonry to dynamically "fit" the elements into the available space.
Use the responsive classes and clearfix as described in the doc under the heading Responsive column resets, in the Grid secion.
Use jQuery to adjust the column heights dynamically.
If your content is dynamically generated so that you don't know which elements will have longer content, and you have different layouts set for different breakpoints, the responsive classes approach can be a bear to adapt. I use a little trick. After each element in the grid, I add a div that I can apply a mini clearfix to using media queries. It's extra markup, but it solves the problem nicely and allows me to have readable and maintainable markup while avoiding the use of javascript to adjust the layout. Here's an example using your markup:
Updated Bootply
<div class="row portfolio"> <!--Add a class so you can target with nth-child-->
<div class="col-lg-2 col-sm-3 col-xs-4">
<div class="panel panel-default">
<div class="panel-body">
<a href="#">
<img src="http://placehold.it/200x200" class="img-thumbnail img-responsive">
</a>
</div>
<div class="panel-footer">
This is text
</div>
</div>
</div>
<div class="clear"></div> <!--Here's the added div after every element-->
....
</div> <!--/.portfolio.row-->
CSS:
#media (max-width: 767px) {
.portfolio>.clear:nth-child(6n)::before {
content: '';
display: table;
clear: both;
}
}
#media (min-width: 768px) and (max-width: 1199px) {
.portfolio>.clear:nth-child(8n)::before {
content: '';
display: table;
clear: both;
}
}
#media (min-width: 1200px) {
.portfolio>.clear:nth-child(12n)::before {
content: '';
display: table;
clear: both;
}
}
If you prefer the jQuery route (again, this assumes that you've added a class "portfolio" to the row that contains your portfolio elements for easier targeting):
var row=$('.portfolio');
$.each(row, function() {
var maxh=0;
$.each($(this).find('div[class^="col-"]'), function() {
if($(this).height() > maxh)
maxh=$(this).height();
});
$.each($(this).find('div[class^="col-"]'), function() {
$(this).height(maxh);
});
});
A Bootstrap "only" approach is to use Bootstrap's .clearfix. You have to iterate this every x number of columns, so in your case a clearfix div would be placed after the 6th col-lg-2. This will work for lg screen widths..
http://www.bootply.com/SV0kI3TSN3
However since you're using multiple responsive breakpoints, you'd need to place a clearfix where the md and xs colums wrap too. This will prevent the gap at all screen widths.
http://www.bootply.com/3TsF0arPRS
Update 2017
1 - As explained above, the 'clearfix' approach (recommended by Bootstrap) like this (requires iteration every x columns). This will force a wrap every 3 columns
<div class="row">
<div class="col-md-4">Content</div>
<div class="col-md-4">Content</div>
<div class="col-md-4">Content</div>
<div class="clearfix"></div>
<div class="col-md-4">Content</div>
<div class="col-md-4">Content</div>
<div class="col-md-4">Content</div>
<div class="clearfix"></div>
<div class="col-md-4">Content</div>
<div class="col-md-4">Content</div>
<div class="col-md-4">Content</div>
</div>
Clearfix Demo (single tier)
Clearfix Demo (responsive tiers)
There is also a CSS-only variation of the 'clearfix' (unsupported).
http://www.codeply.com/go/lUbs1JgXUd
2 - 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
3 - CSS3 columns approach (Masonry-like CSS solution)..
This is not native to Bootstrap 3, but another approach using CSS multi-columns. One downside to this approach is the column order is top-to-bottom instead of left-to-right.
CSS3 columns Demo
4 - JavaScript/jQuery approach
Finally, you may want to use a plugin such as Isotope/Masonry:
Bootstrap Masonry Demo
More on Bootstrap Variable Height Columns
I had the same problem with two panels side-by-side in a row.
I did not find any CSS hack for this, so I gave the two panels a same-height class and I use this JS code.
boxes = $(".same-height");
maxHeight = Math.max.apply(Math, boxes.map(function () {
return $(this).height()
}).get());
boxes.height(maxHeight);
Here is a BootPly link that use the code above: http://www.bootply.com/622XyQ0oH5
Of course, you have to adapt your CSS rules I you want to avoid blank spaces.