'Bootstrap grid for printing
I would like to design a report page with a different layout for printing to mobile. I am using bootstrap v3. It seems the grid can't differentiate between the two as the breakpoint for printing is the same as the breakpoint for mobile (xs)
For example: In the below test html my printed page (or print preview) shows the xs6 columns side by side but the sm6 columns stacked. There isn't a breakpoint between xs and sm.
Surely my printed page is wider than my mobile viewport so shouldn't it use the sm layout?
Am I doing something wrong or is this the way it is? Is there a defined viewport width for printing?
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-xs-6">
xs6
</div>
<div class="col-xs-6">
xs6
</div>
</div>
<div class="row">
<div class="col-sm-6">
sm6
</div>
<div class="col-sm-6">
sm6
</div>
</div>
</div>
</body>
</html>
Solution 1:[1]
What I did was to manually recreate those columns classes in my print css.
.col-print-1 {width:8%; float:left;}
.col-print-2 {width:16%; float:left;}
.col-print-3 {width:25%; float:left;}
.col-print-4 {width:33%; float:left;}
.col-print-5 {width:42%; float:left;}
.col-print-6 {width:50%; float:left;}
.col-print-7 {width:58%; float:left;}
.col-print-8 {width:66%; float:left;}
.col-print-9 {width:75%; float:left;}
.col-print-10{width:83%; float:left;}
.col-print-11{width:92%; float:left;}
.col-print-12{width:100%; float:left;}
Then I just use those classes like I use bootstrap classes to make my columns for print only. I also created .visible-print
and .hidden-print
to hide/show elements only in the print version.
It still needs some work, but that quick patch helped me a lot.
Solution 2:[2]
If you want the Bootstrap's grid do not print with col-xs (mobile settings) , and want to use col-sm-?? instead , Based on Fredy31 answer and you don't even need to define col-print-??. simply rewrite all col-md-?? css class definitions inside a: @media print { /* copy and paste from bootstrap.css*/ } like this:
@media print {
.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
float: left;
}
.col-sm-12 {
width: 100%;
}
.col-sm-11 {
width: 91.66666667%;
}
.col-sm-10 {
width: 83.33333333%;
}
.col-sm-9 {
width: 75%;
}
.col-sm-8 {
width: 66.66666667%;
}
.col-sm-7 {
width: 58.33333333%;
}
.col-sm-6 {
width: 50%;
}
.col-sm-5 {
width: 41.66666667%;
}
.col-sm-4 {
width: 33.33333333%;
}
.col-sm-3 {
width: 25%;
}
.col-sm-2 {
width: 16.66666667%;
}
.col-sm-1 {
width: 8.33333333%;
}
}
Solution 3:[3]
The Sass version of Fredy31 solution:
@for $i from 1 through 12 {
.col-print-#{$i} {
width: #{percentage(round($i*8.33)/100)};
float: left;
}
}
Solution 4:[4]
For Bootstrap 4 (using SASS)
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
@for $i from 1 through $grid-columns {
@media print {
.col-print#{$infix}-#{$i} {
@include make-col($i, $grid-columns);
}
}
}
}
}
will create
@media print {
.col-print-1 {
flex: 0 0 8.33333%;
max-width: 8.33333%; } }
@media print {
.col-print-2 {
flex: 0 0 16.66667%;
max-width: 16.66667%; } }
@media print {
.col-print-3 {
flex: 0 0 25%;
max-width: 25%; } }
@media print {
.col-print-4 {
flex: 0 0 33.33333%;
max-width: 33.33333%; } }
@media print {
.col-print-5 {
flex: 0 0 41.66667%;
max-width: 41.66667%; } }
@media print {
.col-print-6 {
flex: 0 0 50%;
max-width: 50%; } }
@media print {
.col-print-7 {
flex: 0 0 58.33333%;
max-width: 58.33333%; } }
@media print {
.col-print-8 {
flex: 0 0 66.66667%;
max-width: 66.66667%; } }
@media print {
.col-print-9 {
flex: 0 0 75%;
max-width: 75%; } }
@media print {
.col-print-10 {
flex: 0 0 83.33333%;
max-width: 83.33333%; } }
@media print {
.col-print-11 {
flex: 0 0 91.66667%;
max-width: 91.66667%; } }
@media print {
.col-print-12 {
flex: 0 0 100%;
max-width: 100%; } }
Solution 5:[5]
Your switch styles like this
<div class="row">
<div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
<div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
<div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
</div>
See
#grid-example-mixed or #grid-example-mixed-complete
and may you need to clearfix
<!-- Add the extra clearfix for only the required viewport -->
<div class="clearfix visible-xs"></div>
Edit: 04/2019
Since Bootstrap 4.x there are new classes that can be used to set the display behavior when printing. SEE 4.3 Docs
Solution 6:[6]
I had a similar problem, for me the easiest solution was to manually modify the width for elements I wanted to appear differently when printed (and I added a specific class -in my case: title-container, details-container for those, along the col-xs-6 etc.).
For example:
<div class="jumbotron">
<div class="container">
<div class="row">
<div class="col-xs-12 col-ms-3 col-sm-6 col-md-6 title-container">
Some stuff
</div>
<div class="col-xs-12 col-ms-9 col-sm-6 col-md-6 details-container">
Some more stuff
</div>
</div>
</div>
</div>
@media print {
.title-container {
width: 360px;
float: left;
}
.details-container {
width: 300px;
float: right;
}
}
In my case I needed a column to be floated on the right, one to the left, thus the floats... You could set in your custom css the width also for .col-xs-6 etc. just a quick and dirty solution, but did the job for a page where I needed this...
Solution 7:[7]
Instead of recreating with new column names like .col-print-1 , .col-print-2 , write a media query which will be enable while printing the document.
@media print {
.col-md-1,.col-md-2,.col-md-3,.col-md-4,
.col-md-5,.col-md-6,.col-md-7,.col-md-8,
.col-md-9,.col-md-10,.col-md-11,.col-md-12 {
float: left;
}
.col-md-1 {
width: 8%;
}
.col-md-2 {
width: 16%;
}
.col-md-3 {
width: 25%;
}
.col-md-4 {
width: 33%;
}
.col-md-5 {
width: 42%;
}
.col-md-6 {
width: 50%;
}
.col-md-7 {
width: 58%;
}
.col-md-8 {
width: 66%;
}
.col-md-9 {
width: 75%;
}
.col-md-10 {
width: 83%;
}
.col-md-11 {
width: 92%;
}
.col-md-12 {
width: 100%;
}
}
So by this way we can be able to apply print css styles directly without changing the column names.
Solution 8:[8]
The following works great to create grid elements specific for print media. Using Bootstrap 3.
@media print {
.make-grid(print);
}
Then you can use all the grid col elements with the print
keyword. Ex: col-print-6
col-print-offset-2
, etc.
Solution 9:[9]
Maybe you could use Bootstrap 2. If you are familiar with Bootstrap 2, then you can use it as an alternative, as this offers non responsive CSS. Bootstrap 2 was not mobile first, you had to add an extra style sheet to make your web pages responsive.
Or you can add clearfixes for the mobile part. See http://getbootstrap.com/css/#grid-responsive-resets
Solution 10:[10]
And the SASS version of Ehsan Abidi's answer using MiCc83's answer:
@for $i from 1 through 12 {
.col-sm-#{$i} {
width: #{percentage(round($i*8.33)/100)};
float: left;
}
}
I prefer this because I always spec the "sm" size and that most closely approximates a print page in my applications. Then I only need to add something specifically for print when I've got an outlier condition.
Solution 11:[11]
If you only have 2 columns, you can try it. I fixed it with the code below.
<div class="row">
<div class="w-50 p-3 float-left">
</div>
<div class="w-50 p-3 float-right">
</div>
</div>
Solution 12:[12]
If it's just one line of text in two columns you can use the accepted answer here.
Solution 13:[13]
For Bootstrap 4 sass here are some snippets that I applied across several projects. These are making adjustments on:
- Grid (follows the LG breakpoint)
- Spacers (rewrite all below LG margins/paddings)
- Buttons (since background-colors does not work in print preview, switch filled buttons to outline)
- Display (rewrite all below LG displays)
- Text alignments (rewrite all below LG breakpoint)
@media print {
$grid-breakpoints-print: (lg: 992px); // keep breakpoint that you would like to apply for print
/* Rewrite margins, padding, display & alignment to keep the LG and not the mobile ones */
@each $breakpoint in map-keys($grid-breakpoints-print) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints-print);
// rewrite all displays for your print breakpoint
@each $value in $displays {
.d#{$infix}-#{$value} {
display: $value !important;
@each $v in $displays {
&.d-#{$v} {
display: $value !important;
&.d-print-none,
&.table__sort {
display: none !important;
}
}
}
&.d-print-none {
display: none !important;
}
}
}
// rewrite all spacings for your print breakpoint
@each $prop, $abbrev in (margin: m, padding: p) {
@each $size, $length in $spacers {
.#{$abbrev}#{$infix}-#{$size} {
#{$prop}: $length !important;
@each $s, $l in $spacers {
&.#{$abbrev}-#{$s},
&.#{$abbrev}-auto {
#{$prop}: $length !important;
}
}
}
.#{$abbrev}t#{$infix}-#{$size},
.#{$abbrev}y#{$infix}-#{$size} {
#{$prop}-top: $length !important;
@each $s, $l in $spacers {
&.#{$abbrev}t-#{$s},
&.#{$abbrev}y-#{$s},
&.#{$abbrev}t-auto,
&.#{$abbrev}y-auto {
#{$prop}-top: $length !important;
}
}
}
.#{$abbrev}r#{$infix}-#{$size},
.#{$abbrev}x#{$infix}-#{$size} {
#{$prop}-right: $length !important;
@each $s, $l in $spacers {
&.#{$abbrev}r-#{$s},
&.#{$abbrev}x-#{$s},
&.#{$abbrev}r-auto,
&.#{$abbrev}x-auto {
#{$prop}-right: $length !important;
}
}
}
.#{$abbrev}b#{$infix}-#{$size},
.#{$abbrev}y#{$infix}-#{$size} {
#{$prop}-bottom: $length !important;
@each $s, $l in $spacers {
&.#{$abbrev}b-#{$s},
&.#{$abbrev}y-#{$s},
&.#{$abbrev}b-auto,
&.#{$abbrev}y-auto {
#{$prop}-bottom: $length !important;
}
}
}
.#{$abbrev}l#{$infix}-#{$size},
.#{$abbrev}x#{$infix}-#{$size} {
#{$prop}-left: $length !important;
@each $s, $l in $spacers {
&.#{$abbrev}l-#{$s},
&.#{$abbrev}x-#{$s},
&.#{$abbrev}l-auto,
&.#{$abbrev}x-auto {
#{$prop}-left: $length !important;
}
}
}
}
}
// rewrite all text alignments for your print breakpoint
.text#{$infix}-left {
text-align: left !important;
&.text-left,
&.text-right,
&.text-center {
text-align: left !important;
}
}
.text#{$infix}-right {
text-align: right !important;
&.text-left,
&.text-right,
&.text-center {
text-align: right !important;
}
}
.text#{$infix}-center {
text-align: center !important;
&.text-left,
&.text-right,
&.text-center {
text-align: center !important;
}
}
}
/* Rewrite grid to keep the LG and discard the mobile */
@for $i from 1 through 12 {
.col-lg-#{$i} {
flex: 0 0 #{percentage(round($i*8.33)/100)} !important;
max-width: #{percentage(round($i*8.33)/100)} !important;
@for $k from 1 through 12 {
&.col-xs-#{$k},
&.col-sm-#{$k},
&.col-md-#{$k},
&.col-#{$k} {
flex: 0 0 #{percentage(round($i*8.33)/100)} !important;
max-width: #{percentage(round($i*8.33)/100)} !important;
}
}
}
}
/* Since the print will not fill background-colors you need to transform filled buttons into outline */
@each $color, $value in $theme-colors {
.btn-#{$color} {
color: $value !important;
background-color: $white !important;
}
}
}
Here is a working Fiddle. Keep in mind that only @media print { ... } matters in the fiddle example. Variables from the beginning where copied to have a working fiddle.
Solution 14:[14]
Based on Fredy31's answer using Bootstrap's exact widths and removing repetition of float left.
[class^="col-print"] {float:left;}
.col-print-1 {width:8.33333333%;}
.col-print-2 {width:16.66666667%;}
.col-print-3 {width:25%;}
.col-print-4 {width:33.33333333%;}
.col-print-5 {width:41.66666667%;}
.col-print-6 {width:50%;}
.col-print-7 {width:58.33333333%;}
.col-print-8 {width:66.66666667%;}
.col-print-9 {width:75%;}
.col-print-10{width:83.33333333%;}
.col-print-11{width:91.66666667;}
.col-print-12{width:100%;}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow