Bootstrap align Columns of different height - css

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)

Related

Adding a class "collapse" to flex grid creates uneven spacing

So, I am creating a grid system based on flexbox and everything is going quite swimmingly. The basics of my grid are:
<div class="row">
<div class="column"><p>Column</p></div>
<div class="column"><p>Column</p></div>
<div class="column"><p>Column</p></div>
</div>
And in my css:
.row {
margin: 10px 0;
display: flex;
flex-wrap: wrap;
}
.column {
padding: 10px;
flex: 1 1 0%;
}
Essentially, this makes the columns quite fluid, and they shrink/grow to fill all available space. This is great for me as I need to use this throughout various projects where I can't quite customize the grid for every single one. However, I have run into a small "issue". I was going to create a class called ".collapse" so I could collapse the left/right padding to have some columns fit right next together (for example: If I wanted a div with a background color (by adding a color class to the column=> .column .green) flush to an image in the next column). However, the spacing is all out of wack compared to row/columns above it.
<div class="row">
<div class="column purple collapse"><p>Column</p></div>
<div class="column red collapse"><p>Column</p></div>
<div class="column purple collapse"><p>Column</p></div>
<div class="column red collapse"><p>Column</p></div>
</div>
example screenshot here
As you can see in my little example mockup, they do kinda line up, but the right and left margins have "decreased". Is there any smart way around this? I tried adding "left/right margins" to the first-of-type and last-of-type, but this just gets a bit hacky as then anything added in between start having odd alignment issues.
For this kind of grid system, you usually would discourage using structural styling on the grid cells directly, and it lets you do something like this:
.row {
display: flex;
flex-flow: row wrap;
list-style: none;
padding: 0;
margin-left: -10px;
}
.column {
flex: 1 0 0;
padding-left: 10px;
}
.collapse { margin-left: 0; }
.collapse > .column { padding-left: 0; }
.red,
.purple {
padding: 10px;
margin-bottom: 10px;
}
.red { background-color: red; }
.purple { background-color: purple; }
<div class="row">
<div class="column">
<div class="purple">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="red">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="purple">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="red">
<p>Column</p>
</div>
</div>
</div>
<div class="row collapse">
<div class="column">
<div class="purple">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="red">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="purple">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="red">
<p>Column</p>
</div>
</div>
</div>
This approach uses no margins on the outer ends, which I find way more convenient.
It's worth noting that this kind os system is not all that useful anymore, with the advent of CSS Grid Layout, but there you have it.
On a side note, 0 is always 0, and it never needs a unit.

Horizontally centered Bootstrap columns

