labb 0.5.0 is out

Building CSS

Understand how labb scans component usage, prepares Tailwind sources, and builds the CSS for a Django project.

The labb CLI reads component usage in your templates and prepares the CSS classes those components need.

Why labb scans components

Tailwind scans templates for literal class names. It cannot infer the classes behind component props such as these.

<c-lb.button variant="primary" size="lg">Click me</c-lb.button>

Tailwind cannot determine that variant="primary" needs btn-primary or that size="lg" needs btn-lg. Without a safelist, those classes would be absent from the generated CSS.

Scan, prepare, and build

labb handles this in three stages.

Scan templates

Run labb scan to find labb components in your templates.

labb scan

It does three things.

  • Finds <c-lb.component-name> tags
  • Reads their attributes and values
  • Maps each value to classes from the component schema

The scan covers the following sources.

  1. Local templates listed in css.scan.templates
  2. components templates in subscribed css.packages groups

Prepare the classes

For each component, the scanner maps its attributes to classes.

  1. It identifies the component, such as button, card, or modal.
  2. It reads attributes such as variant="primary" and size="lg".
  3. It applies the component schema.

    • variant="primary" → btn-primary
    • size="lg" → btn-lg
    • Base classes are always included (e.g., btn)

The generated safelist lives at .labb/labb-component-classes.txt. .labb/ is gitignored.

/* Auto-generated by labb, do not edit */
/* Total classes: 15 */

btn
btn-primary
btn-lg
card
card-body
card-title
...

labb also writes .labb/labb.css. It brings together the safelist, raw utility sources from package literals groups, and inlined package CSS from imports. Keep one import in input.css.

/* labb css - don't remove this line */
@import "../.labb/labb.css";

Build the stylesheet

Run labb build to create the final CSS with Tailwind.

labb build

It regenerates labb’s generated CSS, reads your input stylesheet, and writes the optimised output.

Run the commands

# Scan component usage
labb scan

# Build the CSS
labb build

# Or combine the two
labb build --scan

Development workflow

During development, watch for changes.

# Rescan templates on change
labb scan --watch

# Rebuild CSS on change
labb build --watch

# Watch both
labb dev

Example

For this template:

<c-lb.button variant="primary" size="lg">Submit</c-lb.button>
<c-lb.card>
  <c-lb.card.body>
    <c-lb.card.title>Hello World</c-lb.card.title>
  </c-lb.card.body>
</c-lb.card>

The scanner adds these classes to the safelist.

btn
btn-primary
btn-lg
card
card-body
card-title

Dynamic values

Some prop values are unknown until the page runs. The scanner includes every class that the prop can produce according to its schema.

<c-lb.badge variant="$status:neutral">Active</c-lb.badge>   
<c-lb.badge :variant="user_variant">Active</c-lb.badge>      
<c-lb.badge variant="">Active</c-lb.badge>     

Each example keeps badge-neutral, badge-primary, badge-success, and the other valid variants in the built CSS. You do not need to safelist them by hand.

The scanner still needs a literal component and prop name. It can read <c-lb.badge> and look up variant, but cannot resolve <c-component is="...">. Safelist the required classes when the component name comes from runtime data.

Safelisting

When the scanner cannot see a class, add it to input.css.

@import "tailwindcss";
@source inline("btn-primary btn-secondary btn-lg btn-sm");

Keep custom safelists in input.css. labb regenerates .labb/ on each build.

The Tailwind safelisting documentation covers the other forms.