---
url: /labels.md
---
# Product Labels

A label template (Administration › Šablony, type *štítek*) prints labels for stock items: the name,
the price, codes and a barcode, one label per page on a roll printer (Zebra) or several on an A4
sheet. It is a Twig text template rendered to HTML and then to a PDF at the template's size.

## Variables

| Variable | Type | Description |
|---|---|---|
| `itemLabels` | [PrintedLabel](/objects#printedlabel)\[] | One label object per printed item, with how many copies (`quantity`) |
| `groupedProductLabels` | [PrintedLabel](/objects#printedlabel)\[] | One per product, the copies of its items summed |
| `sheet` | [LabelSheet](/objects#labelsheet) | What the labels print on: the page's `width` and `height` in mm, the `row` and `column` an A4 sheet starts at, the `printerType` |
| `shop` | [Shop](/objects#shop) | The shop, as in other templates: `shop.name`, `shop.url`, `shop.phone`, … |
| `repository` | | The storefront's [repositories](/repositories), e.g. a product attribute: `repository.attribute.findOneBy({id: 4})` |

A template prints each copy itself, e.g. `{% for copy in 1..label.quantity %}…{% endfor %}`.
What a label object holds (name, variant, codes, barcode content, price, QR code) is in
[PrintedLabel](/objects#printedlabel). The price is there only when the shop prints prices on
labels (its setting *Typ ceny na štítky*); print it with `{{ label.price.current|price }}`.

## Barcodes and QR codes

Write a barcode as a tag; it becomes an image before the PDF is made:

| Tag | Code |
|---|---|
| `<img-code128 src="…" width="1" height="30">` | Code 128 (any text) |
| `<img-ean13 src="…" width="1" height="30">` | EAN-13 (13 digits) |
| `<img-codeI25 src="…" width="1" height="30">` | Interleaved 2 of 5 (digits) |
| `<img-qr src="https://…" width="80">` | QR code (`width` in px) |

`width` is the width of one bar (default 2), `height` the bars' height in px (default 30). The
`-png` forms (`<img-code128-png>`, …) make a PNG instead of an SVG. A value the code cannot hold
gives an empty image, not an error. Size the image with CSS (`height: 8mm; max-width: 100%`).

## Page size

The page is the template's width and height in mm, without margins. One label per page: make each
label fill the page (`html, body { height: 100% }` and the label `height: 100%`; `100vh` is not the
page's height in the PDF) and break after it (`break-after: page`, except the last). An A4 sheet: lay out the grid yourself and start at
`sheet.row` and `sheet.column`. The size is `sheet.width` × `sheet.height` (mm) when a layout needs
it in numbers.

## What a label may use

In the label studio a label renders in a restricted environment, and a text that renders there
renders the same when printed. It reaches only the variables above: not the `iterator` global, and
not `{% cache %}`. Twig's own tags, filters and functions work as everywhere (`include`, `embed` and
`source` have no other templates to load). Of the shop's own filters every one but `ndump`,
`gravatar`, `image_proxy` and `setAnalyticsName`; of its own functions only `QR`,
`isPracovniDen`, `pristiPracovniDen` and `rand`. Objects' methods and properties as in other
templates (no static methods). Output is not escaped automatically: escape product texts with `|e`.
A variable or attribute that does not exist is an error with its line (printing would print
nothing for it): test an optional one with `is defined`, or give it a default with `??`.

## Example

```twig
<style>
    * { box-sizing: border-box; margin: 0; padding: 0; }
    html, body { height: 100%; }
    body { font-family: Arial, Helvetica, sans-serif; }
    .label { height: 100%; padding: 1.5mm 2mm; display: flex; flex-direction: column; justify-content: space-between; break-after: page; }
    .label:last-child { break-after: auto; }
    .barcode img { height: 8mm; max-width: 100%; }
</style>
{% for label in itemLabels %}
    {% for copy in 1..label.quantity %}
        <div class="label">
            <strong>{{ label.productName|e }}</strong>
            {% if label.variantName is not empty %}<div>{{ label.variantName|e }}</div>{% endif %}
            {% if label.price %}<div>{{ label.price.current|price }}</div>{% endif %}
            <div class="barcode"><img-code128 src="{{ label.barcodeContent|e }}" width="1" height="30"></div>
            <small>{{ label.visibleCode|e }}</small>
        </div>
    {% endfor %}
{% endfor %}
```