JSFIDDLE
I have a case where I want my bootstrap columns to horizontally center themselves.
To achieve this, I have used the following rules
CSS:
div[class^=col-] {
float: none;/* Overwrites float left */
display: inline-block;
vertical-align: top;
width: 25%;
}
Then If 4 columns are there they should come in a line. And if there are 3 columns then they should be centered.
HTML:
<!-- The fourth column falls down -->
<div class='row text-center'>
<div class="col-xs-3 col-1">Hi</div>
<div class="col-xs-3 col-2">Hi</div>
<div class="col-xs-3 col-2">Hi</div>
<div class="col-xs-3 col-2">Hi</div>
</div>
<!-- Works Fine and centers the columns -->
<div class='row text-center'>
<div class="col-xs-3 col-1">Hi</div>
<div class="col-xs-3 col-2">Hi</div>
<div class="col-xs-3 col-2">Hi</div>
</div>
It works fine if I have just 1,2 or 3 columns but when I get 4 columns, one of the columns falls down to a new line. To solve this issue, I have tried reducing the width to say 24.7%. But again this does not work in all screens. So I have to keep changing the width.
I would love to know why width 25% is not taking the 25% width and falling down. And how to solve this issue and keep them always in the center.
JSFIDDLE
You should create a special class (ie: row-centered) for this case, and not override the Bootstrap grid.
.row-centered > div {
display: inline-block;
float: none;
}
http://www.codeply.com/go/EXmotvfGtG
Please remove:
div[class^=col-] {
float: none;/* Overwrites float left */
display: inline-block;
vertical-align: top;
width: 25%;
}
and you can add to the .row class:
.row {
display: flex;
justify-content: center;
}
If you're using bootstrap v4 there are added flexbox classes, which you can use:
https://v4-alpha.getbootstrap.com/utilities/flexbox/
Give display: flex to the row. Using this method will work in all screens.
Fiddle
div[class^=col-] {
float: none;
display: inline-block;
vertical-align: top;
width: 25%;
}
body {
color: white;
}
.row {
margin-bottom: 50px;
display: flex;
}
.col-1 {
background: red;
}
.col-2 {
background: blue;
}
<!-- The fourth column falls down -->
<div class='row row-1 text-center'>
<div class="col-xs-3 col-1">Hi</div>
<div class="col-xs-3 col-2">Hi</div>
<div class="col-xs-3 col-2">Hi</div>
<div class="col-xs-3 col-2">Hi</div>
</div>
<!-- Works Fine and centers the columns -->
<div class='row text-center'>
<div class="col-xs-3 col-1">Hi</div>
<div class="col-xs-3 col-2">Hi</div>
<div class="col-xs-3 col-2">Hi</div>
</div>
<!-- Post Info -->
<div style='position:fixed;bottom:0;left:0;
background:lightgray;width:100%;'>
About this SO Question: <a href='http://stackoverflow.com/q/23502342/1366033'>Bootstrap 3 grid, does it *really* matter how many columns are in a row?</a><br/>
Fork This Skeleton Here <a href='http://jsfiddle.net/KyleMit/kcpma/'>Bootrsap 3.0 Skeleton</a><br/>
<div>

How can I separate areas with floats from each other?

I'm struggling with Bootstrap rows and columns in a SharePoint web site. The problem is that I can't and don't want to change the styling that originates from SharePoint, but still be able to use the Bootstrap grid in a part of the page.
I've tried to illustrate the problem without Bootstrap and SharePoint. Here's the JSFiddle:
https://jsfiddle.net/knLjyhe4/
Below is a complete illustration of my example. The problem is that once I use a row to separate element B from C, D and E, the height of side element A affects the first row's height, which I don't want. I want element C to appear immediately below element B. The second example is how it looks before I add the div.row elements.
Below is the HTML and CSS for the isolated example. I had hoped that I could style the div.main element somehow so that the float of A doesn't affect the float of B-E at all. But I can't figure it out.
Please note that I'm sure there are several solutions if I start to change the HTML and styles (like using position), but I really just want to know if there is a way in CSS where the div.main element gets "its own" floating area, without being affected by the A element's float.
<style>
section {
width: 600px;
margin: auto;
}
.block {
float: left;
margin: 10px;
background-color: #339;
color: #fff;
width: 140px;
padding: 10px;
}
.side {
width: 200px;
height: 100px;
}
.main {
margin-left: 240px;
}
.row:after {
display: table;
content: ' ';
clear: both;
}
</style>
<section>
<div class="side block">This is element A in problematic example. I want element C immediately below element B, regardless of the height of this element</div>
<div class="main">
<div class="row">
<div class="block">This is element B</div>
</div>
<div class="row">
<div class="block">This is element C</div>
<div class="block">This is element D</div>
<div class="block">This is element E</div>
</div>
</div>
</section>
<section>
<div class="side block">This is element A when it works but without rows</div>
<div class="main">
<div class="block">This is element B</div>
<div class="block">This is element C</div>
<div class="block">This is element D</div>
<div class="block">This is element E</div>
<div class="block">This is element F</div>
<div class="block">This is element G</div>
<div class="block">This is element H</div>
<div class="block">This is element I</div>
</div>
</section>
Seems to be working if you change your CSS for .main to this (display: table-row;):
.main {
margin-left: 240px;
display: table-row;
}
Updated JSFiddle here
UPDATE 1
Changed table to table-row since it did not work in IE10.
UPDATE 2
For future reference, the final solution used in SharePoint / O365 looked something like this:
HTML (.container is a bootstrap container)
<div id="DeltaPlaceHolderMain">
<div class="container">
<div class="inner-container">
<!--Your content here-->
</div>
</div>
</div>
CSS
.container .inner-container {
display: inline-block;
width: 100%;
}
The .main needs to be float:left and it needs to have less px to width.
Try defines
.side {width:30%; float:left;}
.main{width:70%; float:left; margin-left:0; }
Don't forget to clean the margin-left of .main
The clear: both property on the row:after pseudoclass is causing your second row to jump down below the left-floated side element.
In bootstrap you should use classname col-md-4 on your side element, classname col-md-8 on your main element, and remove the float: left property from your side element. This will give you 2 columns, one for side which is 4 grids wide and one for main which is 8 grids wide. Your rows should function as you expect once the float is gone.
<style>
section {
width: 600px;
margin: auto;
}
.block {
background-color: #339;
color: #fff;
padding: 10px;
}
</style>
<section class="row">
<div class="block col-md-4">This is element A</div>
<div class="col-md-8">
<div class="row">
<div class="block col-md-6">This is element B</div>
</div>
<div class="row">
<div class="block col-md-6">This is element C</div>
<div class="block col-md-6">This is element D</div>
<div class="block col-md-6">This is element E</div>
</div>
</div>
</section>
In general, with bootstrap you don't want to float things. Also, instead of setting element widths explicitly, it is better to use the .col- classes to fit them into the bootstrap grid system.

