Guides / Tutorials

Build a printable dog breed chart

By the Dog Image API team. Updated .

A printable breed chart is one web page that shows a grid of dogs with their names and prints cleanly. The page below fetches the breed list, shows the left side view of each breed, and uses print CSS to set the paper size and keep each card from splitting across pages.

What the page does

  1. Fetches GET /api/v1/breeds, which needs no key and lists every breed with its slug, name and color variants.
  2. Optionally filters that list to the breeds you choose.
  3. Shows each breed as a card: image and name.
  4. Uses @page and break-inside so it prints well.

The images are AI-generated illustrations with a transparent background. The view id left is the left side view. Using one view for every card keeps the chart consistent.

The complete file

Save this as chart.html and open it in a browser. It loads the preview files, so you need to be online.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Dog breed chart</title>
  <style>
    :root { --ink: #2b2118; --card: #fbf3e2; }
    body { font-family: Georgia, serif; color: var(--ink); margin: 0; padding: 24px; background: #fff; }
    h1 { margin: 0 0 4px; font-size: 28px; }
    .grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-top: 16px; }
    .card { background: var(--card); border-radius: 10px; padding: 8px; text-align: center; break-inside: avoid; }
    .card img { width: 100%; height: auto; display: block; }
    .card span { display: block; font-size: 14px; padding: 4px 0 6px; }
    .credit { margin-top: 16px; font-size: 12px; }
    .controls { margin-top: 8px; }

    @page { size: A4 portrait; margin: 12mm; }
    @media print {
      body { padding: 0; }
      .controls { display: none; }
      .grid { grid-template-columns: repeat(4, 1fr); gap: 8mm; }
      .card { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
      .credit a { color: var(--ink); }
    }
  </style>
</head>
<body>
  <h1>Dog breed chart</h1>
  <p>Left side view of each breed. Illustrations are AI-generated.</p>
  <div class="controls">
    <label>Show: <select id="mode">
      <option value="mine">My list</option>
      <option value="all">All breeds</option>
    </select></label>
    <button onclick="window.print()">Print</button>
  </div>
  <div class="grid" id="grid"></div>
  <p class="credit">Images: <a href="https://dogimage.dev/dogs">Dog Image API</a></p>

  <script>
    const API = "https://dogimage.dev/api/v1/breeds";
    const VIEW = "left";
    const MY_LIST = ["pug", "golden-retriever", "german-shepherd", "french-bulldog", "samoyed", "beagle", "dachshund", "poodle"];
    const grid = document.getElementById("grid");
    let all = [];

    async function previewFor(slug) {
      const res = await fetch(API + "/" + slug);
      const breed = await res.json();
      const v = breed.variants.find((x) => x.slug === breed.default_variant);
      return v.views[VIEW].preview_512;
    }

    async function render() {
      const mode = document.getElementById("mode").value;
      const list = mode === "mine" ? all.filter((b) => MY_LIST.includes(b.slug)) : all;
      grid.innerHTML = "";
      for (const b of list) {
        const card = document.createElement("div");
        card.className = "card";
        const img = document.createElement("img");
        img.alt = b.name + ", left side view";
        img.loading = "lazy";
        const name = document.createElement("span");
        name.textContent = b.name;
        card.append(img, name);
        grid.append(card);
        previewFor(b.slug).then((url) => { img.src = url; });
      }
    }

    fetch(API).then((r) => r.json()).then((data) => {
      all = data.breeds;
      render();
    });
    document.getElementById("mode").addEventListener("change", render);
  </script>
</body>
</html>

The print rules

  • @page { size: A4 portrait; margin: 12mm; } sets the paper size and margins. Use letter portrait for US Letter, or A4 landscape for a wider sheet.
  • break-inside: avoid on .card stops a card from splitting between two pages.
  • print-color-adjust: exact asks the browser to print the card background. Browsers hide backgrounds by default to save ink, and users can still turn that setting off in the print dialog.
  • The controls are hidden in print, and the credit link stays.

For a chart with forced page boundaries, wrap groups of breeds in sections and add break-after: page to each section.

Choose your breeds

The MY_LIST array holds breed slugs. Add or remove slugs. Slugs are in the list that the endpoint returns, and the breed list guide shows its shape. The "All breeds" option loads every breed, which means one request per breed for its image URL. That is a lot of requests for a screen, and it makes a long printout, so use it only when you mean to.

What the chart does not show

Each dog fills its own square frame, at most 80% of it. A Chihuahua and a Great Dane both fill their frames, so the chart does not show relative size between breeds. Add a text line for size if your reader needs it, and take that number from a source you trust.

Credit on paper

The preview license needs a visible link that credits Dog Image API on the same page. On a printed sheet the link is still printed as text, so the credit is there. Read the license if you plan to distribute the sheets. For large prints, where 512 pixels will look soft, the paid 2048 pixel PNGs on pricing are the right source.

Questions

Does the chart show how big each breed is?

No. Each dog fills its own square frame, at most 80% of it, so a Great Dane and a Pug look about the same size. Do not use the chart to compare sizes.

How do I save the chart as a PDF?

Open the page, choose Print in your browser, and pick Save as PDF as the destination. The print rules in the page set the page size and breaks.

Do I need an API key?

No. The breed list and the preview files need no key. The credit link has to stay visible on the page, and on the printed sheet.

Can I print a sheet for a breeds list of my own?

Yes. Put the breed slugs you want in the list at the top of the script. Slugs come from the breed list endpoint.

Next steps