Auto page-break in Bootstrap columns - css

I am working on a print stylesheet for a web application. The application uses bootstrap. Every page should be printable and as much whitespace should be removed as possible.
My problem involves the following HTML code:
<div class="row">
<div class="col-xs-6">
<div class="line">...</div>
<div class="line">...</div>
<div class="line">...</div>
</div>
<div class="col-xs-6">
<div class="line">...</div>
<div class="line">...</div>
<div class="line">...</div>
</div>
</div>
I have a two column layout and each column features several lines. Is there a way to enable page-break between lines in the columns?
The columns can have a lot of lines and I want to avoid that the whole div is shifted to a new page. Instead I want to have a page-break between the lines of the div.
I think the main problem I am facing is that I have table that is constructed column by column and not row by row like a normal HTML table.

You're right: because this is structured as css columns instead of as a <table>, you won't be able to do this without using a script to heavily modify the DOM.
But the solution isn't too tricky. Let's think about what you want: a grid that #media screen has three rows and on #media print puts each row on its own page. If each row was grouped in a single element, you could use the page-break-after and/or page-break-before CSS properties to put each row on its own page. In your markup each row is
.row .col-x .line
which both gets in the way of your print formatting and isn't semantic. Let's make each row a .row!
#import 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css';
#media print {
.rows-print-as-pages .row {
page-break-before: always;
}
/* include this style if you want the first row to be on the same page as whatever precedes it */
/*
.rows-print-as-pages .row:first-child {
page-break-before: avoid;
}
*/
}
<div class="container rows-print-as-pages">
<div class="row">
<div class="col-xs-6">first row left</div>
<div class="col-xs-6">first row right</div>
</div>
<div class="row">
<div class="col-xs-6">second row left</div>
<div class="col-xs-6">second row right</div>
</div>
<div class="row">
<div class="col-xs-6">third row left</div>
<div class="col-xs-6">third row right</div>
</div>
</div>
(Here the breaks don't go in the right place without a .container. Depending on the rest of you page, the .container may not be necessary.)
Checking #media print styles is a little inconvenient, but you can do it by making a demo in codepen, selecting the "debug" view, and then looking at the print preview or saving as a pdf. Here's a link to the codepen debug view of the above snippet

Related

Why negative margin in .row?

In the Flexboxgrid framework I see a margin of -1rem on the .row class. In small viewports this creates a small horizontal scroll of the container.
Since I've seen this negative margin on other frameworks, what is its purpose? Inner columns have a padding of the same qty, reversed.
In the picture, red line is .container, dashed line is .row. Btw the margin is visible only on the right.
Because you're supposed to use them in combination with columns.
Columns generally have a padding to push the contents of them away from the border, in order to make it look nicer. However, when you are nesting columns within columns, the content keeps getting pushed inwards, which is mostly not a desired effect. To keep this from happening the rows have a negative margin, which pulls the columns back. In your case, it looks like you need to add a col-xs-12 around the column groups within the rows . This will prevent the content from being pulled too far.
Take a look here for a nicely explained introduction.
Here's a demonstration of how the .row class works:
.col1 {
background: red;
}
.col2 {
background: green;
}
body {
font-family: sans-serif;
}
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/flexboxgrid/6.3.1/flexboxgrid.min.css" type="text/css">
<div class="row">
<div class="col-xs-12
col1">
<div class="col-xs-12
col2">
<div class="box">Without a row</div>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-xs-12
col1">
<div class="row">
<div class="col-xs-12
col2">
<div class="box">With a row</div>
</div>
</div>
</div>
</div>
In general row is placed in container. container has padding of 15 and row has margin of -15

Bootstrap - resize specific column

I don't know how to make this kind of col 3 and 6 size.
Middle column has no padding, but it is not enough.
I was trying to make different sizes of col.
#media (min-width:992px){
.col-md-6 { width: 52,5641%;}
.col-md-3 { width: 23,7179%;}
}
but no success.
With Bootstrap you dont need to add media queries or your own width, just use the BS grid system (you can read more here) and let it handle all the tough work. Based on your picture a 3 column layout would use something like this:
<div class="row">
<div class="col-md-3">.col-md-3</div>
<div class="col-md-6">.col-md-6</div>
<div class="col-md-3">.col-md-3</div>
</div>
Make sure you columns total 12 like above (3+6+3) If you need extra padding in between columns just add a nested DIV and apply the spacing you want to those.
<div class="row">
<div class="col-md-3">
<div class="myclass">
this will have extra padding
</div>
</div>
<div class="col-md-6">.col-md-6</div>
<div class="col-md-3">.col-md-3</div>
</div>
.myclass {
padding: 20px;
}
Updated
Based on your comment if you want column 6 to be slightly larger than it is you will either need to expand that column and "shrink" the outer 2 columns to something like this:
<div class="row">
<div class="col-md-2">.col-md-2</div>
<div class="col-md-8">.col-md-8</div>
<div class="col-md-2">.col-md-2</div>
</div>
If that's not what you are going for then you can create your own table within bootstrap.
<div class="row">
<div class="custom-col">My custom left side</div>
<div class="custom-main">my main column</div>
<div class="custom-col">My custom right side</div>
</div>
Sizing each of the column as you need.
Maybe Bootstrap is not the best option for your problem. It works if only you can divide the screen in 12 equal parts. Rewrite this rule could break other stuff.
What about using flexboxes or other CSS framework more flexible?

