Specify hairline thickness in CSS for printing
Asked Answered
C

8

20

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

Cacology answered 2/4, 2012 at 14:33 Comment(2)
Have you tried various browser clients?Guidry
See below: 3 ways to draw hairlines with CSS3 or SVG.Heartbeat
C
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.

Cacology answered 4/4, 2012 at 8:25 Comment(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.Rossman
H
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.

Heartbeat answered 18/11, 2015 at 15:40 Comment(0)
T
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.

Threadgill answered 2/4, 2012 at 14:40 Comment(0)
C
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.

Chromolithograph answered 29/5, 2012 at 7:47 Comment(2)
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!Cacology
This worked great for me when using WKHTMLTOPDF, thanks!Todhunter
D
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.

Diluvial answered 21/4, 2015 at 17:56 Comment(6)
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)Gastrocnemius
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?Gastrocnemius
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.Diluvial
That's why I set the borders to zero in my example.Gastrocnemius
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.Diluvial
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.Gastrocnemius
G
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.

Gastrocnemius answered 22/11, 2013 at 17:34 Comment(3)
Of course this doesn’t help the average visitor to a website, but it’s useful to know nonetheless for people like us. Thanks!Cacology
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. ;-)Gastrocnemius
Thank you for your answer and have a look at my answer with an addition to it.Diluvial
B
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.

Bela answered 6/1, 2022 at 23:9 Comment(0)
P
0

I have solution for non-overlapping borders: box-shadow with inset property:

box-shadow: inset 0 0 1px #000;

you can use #333, #999 or #ccc instead of black to fine tune border 'width'

Princess answered 19/12, 2023 at 11:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.