'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>

#grid-responsive-resets

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%;}