Forcing an irregular Bootstrap column / row wrapping

I have a typical grid layout as seen attached:
I have 2 rows - one with the widget / header columns and another with the sidebar and content. I did this to keep the widget and header height the same and responsive WITHOUT specifying the height via CSS.
The issue is when it wraps for mobile I want the header and content to stay together at the bottom. I can do a single row with two columns then nest two rows in each but then I am back to specifying the height of the first rows of each nested grid.
I can make that work but it just seems to me that perhaps there is a more elegant solution which escapes me at the moment.
DEMO
Instead of putting widget-header & sidebar-content pairs in 2 separate rows & using pull & pushto adjust the grid, you can easily put widget-sidebar in one column & header-content in another to solve the problem.
HTML:
<div class="col-sm-6 main">
<div class="col-sm-12 a">Widget</div>
<div class="col-sm-12 a">sidebar</div>
</div>
<div class="col-sm-6 main">
<div class="col-sm-12 a">header</div>
<div class="col-sm-12 a">content</div>
</div>
CSS:
.a{ /*for demo only*/
height:100px;
border:2px solid red;
}
.main{
padding:0px; /*for no padding between 2 columns in small devices*/
}

dynamically created bootstrap columns with different heights, float to left

Consider an unknown number of divs being created dynamically and styled using the bootstrap grid system. In this example, I'm using col-sm-4 so after every third block, we move to a new row. The blocks (divs) can be different heights, which is determined by the content within.
This is where I run into the layout problem. When moving to a new row, I want the fourth block to float to the left. This only happens when the left most div in the row above is also the shortest. I have pictures to illustrate.
Real Life:
The Dream:
The "correct" way to do this would be to wrap every three in a row class I beleive, but I'm not sure how to do this with dynamic content (could probably hack it) or if there's an easy css solution.
HTML:
<div class="row">
<div class="col-sm-12">
<div class="col-sm-4 block">
<div class="inner-block"></div>
</div>
<div class="col-sm-4 block">
<div class="inner-block"></div>
</div>
<div class="col-sm-4 block">
<div class="inner-block" style="height:150px"></div>
</div>
<div class="col-sm-4 block">
<div class="inner-block"></div>
</div>
</div>
</div>
CSS:
.block {
padding: 5px;
}
.inner-block {
height: 200px;
background-color: blue;
}
Plunker Example (expand preview to proper size)
If your system is unable to add first/last classes on every nth div, then you can use the nth-child css pseudo selector.
#media (min-width: 768px) {// For medium displays and above
.col-sm-4:nth-child(3n+1) { // We target every 3rd div but offset the count by 1 so that that 1st, 4th 7th etc divs are cleared
clear:both; // Clear the float
}
}

Create a user-defined gap between two Bootstrap columns

I want to create little panels/dashboard for my interface. In my case I want to have two panels like so
+-------------------------------+ +-------------------------------+
| | | |
| | | |
+-------------------------------+ +-------------------------------+
Generally it is easy with Bootstrap 3.
<div class="row">
<div class="col-md-5">
</div>
<div class="col-md-5 pull-right">
</div>
</div>
The problem is, the gap of col-md-2, as it is the case here, is way too big. I cannot use a col-md-1 gap, because then both sides do not have an equal size.
I also tried to add padding right and left, but that had not effect, too. What can I do here?
You could add a class which modifies the width of col-md-6. The width of this class is set to 50%. A smaller gap is achieved by reducing the width like so:
.dashboard-panel-6 {
width: 45%;
}
Add this to your div elements. This way the width rule of col-md-6 gets overriden.
<div class="row">
<div class="col-md-6 dashboard-panel-6">...</div>
<div class="col-md-6 dashboard-panel-6">...</div>
</div>
You can use another div inside and give padding to that.
<div class="row">
<div class="col-md-6">
<div class="inner-div">
</div>
</div>
<div class="col-md-6 pull-right">
<div class="inner-div">
</div>
</div>
</div>
.inner-div{
padding: 5px;
}
I posted this here already but it is still relevant the original question.
I have had similar issues with space between columns. The root problem is that columns in bootstrap 3 and 4 use padding instead of margin. So background colors for two adjacent columns touch each other.
I found a solution that fit our problem and will most likely work for most people trying to space columns and maintain the same gutter widths as the rest of the grid system.
This was the end result we were going for
Having the gap with a drop shadow between columns was problematic. We did not want extra space between columns. We just wanted the gutters to be "transparent" so the background color of the site would appear between two white columns.
this is the markup for the two columns
<div class="row">
<div class="col-sm-7">
<div class="raised-block">
<h3>Facebook</h3>
</div>
</div>
<div class="col-sm-5">
<div class="raised-block">
<h3>Tweets</h3>
</div>
</div>
</div>
CSS
.raised-block {
background-color: #fff;
margin-bottom: 10px;
margin-left: 0;
margin-right: -0.625rem; // for us 0.625rem == 10px
padding-left: 0.625rem;
padding-right: 0.625rem;
}
#media (max-width: 33.9em){ // this is for our mobile layout where columns stack
.raised-block {
margin-left: -0.625rem;
}
}
.row [class^="col-"]:first-child>.raised-block {
// this is so the first column has no margin so it will not be "indented"
margin-left: -0.625rem;
}
This approach does require an inner div with negative margins just like the "row" class bootstrap uses. And this div, we called it "raised-block", must be the direct sibling of a column
This way you still get proper padding inside your columns. I have seen solutions that appear to work by creating space, but unfortunately the columns they create have extra padding on either side of the row so it ends up making the row thinner that the grid layout was designed for. If you look at the image for the desired look, this would mean the two columns together would be smaller than the one larger one on top which breaks the natural structure of the grid.
The major drawback to this approach is that it requires extra markup wrapping the content of each columns. For us this works because only specific columns needed space between them to achieve the desired look.
Hope this helps
Here's another possibility:
Live view
Edit view
You will see that it uses 2 col-md-6, each with a nested col-md-11, and you position the nested row in the second div to the right.
The suggestion from Ken has clean HTML which I like. If your left and right panels use elements with widths defined by Bootstrap though (eg wells or form elements) the column padding could cause hassles and break the layout. This nested approach might be easier in this situation.
HTML
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="row">
<div class="col-md-11">nested row col-md-11</div>
</div><!-- end nested row -->
</div>
<div class="col-md-6">
<div class="row">
<div class="col-md-11 col-md-offset-1">nested row col-md-11</div>
</div><!-- end nested row -->
</div>
</div>
</div>
Good luck!

Resources