Skip to content

Label Layouts

A barcode and text layout rendered on a 3x1 thermal label

What a layout produces: a barcode and text, arranged on a 3x1 thermal label

Introduction

Layouts control what will be printed on each label and how it is arranged.

Things to know:

  • Layouts can be static (each label is exactly the same) or dynamic (data is inserted into the label from the data list). Most commonly, layouts are a mix of both.
  • Layouts are responsive, meaning they will resize to fit the template dimensions. Usually, they'll be designed to fit specific labels.
  • Layouts are made up of one or more layout elements.

The entire label layout specification can be viewed here

Examples

Here is an example of a layout with a barcode in the top 75%, and text in the bottom 20%. Both the barcode and the text show a package label:

{
  "labelContentLayoutElements": [
    {
      "elementType": "CODE128_BARCODE",
      "valueTemplate": "{{package.label}}",
      "yStartFraction": 0.25
    },
    {
      "elementType": "TEXT",
      "valueTemplate": "{{package.label}}",
      "yEndFraction": 0.2
    }
  ]
}

Here is how this layout renders on a 3x1 thermal label:

Barcode/text layout rendered on 3x1 thermal label

Barcode/text layout rendered on 3x1 thermal label

Here is how this layout renders on an Avery 8160 label sheet:

Barcode/text layout rendered on Avery 8160

Barcode/text layout rendered on Avery 8160

Layout Elements

A layout element is a single element that appears somewhere on a label. Text, images, and barcodes are all examples of layout elements.

Each layout element has a specific elementType that describes how it will appear. Available element types:

elementType Description
TEXT A paragraph of text
TABLE A table made of rows/columns of cells, defined with HTML
IMAGE An image file (passed as base64)
CODE128_BARCODE A Code 128 barcode
CODE39_BARCODE A Code 39 barcode
QR_CODE A QR code
BOX A rectangular box used for borders or background fills
FRAGMENT Another label layout, embedded inside this one

Every element type also accepts the same four base fields, whatever else it supports:

Field Description
elementType Which of the types above this element is
enabled Set false to skip the element without deleting it. This is the eye toggle in the layer stack
description A free-text name for the element. It is not printed; it is how the element is labeled in the Label Studio, so a layout with more than a few elements stays readable
xStartFraction, xEndFraction, yStartFraction, yEndFraction The element's rectangle. See Position and Sizing

elementType is the only required field. The API accepts the eight types above and rejects anything else, so a typo is reported rather than silently skipped. The Label Studio is more forgiving while you are editing: an element whose type it does not recognize is shown as Unknown with its position controls intact, so one bad element in a hand-edited layout leaves the rest of the layout editable.

Text

A TEXT layout element adds a paragraph of text.

Tables

A TABLE element adds multiple pieces of text formatted in rows and columns.

  • All text in a table has a consistent font size and spacing.
  • Table borders are not displayed by default.
  • Tables are defined with HTML.

Images

An IMAGE layout element adds an image file onto the label.

  • Images are centered in the layout element and fit to the available space.
  • Image data is passed as base64 and accessed via filename (see value templates).
  • The value template must resolve to usable image data. Unlike other element types, an IMAGE that renders blank is an error rather than an empty space. See Missing Images.

Barcodes

The CODE128_BARCODE and CODE39_BARCODE elements display a scannable 1D barcode that encodes a piece of text.

  • The barcode will fill the layout element area horizontally and vertically.
  • The barcode encodes whatever is produced by the value template.
  • Use CODE128_BARCODE for Metrc tags and most general-purpose use. CODE39_BARCODE is available for systems that specifically require Code 39.

QR Codes

A QR_CODE element displays a scannable QR code that encodes a piece of text.

  • QR codes are centered in the layout element and fit to the available space, with padding.
  • The QR code encodes whatever is produced by the value template.

Boxes

