Print Avery labels using CSS and HTML

A client for whom I provide web services asked me if I could help her print barcode labels from their data.

Now, I’ve created Avery labels using Office, Illustrator, even Photoshop — but never using web technologies. You just don’t have a lot of control printing from your browser using CSS.

Or do you…? After all, we’ve always been able to specify real-world measurements such as “in” and “cm” using CSS.

I bought Avery 5160 labels because they seemed big enough to allow me to be a little sloppy while still providing many stickers per page.

A quick test proved that I could specify the page margins, label sizes, and gutter widths in inches. And both Firefox and IE allowed me to set the print margins to 0, leaving control of the layout to my CSS. Here’s what the print preview looks like from Firefox:

It’s not perfect, but it’s good enough.

Printing multiple pages turned out to be trickier. First, to prevent pages from breaking halfway across my labels, I inserted an empty div with the style rule “page-break-after” set to “always”.

Also, I had used the HTML body to set the margins. But the top of “page 2″ doesn’t know anything about the HTML body’s top margin. There is some documentation on “paged media” but it felt like uncharted territory. Rather than fight it, I decided to let the browser — rather than the CSS — set the top margin. I had to convey that in some friendly instructions on my client’s launch page:

Before printing labels, use your browser’s print preview options to set the top print margin to 1/2 inch and all other print margins to 0 (zero).

Try printing a test page on plain paper first. Hold it up to the light behind a sheet of labels to make sure the bar codes line up with the stickers.

It worked great in Firefox and Internet Explorer — good enough for my client.

Once the concept was proven, I built a controller page that lets my client print a test sheet, blocks of real data, individual data points, and even “blank” labels to push the data past previously peeled stickers so that nothing is wasted.

Here’s a one-page example of the HTML and CSS used to create Avery 5160 labels. (HTML corrected thanks to Halty.)

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>HTML & CSS Avery Labels (5160) by MM at Boulder Information Services</title>
    <link href="labels.css" rel="stylesheet" type="text/css" >
    <style>
    body {
        width: 8.5in;
        margin: 0in .1875in;
        }
    .label{
        /* Avery 5160 labels -- CSS and HTML by MM at Boulder Information Services */
        width: 2.025in; /* plus .6 inches from padding */
        height: .875in; /* plus .125 inches from padding */
        padding: .125in .3in 0;
        margin-right: .125in; /* the gutter */

        float: left;

        text-align: center;
        overflow: hidden;

        outline: 1px dotted; /* outline doesn't occupy space like border does */
        }
    .page-break  {
        clear: left;
        display:block;
        page-break-after:always;
        }
    </style>

</head>
<body>

<div class="label"><img src="http://boulderinformationservices.files.wordpress.com/2011/08/barcode_sample.png" /><br>Human readable</div>
<div class="label"><img src="http://boulderinformationservices.files.wordpress.com/2011/08/barcode_sample.png" /><br>Human readable</div>
<div class="label"><img src="http://boulderinformationservices.files.wordpress.com/2011/08/barcode_sample.png" /><br>Human readable</div>
<div class="label"><img src="http://boulderinformationservices.files.wordpress.com/2011/08/barcode_sample.png" /><br>Human readable</div>
<div class="label">(Repeat 30 times)</div>
<div class="page-break"></div>

</body>
</html>
Posted in Uncategorized | 8 Comments

A visual checksum for your PHP output

Refactoring the code on my billing system, I was promoting a method to its parent object. If I did it right, the output from the code wouldn’t be any different before and after the refactor.

Unfortunately, the output page was a large table of numbers, and it was difficult to detect a small change at a glance. If only there were some way to have the page spit out a checksum, I could quickly tell whether the refactor resulted in identical output.

SHA-1 is an encryption algorithm. It takes a string of any length as an input and returns a string of 20 hexadecimal characters. It’s easy to reduce a big HTML table full of numbers to a small string.

It was still a little difficult to tell the difference between, for example, the next two lines