eliminate container div element using only css

I have this structure:
<div clas="page_cat_list">
<div class="page_cat_row">
<div class="page_cat_item">...</div>
<div class="page_cat_item">...</div>
<div class="page_cat_item">...</div>
<div class="clear_fix"></div>
</div>
<div class="page_cat_row">
<div class="page_cat_item">...</div>
<div class="page_cat_item">...</div>
<div class="page_cat_item">...</div>
<div class="clear_fix"></div>
</div>
</div>
this displays 3 items in a row, but I need the page_cat_list 100% width, and as many items they fit in the row dinamically.
I used:
.clear_fix {
display: none;
}
that`s ok, and
.page_cat_row{
display: inline;
}
this way I have as many items as they fit in the row, but they are aligned left, I tried:
.page_cat_row, page_cat_list {
text-align: center;
}
but is not working
the best solution should be to eliminate the .page_cat_row element, from CSS if possibile, because I have no access to html.
It is supposed to behave like this:
<div clas="page_cat_list">
<div class="page_cat_item">...</div>
<div class="page_cat_item">...</div>
<div class="page_cat_item">...</div>
<div class="page_cat_item">...</div>
<div class="page_cat_item">...</div>
<div class="page_cat_item">...</div>
</div>
.page_cat_item is a div and by default 100% width so you need to center align content inside this div not the whole this
.page_cat_item {
text-align: center;
}
Also the css you were using is having an error
.page_cat_row, page_cat_list {
text-align: center;
}
In your above css you need to define . for both classes not just for first
This is correct
.page_cat_row, page_cat_list {
text-align: center;
}

Wrap floating DIVS Responsive view

i am just wondering if i have layout like this
<div class="container">
<div class="left"> Left </div>
<div class="right"> Right </div>
</div>
changing view port to 320 needs right div appear first and left div below it , Is this possible ??????
yes. just use the flex-box setup on the pertinent media query, as exemplified below and the boxes will show up reversed.
<html><head></head><body><div class="container" style="
display: -webkit-flex;
">
<div class="left" style="
-webkit-flex-flow: column;
background: lightgray;
"> Left </div>
<div class="right" style="
-webkit-flex-flow: column;
background: yellow;
-webkit-order: -1;
"> Right </div>
</div>
</body></html>
Original source: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes
It is possible and widely used. Take a look at this mobile first approach:
<div class="container">
<div class="right"> Right </div>
<div class="left"> Left </div>
</div>
This will be rendered one box below another on mobile. And now we use CSS to rearrange them on bigger screens (above 320px):
#media only screen and (min-width : 481px) {
.left { float: left; }
.right { float: right; }
}

Resources