podcaster cover

Syntax

The Surprisingly Exciting World of Print + PDF CSS

Oct 29
podcaster logo

Podcast Segments

  • [0:00.000 - 0:01.000]: Monday.
  • [0:01.000 - 0:02.000]: Monday.
  • [0:02.000 - 0:03.000]: Monday.
  • [0:03.000 - 0:04.000]: Open wide, dev fans.
  • [0:04.000 - 0:10.359]: Get ready to stuff your face with JavaScript, CSS, Node modules, barbecue tips, get workflows,
  • [0:10.359 - 0:15.760]: breakdancing, soft skills, web development, the hastiest, the craziest, the tastiest web
  • [0:15.760 - 0:17.399]: development treats.
  • [0:17.399 - 0:24.159]: Coming in hot, here is Wes, Barracuda, Boss, and Scott, el Toro Loco.
  • [0:24.159 - 0:25.159]: Tolinsky.
  • [0:25.159 - 0:28.840]: Welcome to Syntax.
  • [0:28.840 - 0:34.759]: We're going to be hitting the command P button and printing this episode of Syntax because
  • [0:34.759 - 0:38.720]: we're going to be talking all about print and PDF CSS.
  • [0:38.720 - 0:44.279]: The type of CSS that you may have written at some point for when your users need to
  • [0:44.279 - 0:45.840]: print out a website.
  • [0:45.840 - 0:48.159]: Seriously, who prints anything these days?
  • [0:48.159 - 0:51.720]: But I think there's a lot of really great use cases and a lot of really interesting
  • [0:51.720 - 0:57.520]: stuff around print CSS, a feature that's been part of CSS for quite a while here.
  • [0:57.520 - 0:58.799]: My name is Scott Tolinsky.
  • [0:58.799 - 1:00.639]: I'm a developer from Denver.
  • [1:00.639 - 1:02.439]: With me as always is Wes Boss.
  • [1:02.439 - 1:03.439]: What's up, Wes?
  • [1:03.439 - 1:04.440]: Hey.
  • [1:04.440 - 1:08.879]: Print CSS, surprisingly interesting.
  • [1:08.879 - 1:15.160]: And it's part of CSS that probably most developers have not had to touch because like you think,
  • [1:15.160 - 1:18.080]: all right, who prints a page anymore?
  • [1:18.080 - 1:24.000]: But I want to go through just a couple quick examples to sort of set the mood as to what
  • [1:24.000 - 1:26.959]: you might want to use print CSS for.
  • [1:27.120 - 1:33.519]: Yeah, before we set that mood, hey, maybe you're getting into trying to export a page
  • [1:33.519 - 1:37.480]: as a PDF with JavaScript and you're finding out how much fun that is.
  • [1:37.480 - 1:39.959]: Well, you're going to be hitting some bugs.
  • [1:39.959 - 1:43.440]: And to make sure that those bugs are captured, you're going to want to go ahead and check
  • [1:43.440 - 1:45.720]: out sentry at sentry.io.
  • [1:45.720 - 1:51.239]: This podcast is presented by Sentry and we're a proud part of Sentry.
  • [1:51.239 - 1:54.239]: So check it out if you have any bugs in your app.
  • [1:54.239 - 1:55.800]: All right, mood.
  • [1:55.800 - 1:56.800]: Good setting time.
  • [1:56.800 - 1:57.800]: Let's go.
  • [1:57.800 - 1:58.800]: All right.
  • [1:58.800 - 2:03.760]: A couple examples of when I've used print CSS as well as a couple bonus ones.
  • [2:03.760 - 2:11.000]: So when I do my sticker shipping, so every year, year and a half, I print 10,000 packs
  • [2:11.000 - 2:14.080]: of stickers and I mail them out via letters.
  • [2:14.080 - 2:20.520]: And in order to do that, I have all of the sales in my database and I need to automate
  • [2:20.520 - 2:23.199]: the generation of all the envelopes.
  • [2:23.199 - 2:27.039]: So it's got the receiver address, has the sender return address.
  • [2:27.039 - 2:32.360]: And then on the front of that envelope, it also has information about how many stickers
  • [2:32.360 - 2:34.800]: need to go in it, like how many did they buy.
  • [2:34.800 - 2:38.600]: So I'll put like a little three in the corner if they ordered three packs.
  • [2:38.600 - 2:41.279]: And that as well as like how many stamps need to be applied.
  • [2:41.279 - 2:48.679]: So in the top right hand corner, it'll say like one CA, one Canadian stamp or two international
  • [2:48.679 - 2:51.360]: stamps or three USA stamps.
  • [2:51.520 - 2:55.320]: That just sort of helps me in the process of actually mailing them.
  • [2:55.320 - 2:57.679]: So being able to automate that.
  • [2:57.679 - 3:03.880]: The other one, when I did t-shirts, I was printing out everything on a four by six inch
  • [3:03.880 - 3:05.520]: thermal label printer.
  • [3:05.520 - 3:11.199]: And each order had both a label that you actually used to ship, right?
  • [3:11.199 - 3:13.160]: USPS, FedEx, whatever.
  • [3:13.160 - 3:16.479]: But you also needed a packing list.
  • [3:16.479 - 3:20.039]: So often you'll get like a when you order something online, you'll get like a packing
  • [3:20.039 - 3:21.039]: list.
  • [3:21.720 - 3:27.039]: It's just a sticker, you know, like why, why is the what goes in my thing a sticker?
  • [3:27.039 - 3:30.559]: And the reason is, is because they needed to print those two things.
  • [3:30.559 - 3:34.800]: Somebody tears it off and the picker goes and they put the label on the box, but then
  • [3:34.800 - 3:41.320]: they also say, all right, well, this person needs a medium t-shirt that is the black color.
  • [3:41.320 - 3:43.360]: So I've used that quite a bit.
  • [3:43.360 - 3:44.360]: Yeah.
  • [3:44.360 - 3:45.360]: Here's one that I've done.
  • [3:45.360 - 3:46.360]: Level up tutorial site.
  • [3:46.360 - 3:49.639]: We had invoices and receipts.
  • [3:49.639 - 3:53.520]: You know, you did a one-off purchase or you did a subscription.
  • [3:53.520 - 3:57.960]: Oftentimes these receipts need to be either saved as a PDF or heaven forbid, they do need
  • [3:57.960 - 4:01.880]: to be printed out for some, uh, some companies to be able to submit them.
  • [4:01.880 - 4:07.320]: We had a lot of people who, as you very well know, Wes, they get to buy tech courses on
  • [4:07.320 - 4:09.759]: a tech stipend or something like that.
  • [4:09.759 - 4:13.100]: This allows them to submit those receipts at the end of the year, which is very funny
  • [4:13.100 - 4:17.959]: as an entrepreneur type of person or somebody who always worked in smaller agencies, I never
  • [4:17.959 - 4:21.420]: had to deal with the receipts until starting to work at Century.
  • [4:21.420 - 4:26.440]: And now you would not believe how thankful I am when somebody makes the receipt process
  • [4:26.440 - 4:32.519]: nice and easy and I can, you know, we have a generated CSS receipt, save as, you know,
  • [4:32.519 - 4:35.920]: print as a PDF or any of that stuff makes my life so much better.
  • [4:35.920 - 4:37.519]: So yeah, much needed.
  • [4:37.519 - 4:45.320]: I have such a hate for, cause I have to do all my expenses and I have to, I've used probably
  • [4:45.320 - 4:50.760]: a hundred different services and they're like receipt workflow.
  • [4:50.760 - 4:54.279]: And I have so many like qualms about how, how they do that.
  • [4:54.279 - 4:58.119]: And at the end I'll have a couple of tips that will make it easier on your users because
  • [4:58.119 - 5:02.600]: you don't think about these little like printing a receipt, you know, like that's like the
  • [5:02.600 - 5:05.920]: last part of your app that you really want to spend any time on.
  • [5:05.920 - 5:08.640]: But man, when people do a good, it is good.
  • [5:08.640 - 5:09.640]: Yeah, totally.
  • [5:09.640 - 5:15.059]: When I wrote my, my book on sublime text many years ago I laid out the entire book
  • [5:15.059 - 5:21.359]: and it was, I never actually printed it as a physical book, but I did deliver it as a
  • [5:21.359 - 5:26.279]: PDF and all of the print CSS also applies to, to PDF.
  • [5:26.279 - 5:29.559]: So that's probably where I wrote the most of my print CSS.
  • [5:29.559 - 5:34.619]: And then other things I asked on Twitter, what people were doing Amazon print return
  • [5:34.619 - 5:38.119]: labels need to be on a single page.
  • [5:38.119 - 5:43.839]: Maybe sites are a big one that people still print out, um, workout sheets, uh, all kinds
  • [5:43.839 - 5:46.679]: of interesting stuff, but let's get into actually how to use it.
  • [5:46.679 - 5:52.399]: So first one, you probably know this, how do you load CSS that is only applied when
  • [5:52.399 - 5:53.399]: printing?
  • [5:53.399 - 5:56.359]: Well, either link it with a media.
  • [5:56.359 - 6:02.200]: So you link up a CSS file that is entirely print CSS, and then you put an attribute on
  • [6:02.200 - 6:07.200]: the link tag, which is media equals print, and that will only be applied.
  • [6:07.279 - 6:08.279]: I looked this up.
  • [6:08.279 - 6:12.480]: It'll only be requested when your user is printing it as well.
  • [6:12.480 - 6:16.880]: So you don't have to think, Oh, that's an extra thing to download when I don't even
  • [6:16.880 - 6:17.880]: need it.
  • [6:17.880 - 6:21.019]: It's not downloaded unless the user actually needs it.
  • [6:21.019 - 6:25.959]: The other way is you can include it in your existing CSS with a media query, right?
  • [6:25.959 - 6:29.480]: Media queries are not just for width and height of your viewport.
  • [6:29.480 - 6:33.700]: You can also use app media print and that CSS will only be applied when your user goes
  • [6:33.700 - 6:34.700]: to print.
  • [6:35.019 - 6:41.660]: There's also a really interesting at rule called the at page where it allows you to
  • [6:41.660 - 6:44.059]: modify aspects of the printed page.
  • [6:44.059 - 6:49.980]: So like what, what the size is, the margin, the padding, the border, um, page break after
  • [6:49.980 - 6:57.179]: always page break after before this basically chooses how you get to break onto a new page.
  • [6:57.179 - 7:02.720]: And like maybe you have something that should always be breaking out like a chapter, right?
  • [7:02.720 - 7:04.660]: You can think about like a book, right?
  • [7:05.619 - 7:08.059]: Are you outlining a book in CSS?
  • [7:08.059 - 7:13.500]: How many times have you been reading a book in the chapter two or chapter three, whatever
  • [7:13.500 - 7:15.779]: starts on the same page as the chapter ends?
  • [7:15.779 - 7:18.959]: It usually doesn't usually start something very next page.
  • [7:18.959 - 7:25.079]: So if you were to do something like, you know, at a chapter you could do page break before
  • [7:25.079 - 7:30.459]: always and then it will always start it on a new page, which is really handy if you're
  • [7:30.459 - 7:32.700]: again laying out anything like a book.
  • [7:32.739 - 7:35.059]: Now Wes, you know, it's funny.
  • [7:35.059 - 7:37.779]: Can you name the CSS at rules?
  • [7:37.779 - 7:39.859]: Like how many at rules do you think you could name?
  • [7:39.859 - 7:41.540]: What do you mean naming them?
  • [7:41.540 - 7:45.380]: Well, there's, there's a handful of different at rules in CSS.
  • [7:45.380 - 7:47.899]: I'm going to say, oh, can, oh, can I name them?
  • [7:47.899 - 7:51.100]: I thought you meant like, can you name print CSS rules?
  • [7:51.100 - 7:53.660]: It's funny because we all know at media, right?
  • [7:53.660 - 7:57.299]: But like how many, you might not think about at page very often.
  • [7:57.299 - 7:59.059]: So at layer at page.
  • [7:59.059 - 8:00.059]: Yeah.
  • [8:00.059 - 8:01.660]: Um, what are the other ones?
  • [8:01.660 - 8:02.660]: Yeah.
  • [8:02.660 - 8:03.660]: There's some interesting ones.
  • [8:03.660 - 8:05.619]: Well, maybe not that interesting at character set.
  • [8:05.619 - 8:15.179]: So you can set the encoding, um, at import is one that we know, um, there's at document,
  • [8:15.179 - 8:16.980]: which I don't know anything about at document.
  • [8:16.980 - 8:22.619]: Oh, the, the app page one is kind of interesting because when I was doing labels, um, I explicitly
  • [8:22.619 - 8:25.100]: needed them to be four by six.
  • [8:25.100 - 8:27.359]: So usually you don't size the page.
  • [8:27.359 - 8:31.640]: You let your users printer size it and you, you, you create it as fluid as possible.
  • [8:31.640 - 8:38.000]: However, when you are explicitly plant printing on a 10 envelopes or an eight and a half by
  • [8:38.000 - 8:43.159]: 11 sheet of paper, um, and you know that that's what it's going to be printed on or, or a
  • [8:43.159 - 8:48.479]: four by six label, that's where you go in CSS has inches for this purpose.
  • [8:48.479 - 8:54.080]: So I literally went in and said it was four inches by six inches and use the CSS size
  • [8:54.080 - 8:56.960]: property, not within height.
  • [8:56.960 - 9:02.159]: The break page break properties are also really interesting because, um, when I was
  • [9:02.159 - 9:08.479]: doing my book, I would have these like tips, you know, like, like little, um, Hey, did
  • [9:08.479 - 9:12.559]: you know, like this tiny little asides as you're going through it?
  • [9:12.559 - 9:16.419]: Um, or you might have a block quote as well when you're quoting someone.
  • [9:16.419 - 9:22.200]: And what I did with that is I would say, uh, block quote, anything that has a class of
  • [9:22.200 - 9:27.000]: tip on it, page break inside avoid or page break inside never.
  • [9:27.000 - 9:32.760]: Uh, and what that will do is it will say like, never start this on one page and break it
  • [9:32.760 - 9:36.039]: on and then continue on to the next page.
  • [9:36.039 - 9:43.760]: You should always snap on to the next full page, which is makes for much better layout.
  • [9:43.760 - 9:44.760]: Yeah.
  • [9:44.760 - 9:50.880]: Have you ever used, um, because I've done actual book laying out in as the InDesign,
  • [9:50.880 - 9:52.599]: have you ever used Adobe InDesign?
  • [9:52.599 - 9:53.599]: No, no, never.
  • [9:53.599 - 10:01.799]: Oh, oh, I have back when I used to do CD art, the layouts of the CD arts before they went
  • [10:01.799 - 10:04.080]: to print had to be layout and InDesign.
  • [10:04.080 - 10:08.159]: I would do it all in Photoshop and then I brought it into InDesign just for the print
  • [10:08.159 - 10:09.159]: setup.
  • [10:09.159 - 10:10.960]: You did all the bleed cut lines and everything.
  • [10:10.960 - 10:16.359]: I'm just, the reason why I bring this up is that like, I don't think most people know
  • [10:16.359 - 10:20.979]: that you can do such cool things like what you're referring to, like avoiding breaking
  • [10:20.979 - 10:26.320]: a block quote in CSS where like working in InDesign to lay out anything is a tremendous
  • [10:26.320 - 10:27.320]: pain in the butt.
  • [10:27.320 - 10:33.059]: I like wonder if, um, there's opportunities for people to do more laying out of this type
  • [10:33.059 - 10:39.400]: of thing with CSS just because it feels maybe like a bit of an, an unknown by the people
  • [10:39.400 - 10:40.719]: who would actually use it.
  • [10:40.719 - 10:41.719]: Right.
  • [10:41.719 - 10:42.719]: Yeah.
  • [10:42.719 - 10:45.479]: You can use, um, we'll talk about units and CSS.
  • [10:45.599 - 10:50.400]: You can use obviously pixels or rems, rems, and a majority of the times you don't have
  • [10:50.400 - 10:54.559]: to modify the sizes of things on your page.
  • [10:54.559 - 11:00.039]: However, if you are doing something that is explicitly for print CSS, like, like labels
  • [11:00.039 - 11:05.320]: or envelopes, something like that, you might want to use inches, millimeters, centimeters,
  • [11:05.320 - 11:11.559]: uh, points, Picas, which I've literally never in my life, uh, used a Pica, which is the
  • [11:11.559 - 11:13.880]: PC, um, or percentages.
  • [11:14.400 - 11:15.400]: Yeah.
  • [11:15.400 - 11:19.640]: I used to work at a design agency that was like just getting out of doing a lot of print.
  • [11:19.640 - 11:25.239]: And so we'd occasionally get designs using Picas, those types of things.
  • [11:25.239 - 11:29.479]: I'd be like, all right, I have to, uh, convert this myself now.
  • [11:29.479 - 11:34.080]: Uh, CSS counters are super handy for print CSS.
  • [11:34.080 - 11:36.640]: This is not part of print CSS.
  • [11:36.640 - 11:38.280]: It's part of regular CSS.
  • [11:38.280 - 11:40.760]: Have you ever used a CSS counter for anything?
  • [11:40.760 - 11:41.760]: No.
  • [11:42.159 - 11:48.320]: I'm seeing this code example and I'm feeling like, how have I, uh, how have I not used
  • [11:48.320 - 11:49.559]: CSS counters?
  • [11:49.559 - 11:56.400]: So CSS counters are really neat because you can count things in CSS and every single time
  • [11:56.400 - 12:02.760]: you have, uh, an instance of an element or instance of a selector, it will increment
  • [12:02.760 - 12:03.760]: it by one.
  • [12:03.760 - 12:10.799]: So, uh, CSS counter works where you reset the counter, um, and you give it a name.
  • [12:10.840 - 12:17.840]: So when I was doing my book, I would have a counter reset chapter, um, on the body and
  • [12:17.840 - 12:22.520]: that creates a counter scope for the entire book.
  • [12:22.520 - 12:30.039]: Um, and then what I did is every single time I had a H one tag, um, I, I said, all right,
  • [12:30.039 - 12:32.840]: my H ones are going to be a chapter.
  • [12:32.840 - 12:39.320]: Um, and like, you may, Oh, you should use an H two every, every chapter was an H one.
  • [12:39.919 - 12:43.559]: Um, it's being printed onto a page.
  • [12:43.559 - 12:49.960]: Uh, you, what you do there is you apply a counter increment property and every single
  • [12:49.960 - 12:55.039]: time that the Dom encounters an H one, it will increment that by one.
  • [12:55.039 - 13:02.119]: And then you can access those numbers, uh, via the counter function in CSS and you can
  • [13:02.119 - 13:09.359]: then inject them into the Dom via the, uh, content property of a before or after pseudo
  • [13:09.359 - 13:10.359]: element.
  • [13:10.359 - 13:14.200]: So what I was doing is I was just saying like chapter one, chapter two, and of course you
  • [13:14.200 - 13:20.200]: could do this in, in react, or if you were rendering out some sort of template, you probably
  • [13:20.200 - 13:29.000]: have those indexes, um, already for you, but it can be really handy just to automatically
  • [13:29.000 - 13:30.000]: do it.
  • [13:30.000 - 13:34.520]: Especially like when I was doing, um, like a table of contents work as well, or you might
  • [13:34.520 - 13:39.080]: want to reset them at certain specific times and same thing with subheadings.
  • [13:39.080 - 13:44.559]: So every single time I had an H one tag of a brand new chapter, I would create a new
  • [13:44.559 - 13:50.280]: scope of sub chapter and that would increment every H two H three.
  • [13:50.280 - 13:55.960]: Um, no, it would only increment every H two and that would be a sub chapter.
  • [13:55.960 - 13:59.200]: And then you can, you can go even further if you wanted to.
  • [13:59.200 - 14:03.320]: Then once you hit the next chapter, you reset the sub chapter count and keep going from
  • [14:03.320 - 14:04.320]: there.
  • [14:04.320 - 14:06.919]: So CSS counters certainly take a look into it.
  • [14:06.919 - 14:11.119]: It's a very nice part of CSS that doesn't get used all that often.
  • [14:11.119 - 14:12.119]: Yeah.
  • [14:12.119 - 14:17.219]: I, I feel like I might not have known this existed or it's like the type of thing I may
  • [14:17.219 - 14:21.159]: have seen at some point, but it's got my wheels turning a bit.
  • [14:21.159 - 14:23.440]: It's been around for a long, long time.
  • [14:23.440 - 14:25.840]: Probably if I were to guess it's been around for 12 years.
  • [14:26.719 - 14:27.719]: Yeah.
  • [14:27.719 - 14:28.719]: Let me, let me look.
  • [14:28.719 - 14:29.719]: Can I use you?
  • [14:29.719 - 14:30.719]: You go ahead to the next one.
  • [14:30.719 - 14:32.520]: I'll, uh, I'll look it up.
  • [14:32.520 - 14:33.520]: Yeah.
  • [14:33.520 - 14:34.520]: Well, okay.
  • [14:34.520 - 14:38.640]: Let's talk about, uh, like named pages and like titling of pages for print, which I think
  • [14:38.640 - 14:43.640]: is really interesting too, because it's another at role, but we have the at role at page and
  • [14:43.640 - 14:54.080]: you're able to like define a header, the like a header for the pages using at top and with
  • [14:54.080 - 15:00.239]: the content property, it's like, we're so used to only using at content for, um, like
  • [15:00.239 - 15:05.719]: before and after pseudo elements, but there's a lot of like really interesting, interesting
  • [15:05.719 - 15:07.159]: use cases here.
  • [15:07.159 - 15:15.640]: So if you want to give a titling to a page, you can do at top at content and then a text
  • [15:15.640 - 15:16.640]: string.
  • [15:16.640 - 15:21.520]: And, and that will display again only on print, which I think is like the most important part.
  • [15:21.520 - 15:25.960]: Your users aren't seeing these things if they're not in a print context, right?
  • [15:25.960 - 15:26.960]: Yeah.
  • [15:26.960 - 15:32.640]: That's, uh, sort of leads into the next one, which is, uh, putting custom margins, headers
  • [15:32.640 - 15:36.440]: and footers and page numbers on each of your pages.
  • [15:36.440 - 15:40.599]: So by default, and this always drives me crazy is when you print it out, it puts the whole
  • [15:40.599 - 15:45.760]: URL at the bottom of the page and it looks like garbage, right?
  • [15:45.760 - 15:52.479]: So you can say at page, which you, you select the page, um, and you can name, you can have
  • [15:52.479 - 15:56.719]: different page like templates almost, they're called named pages.
  • [15:56.719 - 16:00.520]: A chapter page might not have a header and footer, but the, the actual content might
  • [16:00.520 - 16:01.520]: have it in there.
  • [16:01.520 - 16:06.280]: Or like the very first page of your book doesn't need to have page one on it because you're
  • [16:06.280 - 16:09.919]: going to put the, like the, the cover of the book on that page.
  • [16:09.919 - 16:14.280]: So you can, you can create multiple page layouts by simply naming them.
  • [16:14.359 - 16:21.520]: Um, but yeah, you use the, you nest inside of it at bottom at, at top, bottom left, bottom
  • [16:21.520 - 16:22.520]: right.
  • [16:22.520 - 16:26.280]: And that will allow you to control the four corners of the margins.
  • [16:26.280 - 16:29.479]: And then you can put whatever you want inside of them.
  • [16:29.479 - 16:31.159]: And what can you put inside of them?
  • [16:31.159 - 16:33.320]: You can put CSS counters, right?
  • [16:33.320 - 16:34.960]: You can put the name of the book.
  • [16:34.960 - 16:35.960]: That's what I did.
  • [16:35.960 - 16:41.559]: So I put the name of the book on the left and then I put the page number with a CSS
  • [16:41.559 - 16:42.559]: counter.
  • [16:42.559 - 16:47.960]: And I simply just incremented it, uh, every single time and you're, you're able to count
  • [16:47.960 - 16:51.760]: the total number of pages as well with CSS counters.
  • [16:51.760 - 16:58.299]: So you can create one for the current page and one for the total number of pages and
  • [16:58.299 - 17:00.359]: just display that in the bottom right hand corner.
  • [17:00.359 - 17:05.760]: And that's so much easier because you can't do that in, you couldn't do that in react
  • [17:05.760 - 17:09.839]: because you don't know how many pages it's going to be.
  • [17:09.839 - 17:15.520]: You don't know if your users increasing the font size or if they're printing on a letter
  • [17:15.520 - 17:21.959]: paper in North America or what is it a four in, in Europe, uh, they're all slightly different
  • [17:21.959 - 17:22.959]: sizes.
  • [17:22.959 - 17:25.520]: So the, the amount of pages at the end of the day differs.
  • [17:25.520 - 17:26.520]: Yeah.
  • [17:26.520 - 17:30.959]: And you can also, what's interesting too, in addition to the like named pages, I mean
  • [17:30.959 - 17:34.180]: those pseudo selectors are, are really awesome.
  • [17:34.180 - 17:40.099]: So you can have a pseudo selector for a blank page if you want using at page colon blank.
  • [17:40.099 - 17:43.939]: And then now you can apply CSS to a blank page, right?
  • [17:43.939 - 17:49.359]: Let's say there ends up being a blank page and you wanted to have some bit of styling
  • [17:49.359 - 17:53.819]: on that, whether that's, you know, actual text or, or content or whatever, but you can
  • [17:53.819 - 17:57.500]: also target first, uh, left or right.
  • [17:57.500 - 18:01.140]: These little pseudo selectors are interesting or pseudo class, I suppose.
  • [18:01.140 - 18:02.140]: Yeah.
  • [18:02.140 - 18:03.819]: It's a whole crazy world.
  • [18:03.819 - 18:10.180]: Uh, let's talk about, so now you've written all this crazy print CSS, uh, that's available
  • [18:10.180 - 18:11.180]: to you.
  • [18:11.180 - 18:16.540]: Like, and I think you can grok all of print CSS in probably about 45 minutes.
  • [18:16.540 - 18:23.219]: The hardware comes into debugging it because it's not absolutely perfect and you can't
  • [18:23.219 - 18:29.579]: like preview it in the browser that all browsers have a checkbox to apply print CSS.
  • [18:29.579 - 18:32.500]: And I'm here to tell you it's, they're all garbage.
  • [18:32.500 - 18:38.420]: Um, they all say that they're going to emulate it, but they, they don't, they don't do a
  • [18:38.420 - 18:40.140]: very good job of it at all.
  • [18:40.140 - 18:48.180]: So, um, my sort of process for going through it would be open it up in Chrome and Chrome's
  • [18:48.180 - 18:54.660]: print preview in my experience was the closest you could possibly get to what it would actually
  • [18:54.660 - 18:57.300]: look like when it got spit out the other end.
  • [18:57.300 - 19:00.140]: It wasn't always perfect, but it got pretty close.
  • [19:00.140 - 19:06.939]: However, the best way to do it is you simply just save as PDF or, um, I believe on Safari,
  • [19:06.939 - 19:12.579]: there is a preview as PDF button and that will spit it out.
  • [19:12.579 - 19:18.599]: It's kind of slow because you make a change and especially if you have 40 pages, it sometimes
  • [19:18.599 - 19:25.219]: takes 15, 20 seconds to actually print, uh, to PDF and then you got to open it up and
  • [19:25.219 - 19:26.219]: see if it worked there.
  • [19:26.219 - 19:29.420]: There's no, there's no inspect element on a PDF either.
  • [19:29.420 - 19:32.339]: So you're, you're, uh, you're kind of out of luck.
  • [19:32.339 - 19:37.420]: So what I ended up doing with my envelopes is I just put a div around every envelope
  • [19:37.420 - 19:39.339]: and I called it like a page.
  • [19:39.339 - 19:47.060]: And then I explicitly made those 10 inches by three inches and put a border around it
  • [19:47.060 - 19:50.180]: so I could kind of mimic it as close as I could.
  • [19:50.180 - 19:54.660]: And then when I was like done 90% of it, then I started having to do the print preview and
  • [19:54.660 - 19:58.180]: print to PDF and get that last little 10% finish up.
  • [19:58.180 - 19:59.180]: Yeah.
  • [19:59.180 - 20:03.900]: Well, speaking of print to PDF, I think that's a whole nother part of this is, um, Hey, we're
  • [20:03.900 - 20:06.859]: living in a, you know, almost a post printer world.
  • [20:06.859 - 20:11.819]: I have a printer at my house, but it wouldn't shock me if, if many people did not have a
  • [20:11.819 - 20:12.819]: printer.
  • [20:12.819 - 20:16.140]: Um, so here's the world of PDFs, right?
  • [20:16.140 - 20:17.140]: Yeah.
  • [20:17.140 - 20:20.339]: And people often ask, you know, what do you do to get something as a PDF?
  • [20:20.339 - 20:28.099]: Now I am of the mind that in most cases, you know, you can instruct people to do print,
  • [20:28.099 - 20:30.260]: print as PDF and you'll be fine.
  • [20:30.260 - 20:35.500]: Um, and to do that, it's the same as printing any page you do command P or you select print
  • [20:35.500 - 20:39.819]: from the menu and then you're typically given a print dialogue, but what you might not know
  • [20:39.819 - 20:46.819]: is that that destination dropdown, the option that's not an actual printer is save to PDF.
  • [20:46.819 - 20:48.660]: And if you click save from there, guess what?
  • [20:48.660 - 20:53.020]: It creates a PDF of the printed page, just like what we've been talking about as how
  • [20:53.020 - 20:54.260]: you would debug that.
  • [20:54.260 - 21:00.380]: And to me, yeah, that's the easiest possible way of getting your users to save anything
  • [21:00.380 - 21:07.140]: as a PDF because you're not having to use additional services or libraries or anything
  • [21:07.140 - 21:09.020]: where it can get kind of hairy.
  • [21:09.020 - 21:13.459]: And let me tell you, if you're trying to do this in code, it gets hairy, which is why
  • [21:13.459 - 21:19.900]: I just straight up typically don't implement it and just have more instruction there, right?
  • [21:19.900 - 21:20.900]: Instruction on the page.
  • [21:20.900 - 21:22.780]: It's probably a hundred times easier.
  • [21:22.780 - 21:24.540]: And this is, that's what I do as well.
  • [21:24.540 - 21:30.859]: Um, when I first rolled out my receipts, uh, over the years, I would like get an idea of
  • [21:30.859 - 21:34.339]: how many people would email me saying I need a PDF version.
  • [21:34.339 - 21:36.180]: It has almost totally gone away.
  • [21:36.180 - 21:42.579]: So I think people understand now, at least developers, um, understand that it is a PDF,
  • [21:42.579 - 21:47.380]: but the amount of people that screenshot photos when they want to share it, I don't
  • [21:47.380 - 21:51.219]: know if I would totally put all my, uh, eggs in that basket.
  • [21:51.219 - 21:56.979]: So the next option you have is a headless browser, and this is probably the best method
  • [21:56.979 - 22:05.579]: I would say, because you're getting full blown HTML and CSS rendering from a browser that
  • [22:05.579 - 22:10.459]: you expect to render it like you wanted, and you can output it as a PDF out the other end.
  • [22:10.459 - 22:15.780]: So you can run a puppeteer instance, sometimes a little bit tricky to get a puppeteer or
  • [22:15.780 - 22:19.619]: playwright up and running, especially if you're working in a serverless environment.
  • [22:19.619 - 22:24.300]: We've talked about the issues around that, but it is well worth your time because you
  • [22:24.300 - 22:29.619]: get the easiest, like I did a little bit of research and there's so many different services
  • [22:29.619 - 22:35.739]: out there that will allow you to create PDFs, but they don't use CSS.
  • [22:35.739 - 22:41.699]: So you have to relay out the entire thing in XML or you have to use their proprietary
  • [22:41.699 - 22:42.699]: API.
  • [22:42.699 - 22:47.099]: And that might make sense for like, like, I know like government of Canada, when you
  • [22:47.099 - 22:51.739]: have to renew your passport, you download the PDF and like, have you ever used a good
  • [22:51.739 - 22:59.020]: PDF where the drop downs and form inputs, I've used plenty of bad PDFs where like the
  • [22:59.020 - 23:04.300]: tab orders wrong and you have to like numbers don't line up to the number, circle it.
  • [23:04.300 - 23:09.140]: I did one the other day where like it was a radio button for like select all that apply,
  • [23:09.140 - 23:11.420]: but you can only select one of them because it was a radio button.
  • [23:11.420 - 23:16.500]: I was like, so I had to get like the text tool out and just put an X over top of it
  • [23:16.500 - 23:18.060]: and drag and drop it.
  • [23:18.060 - 23:20.180]: Oh my gosh, awful.
  • [23:20.180 - 23:27.260]: But government of Canada, passport renewal, PDF, the best PDF I've ever used in my entire
  • [23:27.260 - 23:28.260]: life.
  • [23:28.260 - 23:31.900]: And I would love to talk to the people who made that thing because I guarantee I would
  • [23:31.900 - 23:32.900]: love to shake their hand.
  • [23:32.900 - 23:40.180]: Like one of the experts in the world of how do you make a PDF that has built in drop downs
  • [23:40.180 - 23:42.339]: and all that good stuff.
  • [23:42.339 - 23:48.900]: There's also services DocRaptor is another one where you can just send your whole payload,
  • [23:48.900 - 23:55.459]: HTML and CSS to DocRaptor and it will return to you a PDF again, that's a paid option,
  • [23:55.459 - 23:59.900]: but you're not spending any time maintaining any services or hosting anything.
  • [23:59.900 - 24:05.420]: And then there's a bunch of libraries out there if you go on NPM, JS PDF seems to be
  • [24:05.420 - 24:12.060]: a very popular one, but that one has an entire like its own API.
  • [24:12.060 - 24:18.180]: And I think there's adapters if you want to use HTML to canvas, but then you're basically
  • [24:18.180 - 24:22.939]: dumping your whole canvas website into a canvas and I've used it before.
  • [24:22.939 - 24:26.180]: It's 90% of the way there, but there's lots of little, little gotchas.
  • [24:26.180 - 24:31.339]: So I would say use Puppeteer or let the user do it.
  • [24:31.339 - 24:32.339]: That's probably the best.
  • [24:32.339 - 24:35.099]: And with that though Wes, you're not even getting into print styles, right?
  • [24:35.099 - 24:38.140]: You're just normal, normal, straight up CSS, right?
  • [24:38.140 - 24:39.140]: No.
  • [24:39.140 - 24:43.579]: With Puppeteer, printing to PDF, the print styles will apply.
  • [24:43.579 - 24:44.579]: Okay.
  • [24:44.579 - 24:45.579]: Okay.
  • [24:45.579 - 24:51.099]: Other things to quickly consider with printing is printers aren't color all the time.
  • [24:51.099 - 24:55.380]: We bought a color printer because our kids always have to print photos for things and
  • [24:55.380 - 25:01.540]: the frigging thing, like the ink ran out in like three minutes, you printed like three
  • [25:01.540 - 25:02.540]: photos.
  • [25:02.540 - 25:03.540]: Is it an inkjet or a?
  • [25:03.540 - 25:08.020]: It was an inkjet, not a, the laser color printers are silly expensive.
  • [25:08.020 - 25:10.180]: So I wasn't ready to do that.
  • [25:10.180 - 25:13.780]: Then I bought the, like, there's this thing where you can do like unlimited ink, like
  • [25:13.780 - 25:18.699]: you can put a tank on the side and I tried to do the like kit and it just started leaking
  • [25:18.699 - 25:19.699]: ink everywhere.
  • [25:19.699 - 25:22.880]: So I just got through the whole thing in the garbage, frigging nightmare.
  • [25:22.880 - 25:25.439]: So we just, we just go to Walmart to print photos now.
  • [25:25.439 - 25:26.439]: Okay.
  • [25:26.439 - 25:27.439]: Yeah.
  • [25:27.439 - 25:28.439]: We don't print photos ever.
  • [25:28.439 - 25:33.040]: So we only have a laser printer and it is in black and white because you can get a good
  • [25:33.040 - 25:36.520]: laser printer for cheap and we never replace that.
  • [25:36.520 - 25:38.319]: Like we hardly ever have to replace that.
  • [25:38.319 - 25:41.880]: And we use, we use the toner all the time and we use it all the time.
  • [25:41.880 - 25:47.880]: So, but it is important to consider that again, even if your users do have color, color ink
  • [25:47.880 - 25:49.900]: is more expensive and all that stuff.
  • [25:49.900 - 25:55.020]: So if you are making your users print stuff in full color, it should probably have to
  • [25:55.020 - 25:56.339]: be in full color.
  • [25:56.339 - 25:58.900]: Like what's the point of making a receipt full color?
  • [25:58.900 - 26:00.579]: There's no point in doing that, right?
  • [26:00.579 - 26:04.420]: So you want to make sure that you're testing to make sure your contrast and stuff is good.
  • [26:04.420 - 26:08.500]: You're not using super light grays for text where there's texts that you need people to
  • [26:08.500 - 26:09.500]: read.
  • [26:09.500 - 26:12.540]: That's the most common one I see is that people use light grays.
  • [26:12.540 - 26:13.540]: Yeah.
  • [26:13.540 - 26:17.180]: Or even like situations where you might have like white text in a black box.
  • [26:17.180 - 26:18.579]: Don't do that.
  • [26:18.579 - 26:23.339]: Have it be the black text in a white box, you know, the opposite or even worse low contrast
  • [26:23.339 - 26:24.979]: text in a colored box at all.
  • [26:24.979 - 26:27.979]: I would just remove backgrounds from any of that stuff entirely.
  • [26:27.979 - 26:33.380]: No, the browser will strip all your background images and all that stuff.
  • [26:33.380 - 26:37.180]: You don't have to worry too much about that type of thing.
  • [26:37.180 - 26:39.339]: You got to be cognizant of it, I think.
  • [26:39.339 - 26:40.339]: Yeah.
  • [26:40.339 - 26:43.099]: Definitely give it a, give it a look over.
  • [26:43.099 - 26:47.819]: And actually one thing we didn't mention with the initial printing is if you want to make
  • [26:47.819 - 26:52.739]: your page printable, a lot of times all you need is a print CSS that will simply just
  • [26:52.739 - 26:59.819]: hide your nav, hide your header, maybe, you know, your header, footer, maybe sidebar.
  • [26:59.819 - 27:04.180]: It just strip all that display none on all of that type of stuff.
  • [27:04.180 - 27:09.140]: Anywhere you're using color to denote, like if you have a calendar or a bunch of tags
  • [27:09.140 - 27:14.020]: and like it shows that red ones are disabled and blue ones, first of all, you shouldn't
  • [27:14.020 - 27:18.300]: just be using color to in your websites in general to denote things.
  • [27:18.300 - 27:23.459]: But if you are, maybe switch it to a pattern that's necessary.
  • [27:23.459 - 27:24.859]: Make it as fluid as possible.
  • [27:24.859 - 27:26.099]: Just like responsive design.
  • [27:26.099 - 27:33.099]: Don't assume a paper size unless you are explicitly doing like labels or envelopes because paper
  • [27:33.099 - 27:36.099]: sizes differ all over the world.
  • [27:36.099 - 27:39.619]: And don't forget to put a title on your fricking document.
  • [27:39.619 - 27:40.619]: This one kills me.
  • [27:40.619 - 27:42.180]: I download, I go to my bank.
  • [27:42.180 - 27:45.819]: I download 12 months worth of exports.
  • [27:45.819 - 27:49.939]: And you know what I get out the other end is a statement dot PDF.
  • [27:49.939 - 27:50.939]: Yes.
  • [27:50.939 - 27:55.020]: And then the next month is statement bracket one dot PDF.
  • [27:55.020 - 28:00.699]: And then come on, like I have the same web file name on that sucker.
  • [28:00.699 - 28:02.939]: Like it kills me that you don't.
  • [28:02.939 - 28:08.660]: And in so many cases, it's you just have to put a title on your HTML tag that says what
  • [28:08.660 - 28:13.500]: month or year this thing is for or specifically.
  • [28:13.500 - 28:14.500]: That's that's that's all you need.
  • [28:14.500 - 28:17.060]: I must say we did that on Level Up Tutorials, Wes.
  • [28:17.060 - 28:21.579]: We did have the month of the invoice and the invoice number.
  • [28:21.579 - 28:22.579]: Oh, beautiful.
  • [28:22.579 - 28:23.579]: Yeah.
  • [28:23.579 - 28:24.619]: Put the invoice number in there.
  • [28:24.619 - 28:28.579]: Also makes like document storing if you search for an invoice number.
  • [28:28.579 - 28:33.900]: I know that search goes inside of documents now, but it doesn't always consider if links
  • [28:34.060 - 28:35.739]: and titles need to be printed out.
  • [28:35.739 - 28:43.300]: So you can use the at after or sort of the after pseudo element and use the ATTR method.
  • [28:43.300 - 28:47.619]: So if you need to explicitly print out where links go.
  • [28:47.619 - 28:51.260]: You can append them after with the content.
  • [28:51.260 - 28:53.579]: Also, word wrap break word.
  • [28:53.579 - 28:58.060]: Very important for long URLs or long content that could possibly spill out onto the paper
  • [28:58.060 - 29:02.739]: because then you beer printed something and then the next page is just like six characters
  • [29:02.739 - 29:05.579]: because it had to overflow and that's a pain.
  • [29:05.579 - 29:10.939]: So make sure that very long characters likely very long URLs that you're not expecting will
  • [29:10.939 - 29:13.699]: break on to the next line.
  • [29:13.699 - 29:15.699]: So that is print CSS.
  • [29:15.699 - 29:18.219]: Yeah, we have a we have a couple laser printers.
  • [29:18.219 - 29:20.979]: We have one here and one at the cottage as well.
  • [29:20.979 - 29:24.219]: Big fan of those because they always work.
  • [29:24.219 - 29:26.660]: The ink is super cheap to replace.
  • [29:26.660 - 29:30.699]: It only runs out like maybe once a year and we print a lot.
  • [29:31.660 - 29:33.060]: Mine does not run out that frequently.
  • [29:33.060 - 29:35.420]: Mine's like one every three years maybe.
  • [29:35.420 - 29:38.140]: And we we we do print it sound like we're not printing.
  • [29:38.140 - 29:39.140]: But yeah, yeah.
  • [29:39.140 - 29:41.180]: Get yourself a laser printers these days.
  • [29:41.180 - 29:43.020]: You would be surprised at how cheap they are.
  • [29:43.020 - 29:44.020]: I bought mine.
  • [29:44.020 - 29:45.699]: Probably a hundred bucks.
  • [29:45.699 - 29:46.699]: Yeah.
  • [29:46.699 - 29:50.420]: Maybe even less for a printer and you know they do come in handy granted.
  • [29:50.420 - 29:51.420]: Get a brother.
  • [29:51.420 - 29:52.420]: Get a brother.
  • [29:52.420 - 29:53.420]: What do you have?
  • [29:53.420 - 29:56.380]: I think I have an HP which is fine.
  • [29:56.380 - 29:57.380]: Yeah.
  • [29:57.380 - 29:58.380]: You know what?
  • [29:58.380 - 29:59.380]: Here's the test of a printer.
  • [29:59.380 - 30:02.300]: Will it print from your laptop?
  • [30:02.300 - 30:05.579]: Will it print actually print from Wi-Fi?
  • [30:05.579 - 30:09.739]: Because it seems like Wi-Fi printing is like the single hardest task of any printer for
  • [30:09.739 - 30:10.739]: some reason.
  • [30:10.739 - 30:11.739]: Yeah.
  • [30:11.739 - 30:16.540]: When the Wi-Fi printing came out, I was so happy because like we put ours in the basement
  • [30:16.540 - 30:20.099]: on a very high shelf because you use it once every month.
  • [30:20.099 - 30:21.459]: You know, I don't want it to be anywhere.
  • [30:21.459 - 30:22.459]: I don't want to see.
  • [30:22.459 - 30:23.699]: No, I don't want to see that thing.
  • [30:23.699 - 30:28.060]: I don't want to see you in my space.
  • [30:28.060 - 30:34.300]: Real quick on the topic of printing as well as I went down the rabbit hole of web Bluetooth
  • [30:34.300 - 30:39.780]: because we got these little nimba, these little label printers that are Bluetooth nimba label
  • [30:39.780 - 30:42.900]: printer and I can't figure out how to make it work.
  • [30:42.900 - 30:45.579]: There's a whole bunch of they're very popular in China.
  • [30:45.579 - 30:49.979]: They're called cat printers and there's a whole bunch of like Chinese get hubs that
  • [30:49.979 - 30:54.500]: I can't understand that have some code around how to hack these things.
  • [30:54.500 - 30:56.060]: I haven't gone too deep.
  • [30:56.060 - 31:01.020]: But there's also like, you know, you get a receipt at a at a restaurant.
  • [31:01.020 - 31:02.020]: Yeah.
  • [31:02.020 - 31:09.020]: Those things are all almost all based on a single standard, which is this like ESP standard.
  • [31:09.020 - 31:15.579]: And I'm very tempted to buy one and use the web serial API and try to figure out how to
  • [31:15.579 - 31:18.819]: send data from the browser directly to the printer.
  • [31:18.819 - 31:20.339]: Not even the print dialogue.
  • [31:20.339 - 31:21.339]: Yeah.
  • [31:21.339 - 31:22.339]: Yeah.
  • [31:22.660 - 31:27.660]: You would be the type of person to try to to hack one of those.
  • [31:27.660 - 31:31.540]: Someone on Twitter said, like, I think somebody's done it like a GitHub issue.
  • [31:31.540 - 31:36.579]: But like, imagine every time a sentry issue is logged, it just goes and like prints it
  • [31:36.579 - 31:37.579]: out.
  • [31:37.579 - 31:40.859]: I think you would be the type of person who would love a flipper zero.
  • [31:40.859 - 31:42.579]: Have you heard of the flipper zero?
  • [31:42.579 - 31:43.579]: Yeah.
  • [31:43.579 - 31:44.579]: Oh, yeah.
  • [31:44.579 - 31:45.579]: Yeah.
  • [31:45.579 - 31:46.579]: I have.
  • [31:46.579 - 31:47.579]: I've gone down that rabbit hole a few times.
  • [31:47.579 - 31:48.579]: Yeah.
  • [31:48.579 - 31:49.579]: Cool.
  • [31:49.579 - 31:50.579]: Well, that's print CSS.
  • [31:50.579 - 31:51.579]: I love it.
  • [31:51.819 - 31:52.819]: Thanks for tuning in.
  • [31:52.819 - 31:53.819]: Catch you later.
  • [31:53.819 - 31:54.819]: Peace.
  • [31:54.819 - 31:55.819]: Peace.
  • [31:55.819 - 32:00.780]: Head on over to syntax.fm for a full archive of all of our shows.
  • [32:00.780 - 32:05.780]: And don't forget to subscribe in your podcast player or drop a review if you like this show.