Check out BugBytes overview of labb

Building CSS

Build Tailwind CSS for labb: CLI scans django-cotton templates, generates CSS, and integrates daisyUI with your Django project.

One of the main features of the labb CLI is the ability to automatically detect CSS classes based on component attributes in templates.

The Problem

Tailwind CSS CLI scans your templates for CSS classes, but it can only detect static class names. When you use labb components with attributes like:

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

Tailwind CSS CLI cannot automatically determine that variant="primary" should map to the btn-primary class, or that size="lg" should map to btn-lg. This means these classes would be purged from your final CSS, causing styling issues.

The Solution: Scan → Extract → Build

labb CLI solves this through a three-step process:

1. Template Scanning

The labb scan command analyzes your HTML templates to detect labb component usage:

labb scan

What it does:

  • Searches for <c-lb.component-name> tags in your templates
  • Parses component attributes and their values
  • Maps attributes to CSS classes using component schemas

Discovery Flow:

  1. Local templates: Scans css.scan.templates in your project
  2. Django apps: For each app in css.scan.apps:

    • If app has custom patterns: scans only those patterns
    • If app has no patterns: scans using default css.scan.templates
  3. Combines results: Merges all discovered templates for scanning

2. CSS Class Extraction

For each component found, the scanner:

  1. Identifies the component (e.g., button, card, modal)
  2. Extracts attributes (e.g., variant="primary", size="lg")
  3. Maps to CSS classes using the component's schema:

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

The extracted classes are written to a text file based on the labb.yaml configuration (default: static_src/labb-classes.txt):

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

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

3. CSS Building

The labb build command uses Tailwind CSS CLI to build your final CSS:

labb build

What it does:

  • Processes your input CSS file (e.g., static_src/input.css)
  • Tailwind CSS CLI reads the extracted classes from labb-classes.txt
  • Generates optimized output CSS with all required classes

The Complete Flow

Here's how the entire process works:

# 1. Scan templates and extract classes
labb scan

# 2. Build CSS with extracted classes
labb build

# (Or do both in one command)
labb build --scan

Development Workflow

For development, you can use watch modes:

# Watch templates and rescan on changes
labb scan --watch

# Watch CSS and rebuild on changes
labb build --watch

# Development mode: concurrent watch + scan
labb dev

Example

Given 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 extracts these classes:

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

Known Limitations

There are some limitations when dealing with dynamic content:

1. Dynamic Attribute Values

Django Cotton, which labb components are built on, allows you to set dynamic attribute values by adding a : colon before the attribute:

<c-lb.button :variant="userVariant" />

Where userVariant is a Python object in the context. labb scan cannot detect the value of these dynamic values, and therefore cannot map them to the correct CSS classes.

2. Dynamic Component References

Django Cotton also allows dynamic component referencing via:

<c-component is="component-name" />

labb scan cannot detect this dynamic component referencing at the moment, and therefore won't be able to extract the correct CSS mappings. This is a potential future feature.

Workarounds

When you encounter these limitations, you can use the following workarounds:

1. Tailwind CSS Safelisting

Employ one of the Tailwind CSS class safelisting methods in your input.css file. This allows you to explicitly tell Tailwind to include specific classes regardless of whether they're detected in your templates.

For example, in your input.css:

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

This ensures that btn-primary, btn-secondary, btn-lg, and btn-sm classes are always included in your final CSS.

For more details on safelisting methods, see the Tailwind CSS documentation on detecting classes in source files.

2. Limit Dynamic Usage

Where possible, limit the use of dynamically set attributes and components. Instead, use static attribute values that can be properly detected by the scanner:

<!-- Instead of this (not detected): -->
<c-lb.button :variant="userVariant" />

<!-- Use this (detected): -->
<c-lb.button variant="primary" />

This ensures that all your component classes are properly extracted and included in the final CSS build.