19

If I have a print CSS styling an element with:

border:1px solid black;

or:

border:0.25pt solid black;

The line is very thick when it prints – at least 1pt. If I try a much smaller value, such as 0.05pt, the line doesn't appear at all. How can I get a thin line? In programs like InDesign you set the thickness to 0.25pt for a 'hairline', i.e. a very thin line but not so thin that it won't be printable.

Note: this question seems to ask the same thing, but nobody has addressed the actual issue of the line thickness, merely the best units of measure to use: pt or px for specifying border-width for print

Community
  • 1
  • 1
user535673
  • 908
  • 1
  • 9
  • 13

7 Answers7

13

Thanks for your help. It would seem that browsers are just useless in this respect.

I've done some more testing and the conclusion seems to be:

  • No browser is any good at printing point sizes.
  • You can't assume users will see a width less than 1.25pt on a prinout.

I tested variations of the following web page, adjusting the border point size each time. I printed with 'fit to page' turned off.

<html>
  <body style="width:17cm; background-color:rgb(245,245,245);">
    <div style="border:0.3pt solid black; width:100%; height:20cm">IE 0.3pt</div>
  </body>
</html>

These are the results of the minimum printable point size and what it looks like compared to a printout of lines from InDesign. I've included a few other notes, too:

FF: 0.25pt, looks like 1.25pt. DIV width looks like it is 17cm, but because of FF's massive print margins the right-hand border gets cut off. It seems 16.5cm is the largest usable width. The BODY height fits the height of the page.

Safari 5: 0.75pt, looks like 1pt. DIV width is 18.2cm and BODY width is 19.5cm - Safari appears to be fitting to page even though there's no indication that it would do this. The BODY height finishes shortly after the DIV height.

Opera 11: 0.4pt, looks like 0.75pt. DIV width is 16.2cm and the BODY background only appears within the div - although the line of text, appears on a white background

IE7: 0.4pt, looks like 0.5pt (as does 0.5pt). As with FF, DIV width looks like it is 17cm, but because of IE's massive print margins the right-hand border gets cut off.

IE9: 0.1 works (and possibly lower), but still looks like 0.5pt. Otherwise same as IE7.

user535673
  • 908
  • 1
  • 9
  • 13
  • 1
    Chrome printing seems to print lines that are visible on the screen and hide lines that are not visible on screen. In other words it emulates what is on the monitor when you print. – brentonstrine Nov 27 '12 at 20:10
12

Nowadays, in 2015, there are a few workarounds to produce hairlines with HTML5 and CSS3, e.g. for printing or on high res screens:

  1. SVG (i.e., by assigning a path stroke-width: .5)
  2. linear gradient backgrounds
  3. 2D transforms: scaling

The scaling approach is described in detail in this article. It boils down to this:

hr.thin {
    height: 1px;
    border-top: none;
    border-bottom: 1px solid black;
    transform: scaleY(0.33);
}

The linear gradient method works along these lines (pun intended, in detail here):

hr.hairline {
    height: 1px;
    background: linear-gradient(
        transparent 0%, 
        transparent 50%, 
        black 50%, 
        black 100%);
}

To simplify things, I have used a 1px <hr> element as an example. But by scaling all styles within an element, or with multiple backgrounds respectively, both solutions may be expanded to work as a border on all four sides of an element.

Avant la lettre
  • 351
  • 3
  • 13
4

Problem might be in browser rescaling the page (at least IE used to do it when printing), but as I tested it now in Opera (no rescale), line still isn't really thin as hairline. However, I am always using this to achieve thin border effect:

p {
  border: 0.4pt solid #CCC;
}

This will create very light gray border. As Barry Kaye has proposed, you can also make it dotted to look thinner.

FurloSK
  • 441
  • 2
  • 14
  • The browser shouldn't scale anything when set to print at 100% but in reality, you are correct – e.g. if you define a 10cm box and print it out, it's rarely actually 10cm. That would be too simple! – user535673 May 29 '12 at 21:31
  • This worked great for me when using WKHTMLTOPDF, thanks! – Steve Bauman Jan 30 '19 at 15:55
4

I have found using a thickness of dotted instead of solid has helped in some print scenarios and renders as more of a thinner (hair) line than dots.

Barry Kaye
  • 7,682
  • 6
  • 42
  • 64
2

I found B.Martin's answer most useful. Here's what I can add to it:

Theory

Physically the width of a hair (hairwidth) is between 17 and 181 microns. That is 0.02 to 0.2 mm or 0.05 to 0.5 pt.

So making lines narrower than 0.1pt doesn't make much sense since eye might not see them.

CorelDraw's hairline is 0.23pt or 81 micron.

Practice