a847a906c9955734217c348eaa5b3b38abab0bdf 
15b8fdd026c607e0b51b2d5e51103a77bf103354

So I decided to take advantage of the fact that here was a nice long string of hex decimals. I grabbed the first 6 and the last 6 digits to create a colored box with a colored border. Now I could quickly glance at a big blob of color and tell whether anything had changed.

This difference is much easier to see:

15b8fdd026c607e0b51b2d5e51103a77bf103354
a847a906c9955734217c348eaa5b3b38abab0bdf

Here is the PHP function:

function getVisualChecksum($out)
{
 // from boulderinformationservices.wordpress.com
 $checksum = sha1($out);
 $checksumColor1 = substr($checksum, 0, 6);
 $checksumColor2 = substr($checksum, -6, 6);
 return sprintf(
  '<span style="background-color: #%s; border: 4px solid #%s">%s</span>', 
  $checksumColor1, 
  $checksumColor2,
  $checksum
 );
}
Posted in Debugging, Refactoring, Web programming | Leave a comment

Share Eclipse snippets among workspaces, or even different computers

I use Eclipse as my editor of choice. I also use multiple Workspaces (see File > Switch Workspace). I also use Snippets for common code templates.

I created some useful snippets in one workspace that I wanted to be able to use in another. Eclipse doesn’t provide an easy way to share snippets across workspaces. Using Eclipse, you would have to copy the snippet, switch workspaces (which requires restarting the program), and then paste it… for each snippet you want to reuse. And that’s awful.

Phase 1: Copy the XML nodes

One way to copy a bunch of snippets across workspaces is to merge the various snippet XML files into a master file. Your snippets are stored in

C:\Users\YOURNAME\AppData\Roaming\Eclipse\workspace-YOUR_WS_NAME\.metadata\.plugins\org.eclipse.wst.common.snippets\user.xml

I was able to use WinMerge to compare my new snippets file with my older one. It was easy to use WinMerge’s Copy Left command to push just the new lines into my older file, and then save the merged master. Restarting Eclipse with the new master file confirmed that I successfully copied the snippets.

But wait a minute…. My snippets files are in sync, but there is nothing to prevent them from drifting out of sync again.

Hard links to the rescue.

Phase 2: Make a hard link

A hard link is a pointer. It looks like a file, but it doesn’t have any contents, it has a reference to another file, somewhere else on the file system. I can create a hard link called “user.xml” in each of my workspaces that points to a single, XML master file.

I saved my merged master XML file to a location outside of the Eclipse folder tree. Then I backed up my individual user.xml files by renaming them. Then I created the hard links.

To create a hard link,

  1. Open a command prompt.  You may have to open the command prompt as an administrator (on Windows 7, right-click the link to command prompt and choose “Run as administrator”).
  2. Change directories into your workspace/(etc.)/org.eclipse.wst.common.snippets/ folder.
  3. Make the link like so:
mklink /H user.xml "C:\path\to\your\master\user.xml"

… and repeat steps 2 and 3 for each of your workspaces. Easy!

To carry the idea a step further, I decided to put my real master XML file in a folder that is shared via LiveMesh (you could do the same thing with Dropbox or a network drive). That way, I can sync my snippets between my laptop and my desktop computer.

Posted in Uncategorized | Leave a comment

CSS bug in IE8 (yes, 8) with generated content and z-index

I came up with a nice way to use the CSS selector “:after” for image replacement (more later perhaps). It works great in modern browsers from Firefox, Safari, and Opera… but not IE8. (Wasn’t IE8 supposed to fix all those CSS bugs?)

I found confirmation on Nicolas Gallagher’s site that, indeed, IE8 fails to position the z-index of generated content correctly.

Time to look for a selector hack for IE8…

Posted in Uncategorized | Leave a comment

Converting to UTF-8

Shamed and inspired by Joel Spolsky’s decade-old article on character encoding, and warned by another blog post (which I can’t find) that described a three-day ordeal fighting the issue, I cleared some time and sat down to make sure all the pages on my site were using UTF-8, start to finish.

