Predictable and consistent cross-browser printing from HTML - css

I'm trying to figure out if there's a way to achieve sane printing straight from HTML. Our users often want to print a few pages for their own records. The printouts contain Google Charts and the grid is handled by bootstrap. Very frequently we want a set of content per page and thus page breaks are very much required.
Traditionally we've used print media queries, but it's been nigh impossible to achieve consistent results across browsers, say Firefox, Chrome and Mobile Safari etc. Pieces will spill over, page breaks will be ignored etc.
Some companies like Amazon and Newegg provide customers with the ability to print out invoices and other pages. It seems that usually that involves having a separate print-only version of the content that's either all tables or very simplified -based markup that looks extremely basic when printed out. Generally there's little to no styling, few if any images, definitely no and no page breaks as far as I can tell.
Another option is to just convert everything to PDF, but that has its own pitfalls and expenses. Now you have to re-generate the same content in a second format for every page that needs to be printed, and perfectly styling PDF is non-trivial as well.
Is there anything out there can can help with this? Any commonly accepted solutions?

We use wkhtmltopdf and PrinceXML to get consistent styling. Both are command line tools that can take a URL plus a custom CSS file. They generate consistent output, and are browser independent, because they are the rendering engine.
We used to use wkhtmltopdf, but we're starting to move to PrinceXML because it supports margin-boxes and two-column layout. (The main caveat with PrinceXML is the price.)
Perfectly styling PDF doesn't seem any worse or harder than styling for web display. My experience is that it takes an hour or two to get a print page styled correctly. I've never tried to handle Google Charts.

All of the popular desktop browsers now support the CSS #page rule for setting page margins, and the CSS properties page-break-inside, page-break-before, and page-break-after for handling page breaks. These will generally provide enough control to achieve consistent cross-platform printing, but there are a few things that only one or two of the browsers can do. Some examples are:
page numbering
running page headers and footers
orphan/widow control
control of background colors
If you need any of those things, PDF might be your best option; otherwise, it might be overkill. A PDF converter isn't going to automatically determine the ideal way to paginate whatever content you throw at it; human judgement will still be required.
That doesn't mean you need to explicitly declare the location of every page break, though. It's usually a lot easier to prevent bad pagination than to force good pagination. In other words, instead of telling the browser where you do want page breaks, tell it where you don't want them.
Examples of places you might want to prevent page breaks:
between a section title and the first line of section text
between a table's column headers and the first row of data*
between closely-related form fields.
The go-to CSS declaration in these situations is page-break-inside: avoid;**. It would be easier to use page-break-after: avoid; in the first two examples, but Firefox only supports the always and auto values for that property. So instead, you have to create an unbreakable div that contains or overlaps the stuff you want to keep together. Here's one way to do it:
<style>
.section {
line-height: 1.25em;
}
.title {
page-break-inside: avoid;
padding-bottom: 1.25em;
font-weight: bold;
}
.overlap {
margin-bottom: -1.25em;
}
</style>
<div class="section">
<div class="title">
Title of This Section
</div>
<div class="overlap">
</div>
This is the section text. It could be any length, so we have to
allow page breaks in it. However, we don't want the first line to
be separated from the section title. The title is unbreakable, so
we just need to add some bottom padding to it and make it overlap
the first line of text.
</div>
*Tables are probably the most challenging thing to print consistently across browsers, but it is possible.
**Old versions of Firefox, Chrome, and Safari don't support the CSS declaration page-break-inside: avoid;, but you can achieve the same effect with display: inline-block;, if needed.

Related

How to use Aural CSS?

