Drawing complex grid with Bootstrap - html

I'm working with a HTML view using Bootstrap3. I need to create a template with different cells and I usually work with cols and rows, but this time I have a problem with drawing one column.
This is the scheme I need:
This is the code:
<div class="row">
<div class="col-md-3 doubleHeight"></div>
<div class="col-md-9 singleHeight"></div>
<div class="col-md-3 singleHeight"></div>
<div class="col-md-3 singleHeight"></div>
<!--column bottom right-->
<!--column bottom left-->
</div>
The problem begins when I try to draw the column on the bottom right. If I draw it after the two col-md-3, it doesn't allow me to show the last column on the left inline with it. If I draw it after the last column on the left, it doesn't occupy the space above.
Have you got any idea of the possible solution?
Thanks.

WARNING: This post contains multiple variations of the same snippet between explanations to demonstrate the logic and provide a visual representation of how the code will actually operate. If you edit it, please keep that in mind.
Before I give you the solution, I want to make something PERFECTLY clear, this is NOT supported by the Bootstrap framework. To clarify, Bootstrap supports the wrapping of the blocks which can be used to account for this, however, it does NOT manipulate the height to accommodate a block spanning multiple rows.
Alright, with that said, the closet you can get to your request is via column wrapping. You can't do multiple layers of blocks because you have blocks that would belong to two different parents, and that simply isn't possible to quantify with the current CSS/HTML structure. Further, you can't do anything for the last block to appear next to the bottom-right block.
Here's a little demo of the structure that gets closet to what you are asking for:
div div {
border: 1px solid black;
}
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://getbootstrap.com/assets/js/ie-emulation-modes-warning.js"></script>
<link href="http://getbootstrap.com/dist/css/bootstrap-theme.min.css" rel="stylesheet"/>
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row">
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and unknown rows.</div>
<div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">This block spans three columns and one row.</div>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and row.</div>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and row.</div>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and row.</div>
<div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">This block spans three columns and one row.</div>
</div>
I added a little border to give a visual idea of how it actually renders. Here's the downside to this, it is 100% dependent upon your control of the content in each block to maintain the rows. For example, if you put only enough content in the very first block to account for the height of the second block, you will get the third, fourth, and fifth blocks left flushed and push the sixth block down further.
div div {
border: 1px solid black;
}
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="http://getbootstrap.com/dist/css/bootstrap-theme.min.css" rel="stylesheet"/>
<script src="http://getbootstrap.com/assets/js/ie-emulation-modes-warning.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
<div class="row">
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">One liner</div>
<div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">One liner</div>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">One liner</div>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">One liner</div>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">One liner<br />Two liner</div>
<div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">One liner</div>
</div>
I'm afraid that there is not "easy" way to mitigate this, short of defining height for each block. Further, the bottom-right block can NEVER exceed the content height of the third and fourth blocks. If it exceeds it, then you get a gap between the sixth block and those immediately above it.
div div {
border: 1px solid black;
}
.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
height: 50px;
}
.row-2 {
height: 100px;
}
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="http://getbootstrap.com/dist/css/bootstrap-theme.min.css" rel="stylesheet"/>
<script src="http://getbootstrap.com/assets/js/ie-emulation-modes-warning.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
<div class="row">
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3 row-2">This block spans one column and unknown rows.</div>
<div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">This block spans three columns and one row.</div>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and row.</div>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">This block spans one column and row.</div>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3 row-2">This block spans one column and row.</div>
<div class="col-lg-9 col-md-9 col-sm-9 col-xs-9">This block spans three columns and one row.</div>
</div>
Even though the sixth block fits into the gap, it can only follow the structure if it is after the fifth block. This forces the browser to render it below it. That's block for you.
Honestly, the ONLY way to make that layout in any framework of HTML(5) and CSS(3) is to use a table. It's a HIGHLY discouraged practice for layouts, but it, truthfully, is the only option that I know of.
Here's the upside, you can still use the Bootstrap col-lg-*, col-md-*, col-sm-*, and col-xs-* classes on the tds to ensure they follow the Bootstrap columns sizing.
td {
border: 1px solid black;
vertical-align: top;
}
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="http://getbootstrap.com/dist/css/bootstrap-theme.min.css" rel="stylesheet"/>
<script src="http://getbootstrap.com/assets/js/ie-emulation-modes-warning.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
<table>
<tr>
<td rowspan="2">This block spans one column and two rows.</td>
<td colspan="3">This block spans three columns and one row.</td>
</tr>
<tr>
<td>This block spans one column and row.</td>
<td>This block spans one column and row.</td>
<td rowspan="2">This block spans one column and two rows.</td>
</tr>
<tr>
<td colspan="3">This block spans three columns and one row.</td>
</tr>
</table>
I'm sorry, I know it's not quite what you were looking for, but, at least as far as my knowledge is concerned, it simply isn't possible to do that a wraparound layout without a table.