It wasn’t nearly as bad as I thought it would be. In fact, it probably took one or two hours. Here is what I did:

  • For MySQL: make a backup, edit the backup file, replacing “latin1″ with “utf8,” restore
  • For Browsers: add the utf-8 header (below) in my head tag. Luckily, all of my pages use the same template for drawing headers, so this was only a single change for the web site, and a single change for my admin pages.
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  • For static text: Change my code editor (Eclipse) to use UTF-8, and re-save some files that had hard-coded em-dashes. (I should have used HTML entities for those anyway.) The setting is under Window > Preferences > General >  Workspace > Text file encoding
  • For PHP/MySQL: this was the least obvious change. You have to specify the character set for the connection between PHP and MySQL. If you have a newer version of PHP (>= 5.2.3), you can use mysql_set_charset. Otherwise, you need to send a SQL command directly:
    // for PHP >= 5.2.3
    mysql_set_charset('utf8',$cn);
    
    // for older versions (see also MySQL documentation for SET NAMES):
    mysql_query('SET NAMES "utf8"');

I don’t believe how easy it was – and I mean that. I expect to get burned somewhere along the way. But for now, it looks good and was pretty painless.

Since then I have found broken special characters here and there, but I’ve been able to find them and fix them as I go. Let’s hear it for incremental improvements!

 

Posted in Web programming, Webmastering | Leave a comment

Aw, Phoocs! That is to say… PHP + OOCSS

When I first heard about OOCSS, I was skeptical. Here was another expert developer with her own pet system for building pages – didn’t we all have something like that in our snippet library?

Plus, the “OO” component of OOCSS seems like kind of a stretched metaphor. It’s not truly object-oriented in the way that many programming languages are.

Plus, if you buy into OOCSS, you don’t get control of source-code order, which I thought was very important.

Nevertheless, I was tired of writing HTML by hand, and if Nicole Sullivan had a streamlined way to build one-, two-, and three-column layouts, with modules that magically worked, I was willing to listen. And the more I worked with OOCSS – particularly the templates and the modules – the more I was hooked.

It’s been about 2 years and I’ve never looked back. I always use OOCSS for new projects. Why not use a system that has been lovingly crafted, tested in the real world, and that works so cleanly?

Over the years I built wrappers in PHP for some of the sometimes-complex HTML structures required by OOCSS. After explaining to a friend why he should use OOCSS (and my PHP libraries that support it), I decided to make my libraries into an open-source project called Phoocs. That’s PHP + OOCSS, shortened into something relatively pronounceable… “fooks!” … sounds a little swear-y, but it won’t make you swear, I promise. If you’re interested in using it, find the source code on github.

I hope you find the library easy and useful. By all means submit suggestions, improvements, or even kudos to the project or to me here at this blog.

Posted in Uncategorized | Leave a comment

When PNG color doesn’t match hex color in IE, smush.it!

I built a site for my cousin’s business. We used PNGs for some of the background images and it looked gorgeous (at least to me).

Then one day she asked me why her site had those weird rectangles. I had no idea what she was talking about, so she showed me on her computer, and sure enough, ugly rectangles surrounded the background images, rather than blending seamlessly into the CSS hex colors:

Ugly rectangles delineate PNG

I noticed she used Internet Explorer, and I had remembered seeing this problem in the past, also on IE… it had something about how the file was exported from Photoshop.

I couldn’t remember what the export settings were, or why it mattered, but rather than tinkering with export flags, I thought of smush.it, an image-shrinking application that leaves image data intact but strips away non-image metadata from files. If the color difference was some flag from Photoshop, maybe smush.it would strip it out.

Sure enough. I ran the PNG through smush.it and saved over the original. When I refreshed the page, it looked perfect. No more ugly rectangles. And best of all I didn’t even have to open Photoshop.

No ugly rectangles

Posted in CSS, Images, Webmastering | Leave a comment