I've read one place that aural stylesheets are no longer in use? Is there something that has replaced them? I'm sure something is being used to make things easier for those who are visually impaired?
If aural CSS is in use still, is there a way to specify what should be said in a specific place, similar to using "alt" for images? For instance, I'm using an iconfont for my logo. I'd like to be able to have the user hear the name of my company, but because it's just done with a span, there's no place in that particular span that indicates the words (I'm assuming here that the system reads the words displayed on the screen, and not all the code with it, so obviously this works better if there's actual text to read). Maybe include a content: 'whatever text you want' is added somehow?
The gist is that I'm working on a site about opera for a client, and the client would like for the content to be accessible to everyone. And obviously someone with visual impairment is going to be especially wanting to hear things.
1. Is there a replacement for aural?
Aural stylesheets have indeed been deprecated as of CSS3. Major browsers such as Firefox removed the implementation a while ago. There is still a speech media included, but I haven't seen any implementations so far (it just seems to be a proposal at this point).
Many people with visual impairments use screen readers and to a lesser degree refreshable braille displays to view the content, so you usually don't have to worry about a direct implementation of speech. Important points for that to work are:
People have to be able to navigate through your content using the
tab key
All relevant rich content such as images etc. need to have a text equivalent.
Your html should be semantic (have a look at the aria attributes)
2. How can you make icon fonts (and other non-legible items) accessible?
In this article on bulletproof accessible font icons they propose a pretty good solution:
Since the characters don't have any direct semantic meaning, you could include them in the :before pseudoclass of your span:
.logo:before {
font-family: YourIconFontFamily;
content: "★";
}
And then include the company name directly in the span:
<span class="logo">Your company<span>
According to W3 it's defined in CSS 2 - but is already been deprecated with CSS3. You also can have a look at the Speech module: http://www.w3.org/TR/css3-speech
You can use another span with the specific content only for the screen reader which would look something like:
<span aria-hidden="true">Here could be your company name</span>
Source: http://www.456bereastreet.com/archive/201205/hiding_visible_content_from_screen_readers_with_aria-hidden/

CSS Best Practices for Large Scale Web Site