A BOX element draws a rectangular box inside the layout element area. It does not use a value template.

  • boxStrokeColor sets the border color (hex, default #000000).
  • boxStrokeWidth sets the border width in points (default 0.5).
  • boxStrokeAlpha sets the border opacity (0.0–1.0, default 1.0).
  • boxBackgroundColor sets the fill color (hex). Omit to disable fill.
  • boxBackgroundAlpha sets the fill opacity (0.0–1.0, default 1.0).

Fragments

A FRAGMENT element draws another layout inside its rectangle, so a block you use on many labels is written once instead of copied into each one. See Reusing Layouts With Fragments.

Position and Sizing

Layout elements are positioned as rectangles inside the printable area. The boundaries of the rectangle are specified as fractions of the label's printable width and height. This allows the same layout to be reused across labels of different sizes.

Layout elements use the following values to define size and position:

  • xStartFraction - left edge (default 0)
  • xEndFraction - right edge (default 1)
  • yStartFraction - bottom edge (default 0)
  • yEndFraction - top edge (default 1)

Values are decimals between 0 and 1 (for example, 0.05 = 5% of the total dimension).

Note: The default start and end values fill the entire printable area. In the earlier example, only one fraction is defined for each layout element, the rest fall back to defaults.

Aspect Ratio Limits

By default, layouts will fill the available template width and height. You can define a minimum and maximum aspect ratio for the layout, which will limit how much it will stretch.

Layouts use two values to control this:

  • minAspectRatio
  • maxAspectRatio

Note: If T3 detects a minimum or maximum aspect ratio is reached, it will center the layout inside the template.

Reusing Layouts With Fragments

Most labels share blocks: a state warning panel, a barcode with its human-readable tag underneath, a facility footer. A fragment lets you write that block once and embed it in as many layouts as you like.

A fragment is not a special kind of object; it is an ordinary label layout. Anything you can print on its own can be embedded in another layout, and the layout you embed is exactly what GET /v2/labels/label-content-layouts returns.

Fragments work like images: send a map of named layouts alongside your request, then reference one by name from a FRAGMENT element.

{
  "labelContentLayoutConfig": {
    "labelContentLayoutElements": [
      {
        "elementType": "CODE128_BARCODE",
        "valueTemplate": "{{ package.label }}",
        "yStartFraction": 0.4
      },
      {
        "elementType": "FRAGMENT",
        "fragmentKey": "state_warning",
        "yStartFraction": 0,
        "yEndFraction": 0.35
      }
    ]
  },
  "fragments": {
    "state_warning": {
      "labelContentLayoutElements": [
        {
          "elementType": "TEXT",
          "valueTemplate": "{{ t3.text.poison_control_center_phone }}",
          "paragraphFontSize": 6,
          "yStartFraction": 0.5
        },
        {
          "elementType": "BOX",
          "boxStrokeWidth": 1
        }
      ]
    }
  },
  "renderingOptions": { "renderingVersion": 2 }
}

Positioning inside a fragment

A fragment fills its element's rectangle, and its own elements are positioned relative to that rectangle, not to the whole label. In the example above, the fragment occupies the bottom 35% of the label, so the TEXT at yStartFraction: 0.5 sits halfway up the fragment, not halfway up the label.

This is what makes a fragment portable: move the FRAGMENT element and everything inside it moves with it.

Aspect ratio

A fragment honors its own minAspectRatio and maxAspectRatio inside its rectangle, exactly as a layout does inside a label, so a block designed to be wide is not squeezed into a tall box. If the rectangle falls outside the fragment's limits, the fragment is centered within it.

The defaults are wide (0.1 and 10), so an ordinary layout used as a fragment will simply fill its rectangle. Set the limits on the fragment when its proportions matter.

Font sizes do not scale

paragraphFontSize is measured in points, so it is not affected by the size of the fragment's rectangle. A fragment written with 10pt text renders at 10pt whether it fills the label or sits in a narrow strip.

This is worth planning around, because barcodes, QR codes and images do scale to fit their element. Put text that needs to fit its box on paragraphTextResizeStrategy: SHRINK_TEXT (see Responsive Sizing).

Data

A fragment sees exactly the same data as the layout that embeds it, so {{ package.label }} means the same thing in both. There is no separate data list for a fragment.

Nesting and limits

A fragment can embed other fragments, up to five levels deep. Every fragment goes in the same flat fragments map no matter how deeply it is nested.

Requests are rejected with a 400 if:

  • A fragmentKey is not in the fragments map. The error lists the available keys and suggests near matches.
  • A fragment embeds itself, directly or through another fragment.
  • Fragments are nested more than five levels deep.
  • Fragments expand a single label past 500 elements.
  • renderingOptions.renderingVersion is not 2. Fragments require version 2.

All of these are detected before anything is drawn, so a rejected request never produces a partial PDF.

Next Steps