In fact, wkhtmltopdf tool is handy for creating thin lines. I've managed to acheive the following widths:

  • 0.1pt with zoom factor of 8
  • 0.2pt with zoom factor of 4 (which is more practical since a4 is zoomed to a common size a0 in this case)

I didn't measure the real width of the line but it looks pretty much the same as 'hairline' of my CorelDraw.

NB Changing the width from 0.1pt to 0.15pt (zoom=8) or from 0.2pt to 0.3pt (zoom=4) doesn't change the resulting line width, at least visually.

So, what I've come with is:

wkhtmltopdf -s A0 --zoom 4 <input filename> <output filename>

gives a pretty A0-sized page which can be automatically scaled back to A4 when printing - no hairwidth lines are lost on this stage as well.

Update: I've finally managed to measure it using an Acrobat plugin: original 0.3pt line after -s A0 --zoom 4 becomes 0.6pt on a0 (that is 0.15pt after downsizing) which is quite enough of a hairline for me.

Antony Hatchkins
  • 31,947
  • 10
  • 111
  • 111
  • My guess is that `wkhtmltopdf` rounds the widths. So if you use a scaling factor of 8 and a width of 0.1pt then you effectively have a width of 0.8pt which is most likely scaled to 1pt. That would explain why the different widths you mentioned give the same output. (0.1*8=0.8pt ~ 1pt and 0.15*8=1.2pt ~ 1pt) – B. Martin Apr 21 '15 at 18:18
  • I don't understand why you don't use `-s A4` to scale it back to A4 paper size. Does that have any advantage that I didn't see? – B. Martin Apr 21 '15 at 18:21
  • Well, I have a full-page drawing so if I use `-s A4` it generates 3 pages for me, all of them truncated on the right side. – Antony Hatchkins Apr 21 '15 at 18:42
  • That's why I set the borders to zero in my example. – B. Martin Apr 21 '15 at 19:20
  • I'm not really sure why you set the borders to zero in your example, but it doesn't make much difference for me. It gives me 2 truncated pages instead of 3, that's all. – Antony Hatchkins Apr 23 '15 at 17:20
  • The text on the invoices I create have to be very precisely positioned. It's very hard to achieve that when whole output is scaled. In addition to that I need to create borderless PDFs. By setting the margings to zero you can do all the positioning with css. In the beginning I had the problem as well that it produced 2 pages instead of one. Howevever you can achieve perfect positioning with the right css formating. – B. Martin Apr 23 '15 at 17:59
1

I suggest to use a tool which converts the HTML document to a PDF first. Then you can print the PDF and get consistent results. Wkhtmltopdf is very good for that because it's based on the most standard compliant web rendering engine.

When using wkhtmltopdf you can set the zoom to a value above 1 to get thinner lines. Set the line width to something like 0.25pt and use the following command.

wkhtmltopdf -T 0 -B 0 -L 0 -R 0 -s A4 --zoom 10 <URL> <output filename>

Now you get really thin lines. When you specify a higher zoom value the rendering is more precise and looks therefore slightly different.

To get the best results use the following units: mm, cm and pt instead of px.

B. Martin
  • 1,047
  • 12
  • 18
  • Of course this doesn’t help the average visitor to a website, but it’s useful to know nonetheless for people like us. Thanks! – user535673 Nov 25 '13 at 09:37
  • I added this because I don't think that the average user worries about whether a line is 1pt or 0.25pt think. I think this thread is for web developers. I believe the only solution to get consistent results for all visitors is to offer a PDF version of a website. ;-) – B. Martin Nov 25 '13 at 17:53
  • Thank you for your answer and have a look at my answer with an addition to it. – Antony Hatchkins Apr 21 '15 at 17:57
0

I came up with a clever and somewhat clunky hack using pseudo elements and scaling. It has worked for everything so far and can easily be modified (border-top, border-left...). It can for example be used as a class, because it's height/width is not hardcoded. Here is an example:

.thinborders {
  /* not needed */
  width: 300px;height: 300px;margin: 50px;padding: 15px;background-color: #ccc;

  /* very important */
  transform: scale(1); /* position: relative; might also work, but not on all elements */
}

.thinborders::before {
  content: "";
  
  position: absolute;
  width: 800%;
  height: 800%;
  top: 0;
  left: 0;
  
  /* change  */
  --border-width: 0.5px;
  
  /* can be border-bottom or anything else */
  border: calc(8 * var(--border-width)) solid black;
  
  transform: scale(12.5%);
  transform-origin: left top;
  
  box-sizing: border-box;
}
<div class="thinborders">
  i have thin borders
</div>

This can obviously be made into a sass/less mixin or something other fancy.

THIS DOESN'T WORK IN FIREFOX. I have only tested it in Chrome.

drstuggels
  • 122
  • 2
  • 12