Masonry (javascript) seems ideal for this, although not pure CSS/Bootstrap.

In this case the problem was simplified because I had divs with fixed height. I kept Bootstrap template and I assigned to the bottom left div the class of col-md-9, giving it a certain amount of space from the top. I know it's not the best way to do it, but it is horizontally responsive still.
This is the HTML code:
<div class="row-fluid">
<div class="col-md-12">
<div class="row">
<div class="col-md-3 doubleRow box">...</div>
<div class="col-md-9 singleRow box">...</div>
<div class="col-md-3 singleRow box">...</div>
<div class="col-md-3 singleRow box">...</div>
<div class="col-md-9 singleRow box">...</div>
<div class="col-md-3 doubleRow box upper">...</div>
</div>
</div>
And this is the CSS:
.singleRow{
height:280px;
}
.doubleRow{
height:560px;
max-height:100%;
}
.upper{
top: -280px;
margin-bottom: -280px;
}
.box {
border-style: solid;
border-width: 5px;
border-color:black;
text-align: center;
padding: 1%;
position: relative;
}

Related

How can I add margin between three Bootstrap columns without them wrapping?

.background-color {
background-color: lightgrey;
height: 200px;
border: 1px solid black;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<div class="container">
<div class="row">
<div class="col-4 background-color">1</div>
<div class="col-4 background-color">2</div>
<div class="col-4 background-color">3</div>
</div>
</div>
So I have three columns which are each 4 columns in width and whenever I add m-3 (margin all around) they break off because of that, how can I contain them? So they stay all 3 on the same line?
.background-color {
background-color: lightgrey;
height: 200px;
border: 1px solid black;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<div class="container">
<div class="row">
<div class="col-4 background-color m-3">1</div>
<div class="col-4 background-color m-3">2</div>
<div class="col-4 background-color m-3">3</div>
</div>
</div>
Only way I saw around this was to nest other elements.
<div class="container">
<div class="row">
<div class="col-4"><div class="col-12 background-color m-3">1</div></div>
<div class="col-4"><div class="col-12 background-color m-3">2</div></div>
<div class="col-4"><div class="col-12 background-color m-3">3</div></div>
</div>
</div>
The Bootstrap column system (as you probably know) is based on the idea that the page has 12 notional columns. You then use the col-* classes to indicate how many of those 12 columns each element takes up. So, in this case, you've declared that each element takes up 4 columns, which means they use all 12 notional columns.
The problem is that margins in HTML are outside the element. So, if you have three elements, each using 4 columns, and then add some margin, you now have more than the width of the 12 columns available (here, 12 columns plus three lots of m-3). As a result, the third element doesn't have enough space to be displayed and flows to the next line.
To avoid this, you can use padding instead of margins (because paddings are inside the element, you get visual separation while sticking to the grid widths). Alternatively, you could reduce the width of the elements to col-3 and add your margin outside that. However, this may mean (depending on your layout) that it doesn't use the full width.
Ultimately, if you need three elements across the page with margins, it may be best to define your own classes rather than trying to use the Bootstrap classes. Frameworks are great when you work with them, and a pain when you work against them!
.background-color {
background-color: lightgrey;
height: 200px;
border: 1px solid black;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<div class="container-fluid">
<div class="row">
<div class="col background-color m-3 ">1
</div>
<div class="col background-color m-3">2</div>
<div class="col background-color m-3">3</div>
</div>
</div>
use col instead of col-4

How to make bootstrap column shrink to size of its contents

I have a bootstrap column that I want to shrink to the height of its contents so another column can fill the space below it. Here is an image of what I am referring to:
I would like for the first column – holding both col-1 boxes – to shrink to the height of its contents so the "last" box can fill the space.
Codepen link
.box {
background-color: green;
margin: 5px;
padding: 25px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<div class="container">
<div class="row">
<div class="col-12 col-md-8 col-lg-9">
<div class="box">col-1</div>
<div class="box">col-1</div>
</div>
<div class="col-12 col-md-4 col-lg-3">
<div class="box">col-2</div>
<div class="box">col-2</div>
<div class="box">col-2</div>
</div>
<div class="col-12 col-md-8 col-lg-9">
<div class="box">last</div>
</div>
</div>
</div>
Note: I originally just put the 3rd bootstrap column as a child of the first column, but had to move away from that because of how the tabbing on the page worked. I need it to tab from col-1 to col-2 to col-3, the last one.
You can't "shrink" the size of one column in a grid layout without affecting the others, so we need to break down what you want to achieve. You are trying to work with 3 different orders:
Visual order on larger screens: col-1, last, col-2
Visual order on mobile: col-1, col-2, last
Tab order on all screens: col-1, col-2, last
The mobile order and tab order are the same (and also we can't change tab order responsively without JS), so we start with this as the basis of our display.
Then we want last to be positioned before the 3rd element of col-2 on large screens, but after it on mobile, so we need to make those 2 elements work relative to each other instead of being part of the other cols.
Working Example - I've added inputs to see the tab order. (Run in Full Page to see the cols)
.box {
background-color: green;
margin: 5px 5px 0;
padding: 25px;
}
input { width: 30px; } /* For demo only */
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<div class="container">
<div class="row">
<div class="col-12 col-md-8 col-lg-9">
<div class="box"><input placeholder="1"> col-1</div>
<div class="box"><input placeholder="2"> col-1 </div>
</div>
<div class="col-12 col-md-4 col-lg-3">
<div class="box"><input placeholder="3"> col-2</div>
<div class="box"><input placeholder="4"> col-2</div>
</div>
<div class="col-12 col-md-4 col-lg-3 order-md-last">
<div class="box order-1"><input placeholder="5"> col-3</div>
</div>
<div class="col-12 col-md-8 col-lg-9">
<div class="box"><input placeholder="6"> last</div>
</div>
</div>
</div>
How this works:
1. Put the 3rd element from col-2 in its own column col-3 which has the same classes as col-2 so its looks exactly the same as when it was in col-2. It also displays exactly as it was on mobile screens. But now it can also be moved independently of col-2.
2. Move the placement of the on larger screens. The step above makes it appear before the last column, so we can use Bootstrap's order classes. Simply adding order-md-last to col-3 makes it appear last on screens above the md breakpoint:
<div class="col-12 col-md-4 col-lg-3 order-md-last">
<div class="box order-1"><input placeholder="5"> col-3</div>
</div>

Bootstrap 4 - How to achieve this layout

I'm currently working on a website and I have come across with the following problem thinking the best practice to achieve the following layout using Bootstrap 4. (Wrapped in Red)
As you can see the first column is a col-md-7 and the other one is col-md-5. However, the first column includes an image and it has to touch the left corner of the page. However, the right column has to have the standard width and column size. To give you more insight following is what I'm trying to achieve.
[JS Fiddle][2]
You mean something like that using align-self-start class?
.row {
background: #f8f9fa;
margin-top: 20px;
}
.col {
border: solid 1px #6c757d;
padding: 10px;
}
.image {
height: 200px;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<div class="container">
<div class="row d-flex">
<div class="col image">
Image
</div>
<div class="col align-self-start">
Test
</div>
</div>
</div>
You will need to wrap the left image and the right column in a row, set the column width for each, then place each item in the right column inside of that div with a full width.
I think if you continue to ask "do it for me" questions on SO you will get roasted, I know I have. But I'm here to help. LMK if you want more details.
There are a million solutions to this problem, This would be a great time to look into CSS Grid and learn the new new.
Here is a codepen of the general approach
<div class="row">
<div class="col-md-7 left-box"></div>
<div class="col-md-5">
<div class="col-md-12 item"></div>
<div class="col-md-12 item"></div>
<div class="col-md-12 item"></div>
</div>
</div>

How to make items stay in line even on smaller devices with bootstrap

I am having troubles. I am making a website with bootstrap. When I make an a row with bootstrap and add my columns, the different columns go to a new line under each other when the devices shrink in size..
my code is as follow
<div class="row">
<div class="col-xs-4 col-sm-4 col-md-4"><center>Feed</center></div>
<div class="col-xs-4 col-sm-4 col-md-4"><center>Tutor</center></div>
<div class="col-xs-4 col-sm-4 col-md-4"><center>Profile</center></div>
</div>
im not sure what i am doing wrong. Everytime i shrink my browser, it stills shrink into a new line. Help please!
Apply below css either through class name to parent row, or direct styling
.cls_name{
flex-wrap: nowrap;
}
here nowrap will forcefully show all child in a single row
Looks like this will help you.
.single-row{
display: flex;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class="container-fluid">
<div class="row single-row" >
<div class="col-sm-2" style="background-color:lavender;">Feed</div>
<div class="col-sm-2" style="background-color:lavenderblush;">tutor</div>
<div class="col-sm-2" style="background-color:lavender;">profile</div>
</div>
</div>

Adjust width of inline buttons automatically based on parent width

I currently have 3 buttons that are inline. I'm having issues in how to style these buttons so the width is automatically calculated to take the width of the parent div. For example, if the parent div is 1000px, I'd like the width of the inline buttons to be 1000/3 - a set margin to space these buttons. So those need to be taken into account which will be fixed. Catch is, the first and last element should not have a left margin and right margin respectively. This way I can dynamically add buttons and the styling should take care of the width. Hope that helps?
JsFiddle
HTML:
<div class="row" style="width: 1000px;border: 1px solid #999;">
<div class="row" style="padding-bottom:20px;">
My Button
My Button2
My Button3
</div>
</div>
You could use a table as so:
<table style="width:100%;">
<tbody style="width:inherit;">
<tr>
<td>Left</td>
<td>Centre</td>
<td>Right</td>
</tr>
</tbody>
</table>
And then add as many <td> elements as needed.
Assuming you are ignoring bootstrap standards, and wanting to custom style this.
try
.row {
/*width: 1000px;*/
border: 1px solid #999;
}
.row .row {
padding-bottom: 20px;
margin 0 -10px; /*offset the left and right gutter*/
}
.btn-default {
display: block;
float: left;
text-align: center;
margin: 10px; /*example margin*/
padding: 30px;/*example padding */
/*width: 30%;*/ /*fall back if needed*/
width: Calc((100% / 3) - 20px); /*minus 2 x margin*/
}
JSFiddle
KingKongFrog. Hi again. When you set a width to a fixed value like 1000px you lose the ability to be responsive. Try to use percentage. When using Bootstrap the xs starts around 700px, if you have say 3 buttons side by side you can run into problems fitting them across a small screen like 320px.
So you need to take over control from bootstrap css a little to do want you want to do.
I have added some of the bootstrap classes and also added some more custom classes to help show what you may need to do here.
Using #media (max-width: 320px) is the main width that you may need to control like reducing the size of the buttons/fonts etc. And if using any col-xs-offset-X when it shown on a screen size within 320px you will need to reset these to zero left etc.
Custom css that you want/need to over ride Bootstrap needs to be placed below bootstrap in the page.
Have a look at the Fiddle here and try resizing it.
Here is a full screen fiddle view that's easy for resizing.
<br>
<div class="container bg-info">
<br>
<div class="col-lg-12 bg-warning">
<br>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3
col-lg-offset-2 col-md-offset-2 col-sm-offset-1 col-xs-offset-2
col-xxs-pull-1">
My Button1
</div>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3
col-lg-offset-0 col-md-offset-0 col-sm-offset-1 col-xs-offset-0
.col-xxs-offset-1">
My Button2
</div>
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3
col-lg-offset-0 col-md-offset-0 col-sm-offset-1 col-xs-offset-0
col-xxs-push-1">
My Button3
</div>
<br><br>
</div>
<br>
</div>
If you are working with bootstrap, you have to understand the grid system. There is col-xs-..., col-sm-..., col-md-..., col-lg-... to handle the column width. Therefore don't set a width. Read bootstrap grid options to understand the basics. A whole width of the screen has in total 12 columns. For example col-xs-12 in smaller displays fills the whole width.
HTML
<div class="row">
<div class="col-..."></div>
<div class="col-..."></div>
<div class="col-..."></div>
</div>
<div class="row myButtons">
<div class="col-xs-4 col-sm-4 col-md-4 col-lg-4">
My Button
</div>
<div class="col-xs-4 col-sm-4 col-md-4 col-lg-4">
My Button2
</div>
<div class="col-xs-4 col-sm-4 col-md-4 col-lg-4">
My Button3
</div>
</div>
Here in all device sizes every part has 4 columns. In total 12. (Set, for example every cols-xs-4 to col-xs-12 and resize the screen to see what happens!). That's how bootstrap work.
Example