Bootstrap print CSS removes background color
Asked Answered
C

10

30

When I use bootstrap, it removes the background color from everthing when I try to print my page. Almost everything on my website is using bootstrap classes so I want to avoid a lot of manual CSS outside bootstrap. I've found out that bootstrap uses @media print to remove the background color. I'm using a bootstrap theme as well (theme united) which is removing the background color as well.

theme-united.css

@media print
*, *:before, *:after {
    background: rgba(0, 0, 0, 0) !important;
    color: rgb(0, 0, 0) !important;
    -webkit-box-shadow: none !important;
    box-shadow: none !important;
    text-shadow: none !important;

bootstrap.min.css

@media print
*, :after, :before {
    color: rgb(0, 0, 0)!important;
    text-shadow: none!important;
    background: 0 0!important;
    -webkit-box-shadow: none!important;
    box-shadow: none!important;

Is there a way to make sure that the background color is not removed when printing without editing these 2 CSS files?

For example: When I use .alert-danger, I want that alert danger printed as it is displayed on screen, so would be printed as a red box.

See JSFiddle: http://jsfiddle.net/7mtk7wrh/

Cholinesterase answered 29/10, 2015 at 9:44 Comment(5)
Refer the stack overflow question #14987996Brash
Which color you want to set as background right now it will show black right?Ticknor
@AkashK.: ofcourse I thought of that, but none of it is working so far. I don't want to add every bootstrap color to my own CSS to override bootstrap printing styles.Cholinesterase
@Mithun: I tried that solution already, but the colors are still overwritten by bootstrap.Cholinesterase
@Mitul: I want to use the colors of the original bootstrap class (for example; when I use .alert-danger, I want to see a red box)Cholinesterase
T
50

Unfortunately there is not a good answer to your question - but maybe if you understand the why's then you can choose a way forward.

Why?

It's true that Bootstrap uses the @media print { * { color: $fff; background: transparent; }} -- but there is a very solid reason. This bit of code is actually derived from the normalizer.css project (by a then college of @mdo 's, @necolas) - it's intent is to make all browsers behave the same. These guys chose to "normalise" the css for a very good reason:

With most browsers one can choose to include or exclude background color, so the behaviour is not standard across even the same browser. Imagine for a sec a website with very dark background with white text - when printing with backgrounds off, it will look like you're printing nothing - when actually you're printing white text on no (white) background.

There was no way to account for all the different uses of color, so they choose to go black (font) and white (background, actually 'transparent'). Even the choice of black was well thought of -- its a better print solution, as most color printers have more black "ink/toner" (more economical) and they don't need to mix color to make black (so faster).

Remember that Bootstrap is also a "framework" - so a starting point if you will - and kudos to @mdo and @necolas for having the foresight to think of this in terms of establishing a predictable baseline. (No, I don't know them.)

Nope...

So the thinking here is: "what if we could 'go back' and unset this. Unfortunately CSS does not work like that - yes browsers load the CSS declarations in a "queue" where the last declaration wins (LIFO, or last-in-first-out), but I'm not aware of a way to remove this stack. So CSS developers just add more to the end...

So one would assume that we can go back that way --- add a * { background-color: inherit }. Problem is that inherit reverts to the parent property, but * is the root, so it has nothing to revert to. Same goes for initial!

Maybe!

So we're left with 4 options, none of them is what you where hoping for, but it is what it is. In order of difficulty:

  1. Download the BS (less or sass) source, edit the offending code, and then compile it. (You need to use a local copy, CDN's will not work.)
  2. Download the CSS variant of your choice, search and delete the offending code. (No CDN's again.)
  3. Use getbootstrap.com/customize to create a new variant - exclude "Print media styles" under "Common CSS". (Again, no CDN's)
  4. Override the specific items who's color you want to print: e.g.
    @media print {
      .alert-danger {
        color: yellow !important;
        background-color: red !important;
      }
    }

CDN's copies of BS will now work, but then you have the problem of the user possibly not printing backgrounds and having the output white (yellow in the e.g.) on white!

Finally

Well I hope learning the why's was at the very least a way of you thinking of a workaround. General rule of thumb I follow is that when printing, the background is (should be) always white. When constrained that way you start thinking of novel ideas, like exclamation icons around the text that only "print" (@media only screen { .hidden-screen { display: none; }})

Trig answered 20/4, 2016 at 11:13 Comment(2)
I want to keep the background image not color, so this solution doesn't work.Icono
Great explanation. Finally end up creating a new view for print purposes without Bootstrap...Nectareous
T
11

Despite !important usage being generally frowned upon, this is the offending code in bootstrap.css

.table td,
.table th {
    background-color: #fff !important;
}

Let's assume you are trying to style the following HTML:

<table class="table">
    <tr class="highlighted">
      <th>Name</th>
      <th>School</th>
      <th>Height</th>
      <th>Weight</th>
    </tr>
</table>

To override this CSS, place the following (more specific) rule in your stylesheet:

@media print {
    table tr.highlighted > th {
        background-color: rgba(247, 202, 24, 0.3) !important;
    }
}

This works because the rule is more specific than the bootstrap default.

Towline answered 28/4, 2018 at 16:8 Comment(0)
K
1

You can get this working by removing those lines from bootstrap.css file, there might be a jquery solution to this but it is much more complicated than erasing a few lines. :/

Or you could use a plugin called html2canvas as presented in this jsfiddle

Klipspringer answered 29/10, 2015 at 10:10 Comment(13)
Tried this one, but this is resetting the color to the original value. Thing is, I use, for example, .alert-danger to create a box with a red background, I want that red box printed as a red box as well. So I need the bootstrap CSS to add the background color, I just don't need the printing part.Cholinesterase
try to change it to initial then. the CSS initial will go to bootstrap.css settings for that box and disregard the rules that were set before. If it doesn't work, do you mind sending a link or recreating the problem in jsfiddle? :)Klipspringer
Not working either. This is setting the color to the default value: w3schools.com/cssref/css_initial.asp. Inherit is not working because there is !important the the transparent back-ground color in the css so the real color is ignored.Cholinesterase
The just remove those rules from bootstrap.css, it's not like you're updating bootstrap every day... I still think this can be fixed without fiddling with bootstrap.css, could you recreate the problem in jsfiddle please?Klipspringer
I've added the JSFiddle in m question with your example already in it. I'm not going to update bootstrap everyday, very true. But I know I'm going to forget to remove those lines an I think it's stupid that bootstrap removes the background color so I can't stand it that I should edit the bootstrap CSS and that there would be no work around.Cholinesterase
Sorry, I can't think of a better solution than to remove those lines from bootstrap.css - inherit would have worked if !important wasn't used. - By the way, I couldn't find those rules in the bootstrap.css file, I was checking bootstrap.3.3.5Klipspringer
This is what I found in the CSS: @media print { *, *:before, *:after { color: #000 !important; text-shadow: none !important; background: transparent !important; -webkit-box-shadow: none !important; box-shadow: none !important; }Klipspringer
Oh yes, You're right, my chrome automatically translates to rgba so I guess that's the rgba value of it or something. The css is indeed transparent.Cholinesterase
Found a solution for you, please check my revised answer.Klipspringer
It is indeed working for the background-color, but when I add the class hidden-print, that element is printed as well.Cholinesterase
Well, simple fix... move the rule hidden-print as a last rule in all your CSS files and write: `@media print { .hidden-print {display:none !important;}}Klipspringer
I've updated your JSFiddle but it doesn't seem to work: jsfiddle.net/7mtk7wrh/5Cholinesterase
Interesting question man, I am a bit busy, I will try to fix this later.Klipspringer
G
1

I ended up here with the same problem but found the Chrome comes with a show background graphics option on the print dialog under more settings that did exactly that! No modification of Bootstrap (4) required.

Graeae answered 29/11, 2017 at 17:35 Comment(0)
T
1

@Vino explained really well. I was also facing problem because bootstrap.css makes background transparent forcefully. Thus I have customized the specific element in my custom CSS file. Remember to change <.element> with element where you want the colorful background instead of transparent.

@media print {
	 .element{
		background-color: white !important;
		box-shadow:  inset 0 0 0 1000px #fff !important; /* workaround for IE 11*/
	 }
 } 
Tisza answered 19/11, 2018 at 6:4 Comment(0)
S
1

Actually, there is a solution, but this is still a hack. It was used for a pdf generation in puppeteer, so it was tested only in this case, but most probably should work in all modern browsers. Keep in mind that BOOTSTRAP_PRINT_RULE can be different in a different version of Bootstrap.

const BOOTSTRAP_PRINT_RULE = `@media print {
  *, ::after, ::before { color: rgb(0, 0, 0) !important; text-shadow: none !important; background: 0px 0px !important; box-shadow: none !important; }
  a, a:visited { text-decoration: underline; }
  a[href]::after { content: " (" attr(href) ")"; }
  abbr[title]::after { content: " (" attr(title) ")"; }
  a[href^="javascript:"]::after, a[href^="#"]::after { content: ""; }
  blockquote, pre { border: 1px solid rgb(153, 153, 153); break-inside: avoid; }
  thead { display: table-header-group; }
  img, tr { break-inside: avoid; }
  img { max-width: 100% !important; }
  h2, h3, p { orphans: 3; widows: 3; }
  h2, h3 { break-after: avoid; }
  .navbar { display: none; }
  .btn > .caret, .dropup > .btn > .caret { border-top-color: rgb(0, 0, 0) !important; }
  .label { border: 1px solid rgb(0, 0, 0); }
  .table { border-collapse: collapse !important; }
  .table td, .table th { background-color: rgb(255, 255, 255) !important; }
  .table-bordered td, .table-bordered th { border: 1px solid rgb(221, 221, 221) !important; }
}`

for (const styleSheet of document.styleSheets) {
    for (const [index, rule] of Array.from(styleSheet.cssRules).entries()) {
        if (rule.cssText && rule.cssText.includes(BOOTSTRAP_PRINT_RULE)) {
            styleSheet.deleteRule(index)
            return;
        }
    }
}
Snowmobile answered 6/4, 2021 at 20:3 Comment(1)
@M-Chen-3 it's a kind of black magic... Seriously, we just remove this exact rule from a browser's DOM There we go thru all stylesheets been loaded and try to find a rule which we need to remove. When the rule is found we remove it. It updates the CSS rules list and triggers a rerender. Think about this as a removal of a <div> element but for style rulesSnowmobile
E
0

i had also face the same problem.. i just remove the bootstrap.min.css from my code then it work for me.

Elamitic answered 21/3, 2018 at 12:4 Comment(1)
Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker.Overman
D
0

just make the specificity-value more specific and you should be ok. something like:

@media print {
   tbody>tr:nth-child(even)>td {
        background-color: rgb(230, 216, 216) !important;
    }
}
Diploma answered 22/8, 2019 at 7:42 Comment(0)
T
0

Since version 4 of Bootstrap with SASS you can actually set the following variable to false which will turn of this behavior:

$enable-print-styles: false

If this is not an option, there is the following script which brutally rips out all @media print annotations from the CSS. It assumes that Bootstrap is the first style sheet loaded and that it runs after Bootstrap has loaded.

var style = document.styleSheets[0];

[].forEach.call(style.cssRules || [], function (aRule, aIndex) {
   if (aRule.cssText.indexOf("@media print") >= 0) {
      style.deleteRule(aIndex);
   }
});
Tsai answered 26/12, 2021 at 20:30 Comment(0)
B
0

You can use this (https://developer.mozilla.org/fr/docs/Web/CSS/print-color-adjust)

.your-selector {
    -webkit-print-color-adjust: exact; 
}

Warning: This is not standart, but might help you.

Berniecebernier answered 14/4, 2022 at 9:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.