So far, my experience in web design has been with very small scale sites and blogs (where there isn't much diversity in page styling). However, I am now beginning to tackle some significantly larger scale web sites and I want to start off on the right foot by creating a scalable and maintainable css file / structure.
Currently, my method for applying styles to web pages is to give every web page a distinct ID in the body, and then when I'm designing a page my css rule will look like this:
body#news section .top { rules }
Surely there is a more maintainable approach to applying CSS for a large-scale web site?
Avoid giving each page a body tag with a unique ID. Why? Because if a page needs to be styled uniquely, it should have its own stylesheet.
I will often have a main.css stylesheet, stylesheets for various similar portions of my website (like an administration.css for an admin section, assuming the pages in the admin section shared a similar look and feel), and then give certain unique pages their own stylesheets (like signup.css).
I then include the stylesheets in order from least-to-most specific, because if two otherwise-identical rules are encountered, the rule in the most "recently" included stylesheet will be used.
For example, if my main.css had:
a { color: red; }
... and for some reason, I wanted my signup page to have blue links:
a { color: blue; }
The second rule will overwrite the first if my signup.css were included after main.css.
<link rel="stylesheet" href="/stylesheets/main.css">
<link rel="stylesheet" href="/stylesheets/signup.css">
there is a very informative and detailed answer over here: Managing CSS Explosion
you could also check out object oriented css: http://www.slideshare.net/stubbornella/object-oriented-css
or css systems: http://www.slideshare.net/nataliedowne/css-systems-presentation
To sum up the above answers and give some additional comments:
You put everything in one CSS, and use unique body IDs for page-specific settings. This approach speeds up your site because you're saving HTTP requests (browser caches just one file)
You have one CSS per page, plus one global one to take care of global settings, header, footer and any other elements that appear everywhere. This is friendlier if you have more than one developer working - less chance of conflicts because of updates to the same file. Even if you use a versioning system like SVN (and with a big site you should), it's always safer to have different files.
You can have the best of both worlds by separating into files, and then using a minifier to merge and compress all of them into one "compiled" CSS. This is more complicated, you need to fit it into your workflow, and it makes frontend debugging harder. See Any recommendations for a CSS minifier?.
What you should find is that most pages will have similar design aspects like typography and basic formatting which means you dont need to apply and id to the body tag.
You should try and use ids that describe the structure of your page (header, footer, sidebar etc) which can be reused on each page where neccessary. Only when styling areas specific to news or project etc is when you should start using id=news.
At the end of the day there is no right and wrong answer. Just try to maintain resuable css styles whilst trying not to overload your markup with uneccessary tags.
Always use classes for CSS. This will allow you to reuse more of your code. Since you can have multiple duplicate classes per page this allows you to really create some small code.
CSS parses from right to left. So in the example above it will find your selector in this order:
elements with the classname .top
elements with the classname .top that are in the section tag
elements with the classname .top that are in a section tag also contained in the #news element
...etc.
Look at it this way you should really try to keep your selectors as short as possible. Create a base style for .top, then if you need to write something custom for the #news section you can use #news .top.
Always try to use the shortest possible rules.
margin:0 5px;
over
margin:0 5px 0 5px;
It's basic, but you'd be amazed at how many people don't do this.
Also learn what you can shorted:
ex: font:bold 12px Helvetica, Arial, sans-serif;
One thing that is very helpful is if you alphabetize your rules. Especially if you are using CSS3 -webkit- and -moz- properties. I get a lot of push back on this one, but I work with 12+ developers and I've seen
.myClass { color:#f00; /* more stuff */ color:#fff; }
If they are alphabetical then you'll avoid code duplication.

What's so bad about in-line CSS?

When I see website starter code and examples, the CSS is always in a separate file, named something like "main.css", "default.css", or "Site.css". However, when I'm coding up a page, I'm often tempted to throw the CSS in-line with a DOM element, such as by setting "float: right" on an image. I get the feeling that this is "bad coding", since it's so rarely done in examples.
I understand that if the style will be applied to multiple objects, it's wise to follow "Don't Repeat Yourself" (DRY) and assign it to a CSS class to be referenced by each element. However, if I won't be repeating the CSS on another element, why not in-line the CSS as I write the HTML?
The question: Is using in-line CSS considered bad, even if it will only be used on that element? If so, why?
Example (is this bad?):
<img src="myimage.gif" style="float:right" />
Having to change 100 lines of code when you want to make the site look different. That may not apply in your example, but if you're using inline css for things like
<div style ="font-size:larger; text-align:center; font-weight:bold">
on each page to denote a page header, it would be a lot easier to maintain as
<div class="pageheader">
if the pageheader is defined in a single stylesheet so that if you want to change how a page header looks across the entire site, you change the css in one place.
However, I'll be a heretic and say that in your example, I see no problem. You're targeting the behavior of a single image, which probably has to look right on a single page, so putting the actual css in a stylesheet would probably be overkill.
The advantage for having a different css file are
Easy to maintain your html page
Change to the Look and feel will be easy and you can have support for many themes on your pages.
Your css file will be cached on the browser side. So you will contribute a little on internet traffic by not loading some kbs of data every time a the page is refreshed or user navigates your site.
The html5 approach to fast css prototyping
or: <style> tags are no longer just for the head any more!
Hacking CSS
Let's say you're debugging, and want to modify your page-css, make a certain section only look better. Instead of creating your styles inline the quick and dirty and un-maintainable way, you can do what I do these days and take a staged approach.
No inline style attribute
Never create your css inline, by which I mean: <element style='color:red'> or even <img style='float:right'> It's very convenient, but doesn't reflect actual selector specificity in a real css file later, and if you keep it, you'll regret the maintenance load later.
Prototype with <style> instead
Where you would have used inline css, instead use in-page <style> elements. Try that out! It works fine in all browsers, so is great for testing, yet allows you to gracefully move such css out to your global css files whenever you want/need to! ( *just be aware that the selectors will only have page-level specificity, instead of site-level specificity, so be wary of being too general) Just as clean as in your css files:
<style>
.avatar-image{
float:right
}
.faq .warning{
color:crimson;
}
p{
border-left:thin medium blue;
// this general of a selector would be very bad, though.
// so be aware of what'll happen to general selectors if they go
// global
}
</style>
Refactoring other people's inline css
Sometimes you're not even the problem, and you're dealing with someone else's inline css, and you have to refactor it. This is another great use for the <style> in page, so that you can directly strip the inline css and immediate place it right on the page in classes or ids or selectors while you're refactoring. If you are careful enough with your selectors as you go, you can then move the final result to the global css file at the end with just a copy & paste.
It's a little hard to transfer every bit of css immediately to the global css file, but with in-page <style> elements, we now have alternatives.
In addition to other answers.... Internationalization.
Depending of the language of the content - you often need to adapt the styling of an element.
One obvious example would be right-to-left languages.
Let's say you used your code:
<img src="myimage.gif" style="float:right" />
Now say you want your website to support rtl languages - you would need:
<img src="myimage.gif" style="float:left" />
So now, if you want to support both languages, there's no way to assign a value to float using inline styling.
With CSS this is easily taken care of with the lang attribute
So you could do something like this:
img {
float:right;
}
html[lang="he"] img { /* Hebrew. or.. lang="ar" for Arabic etc */
float:left;
}
Demo
Inline CSS will always, always win in precedence over any linked-stylesheet CSS. This can cause enormous headache for you if and when you go and write a proper cascading stylesheet, and your properties aren't applying correctly.
It also hurts your application semantically: CSS is about separating presentation from markup. When you tangle the two together, things get much more difficult to understand and maintain. It's a similar principle as separating database code from your controller code on the server side of things.
Finally, imagine that you have 20 of those image tags. What happens when you decide that they should be floated left?
This only applies to handwritten code. If you generate code, I think that it's okay to use inline styles here and then, especially in cases where elements and controls need special treatment.
DRY is a good concept for handwritten code, but in machine-generated code, I opt for "Law of Demeter": "What belongs together, must stay together". It's easier to manipulate code that generates Style tags than to edit a global style a second time in a different and "remote" CSS file.
The answer to your question: it depends...
Using inline CSS is much harder to maintain.
For every property you want to change, using inline CSS requires you to look for the corresponding HTML code, instead of just looking inside clearly-defined and hopefully well-structured CSS files.
The whole point of CSS is to separate content from its presentation. So in your example you are mixing content with presentation and this may be "considered harmful".
In addition to the other answers, another concern is that it violates the recommended Content Security Policy from MDN, https://infosec.mozilla.org/guidelines/web_security#content-security-policy
The justification they use is that inline javascript is harmful, XSS, etc., but it doesn't justify why inline styles should also be disabled. Maybe someone can comment as to why, but until then, I'll just rely on appeal-to-authority and claim: it's a security best practice to avoid inline styles.
Code how you like to code, but if you are passing it on to someone else it is best to use what everyone else does. There are reasons for CSS, then there are reasons for inline. I use both, because it is just easier for me. Using CSS is wonderful when you have a lot of the same repetition. However, when you have a bunch of different elements with different properties then that becomes a problem. One instance for me is when I am positioning elements on a page. Each element as a different top and left property. If I put that all in a CSS that would really annoy the mess out of me going between the html and css page. So CSS is great when you want everything to have the same font, color, hover effect, etc. But when everything has a different position adding a CSS instance for each element can really be a pain. That is just my opinion though. CSS really has great relevance in larger applications when your having to dig through code. Use Mozilla web developer plugin and it will help you find the elements IDs and Classes.
I think that even if you want to have a certain style for one element, you have to consider the possibility that you may want to apply the same style on the same element on different pages.
One day somebody may ask to change or add more stylistic changes to the same element on every page. If you had the styles defined in an external CSS file, you would only have to make changes there, and it would be reflected in the same element in all of the pages, thus saving you a headache. :-)
Even if you only use the style once as in this example you've still mixed CONTENT and DESIGN. Lookup "Separation of concerns".
Using inline styles violates the Separation of Concerns principle, as you are effectively mixing markup and style in the same source file. It also, in most cases, violates the DRY (Don't Repeat Yourself) principle since they are only applicable to a single element, whereas a class can be applied to several of them (and even be extended through the magic of CSS rules!).
Furthermore, judicious use of classes is beneficial if your site contains scripting. For example, several popular JavaScript libs such as JQuery depend heavily on classes as selectors.
Finally, using classes adds additional clarity to your DOM, since you effectively have descriptors telling you what kind of element a given node in it is. For example:
<div class="header-row">It's a row!</div>
Is a lot more expressive than:
<div style="height: 80px; width: 100%;">It's...something?</div>
Inline CSS is good for machine-generated code, and can be fine when most visitors only browse one page on a site, but one thing it can't do is handle media queries to allow different looks for screens of different sizes. For that, you need to include the CSS either in an external style sheet or in an internal style tag.
In-page css is the in-thing at the moment because Google rates it as giving a better user experience than css loaded from a separate file. A possible solution is to put the css in a text file, load it on the fly with php, and output it into the document head. In the <head> section include this:
<head> ...
<?php
$codestring = file_get_contents("styles/style1.txt");
echo "<style>" . $codestring . "</style>";
?>
... </head>
Put the required css in styles/style1.txt and it'll get spat out in the <head> section of your document. This way, you'll have in-page css with the benefit of using a style template, style1.txt, which can be shared by any and all pages, allowing site-wide style changes to be made via only that one file. Furthermore, this method doesn't require the browser to request separate css files from the server (thus minimising retrieval / rendering time), since everything is delivered at once by php.
Having implemented this, individual one-time-only styles can be manually coded where needed.
According to the AMP HTML Specification it is necessary to put CSS in your HTML file (vs an external stylesheet) for performance purposes. This does not mean inline CSS but they do specify no external stylesheets.
An incomplete list of optimizations such a serving system might do is:
Replace image references with images sized to the viewer’s viewport.
Inline images that are visible above the fold.
Inline CSS variables.
Preload extended components.
Minify HTML and CSS.
Personally, I think the hatred of inline css is just ridiculous. Hardcore cult behaviour, people just sheepishly repeat "Separation of concerns!". Yes, there are times where if there is a repeating element and you will need repeated styling to use a class targeted from a CSS file, but most of the time it improves speed of development and CLARITY OF CODE to put the style inline, it's great if I can look at the code and see that there is a custom margin height, it helps me picture the HTML document as a whole, instead of some named class that gives me little insight into which styles will be applied.
So I will be the contrarian here and say that inline css is great and that people who scream at you for using it are just following what they have been told without actually giving it any original unbiased consideration.
Even though I totally agree with all the answers given above that writing CSS in a separate file is always better from code reusability, maintainability, better separation of concerns there are many scenarios where people prefer inline CSS in their production code -
The external CSS file causes one extra HTTP call to browser and thus additional latency. Instead if the CSS is inserted inline then browser can start parsing it right away. Especially over SSL HTTP calls are more costly and adds up additional latency to the page. There are many tools available that helps to generate static HTML pages (or page snippet) by inserting external CSS files as inline code. These tools are used at the Build and Release phase where the production binary is generated. This way we get all the advantages of external CSS and also the page becomes faster.
In addition to other answers, you cant target the pseudo-classes or pseudo-elements in inline CSS
We have created a template-driven artifact generator that provides an include file capability for any kind of text artifact -- HTML, XML, computer languages, unstructured text, DSV, etc. (E.g., it's great for handling common Web or manual page headers and footers without scripting.)
Once you have that and use it to provide "style" tags inside your "head" tag, the "separation of concerns" argument goes away, to be replaced by "we have to regenerate after every change to the template" and "we have to debug the template from what it generates". Those gripes have been around since the first computer language to get a preprocessor (or someone started using M4).
On balance, we think the meta-izing capability of either a CSS file or "style" tags is cleaner and less error-prone than element-level styling. But it does require some professional judgment, so newbies and scatterbrains don't bother.

How are the page-break properties in CSS supposed to work?

Modern browsers are supposed to support the CSS page-break properties to some degree. However I haven't been able to get any browser to print any differently when I use avoid, widows, or orphans. Am I doing it wrong, or is the browser support just not as solid as advertised?
h2 {
page-break-after: avoid;
}
p {
page-break-inside: avoid;
orphans: 2;
widows: 2;
}
Browser support for printing sucks. Not just a little bit, but completely totally and without compare. About once every other year (for the past 10), I've played around with this and I always come back to the same conclusion: don't depend on the browser to be able to handle good printing.
If it absolutely must be positioned correctly, create a pdf file on the fly and let the user print that.
If you are wanting to do a page break I know that this is the way it works at least in Firefox and IE. Last time I checked this worked in IE7.
Page 1
<br style="page-break-after:always" />
Page 2
It should print the pages on separate pieces of paper, totally depending on the browser.
I know this will go against everything everyone says about html development, but use tables. Put content that needs to stay together into a table, and then the page will not be split in the middle of the table. If the table is longer than one page, then it will be split somewhere in the middle of the table, but using tables is a good way to keep content together when printing.

How to split a string (e.g. a long URL) in a table cell using CSS?

Here's the situation: I'm trying my hand at some MySpace page customisations. If you've ever tried [stackoverflow], I'm sure you understand how frustrating it can be.
Basically it can be all customised via CSS, within a certain set of rules (e.g. the '#' character is not allowed...how useful!).
Have a look at this blog if you want more info, I used it as the basis for my customisations
So the only problem is with the comments section, where 'friends' post whatever they feel like.
It already has...
max-width:423px;
...set on the table, but I've discovered if long URLs are posted in the comment section, it blows out the table width, regardless of the max setting!
Question: Is there a way to manage text that is going to push the width of the table?
Perhaps splitting/chopping the string? Or is there more I should be doing..?
The URLs are posted as text, not hrefs.
Using Firefox and Firebug btw.
Edit: Also javascript is not allowed ;)
Another edit Just checked with IE7, and it seems to work.. so firefox is being the hassle in this case..
Have you tried the various values for the "overflow" css property? I think that may do what you need in some permutation.
a few browsers support word-wrap
ex.
<div style="width: 50px; word-wrap: break-word">insertsuperlongwordhereplease</div>
browser support currently is IE / Safari / Firefox 3.1 (Alpha)
Your options are pretty limited, if you are using only CSS. You can try
overflow: hidden
to hide the offending parts. CSS 3 supports text-wrap, but support for it is probably non-existent. IIRC there is an IE-only css-property for doing the same thing, but I can't remember it at the moment and my Google-Fu fails me.

Resources