Canvas Builder — Tailwind CSS Setup¶
Canvas Builder's shipped Tailwind profile uses Tailwind's native responsive prefix convention (md:, lg:, xl:), not Bootstrap's infix style. Apply the Tailwind profile first (General → Framework → select Tailwind → Use this framework as my base), then follow the steps below.
1. Build setup (Tailwind v4)¶
Tailwind v4 is configured in CSS — no tailwind.config.js. In your theme's entry
stylesheet, import Tailwind and point @source at (a) a file holding Canvas
Builder's runtime classes and (b) the module's component templates:
/* src/input.css */
@import "tailwindcss";
/* Classes Canvas Builder applies from config at RUNTIME — Tailwind can't see
these by scanning source, so export them to a file (see step 2). */
@source "./canvas-builder-safelist.txt";
/* Static classes in Canvas Builder's own component templates. */
@source "../../../../modules/custom/canvas_builder/components";
Build:
npm install -D tailwindcss @tailwindcss/cli
npx @tailwindcss/cli -i src/input.css -o dist/main.css --minify
Then load dist/main.css from your theme's *.libraries.yml.
Tailwind v3? Use a
tailwind.config.jswithcontent(your templates +../../modules/custom/canvas_builder/components/**/*.twig) and asafelistarray holding the same exported list. v3 calls itcontent; v4 calls it@source. Everything else is identical.Verified: every class in the shipped Tailwind profile — colors, text-align,
p-*/m-*and their per-side forms (pt-*,px-*, …),gap-*,grid-cols-1..12,items-*/justify-*,flex-row-reverse,min-h-screen/h-fitand the container widths, each with itsmd:/lg:/xl:variant — compiles under Tailwind v4 from the exported safelist.The per-side spacing classes are the reason you must export the safelist rather than hand-write one: the box-model editor derives
pt-6fromp-6at runtime, so those names appear in no source file and Tailwind purges them unless the export lists them.npm workspaces gotcha: if your project root declares npm
workspaces,npm run/npm installinside the theme may resolve to the workspace root instead of the theme. Run the Tailwind CLI directly (as above) or build the theme outside the workspace.
2. Export the safelist¶
Canvas Builder applies its utility classes from config at runtime, so Tailwind can't discover them by scanning templates — you must hand it the list:
- From the editor: Administration → Canvas Builder → General → Framework →
Tailwind Safelist lists every class currently mapped in your style tables and
layout maps. Click the textarea to select all, and save it as the
@sourcefile (canvas-builder-safelist.txt). It updates automatically whenever you change style tables — re-export after any change. - Scripted (CI): generate the identical list with Drush so the build never drifts (run with the Tailwind profile active):
drush eval 'echo implode(PHP_EOL, \Drupal::service("canvas_builder.framework_profiles")->getSafelistClasses());' \
> themes/custom/<theme>/src/canvas-builder-safelist.txt
See FRAMEWORKS.md → Exporting & importing classes for moving the whole class config between sites.
Layout maps¶
The Tailwind profile pre-fills the layout matrices (General → Columns / Section) with Tailwind-native classes:
| Viewport | Prefix | Example |
|---|---|---|
| Mobile | (none) | gap-4 / justify-start |
| Tablet | md: |
md:gap-4 / md:justify-start |
| Desktop | lg: |
lg:gap-4 / lg:justify-start |
| Large Desktop | xl: |
xl:gap-4 / xl:justify-start |
columns.count is stored but not emitted. The column count resolves per
viewport via --cb-columns-count-{breakpoint}, which one class per enum value
cannot express. The grid-cols-* rows stay in config (so customisations
survive) and still reach the safelist, but the renderer no longer applies them.
section.container_type is base-only by design (mx-auto max-w-screen-lg is already a responsive container — no infix needed).
Alignment families are emitted as real, per-viewport classes. columns.valign/columns.halign (items-*/justify-*) and grid.grid_valign/grid.grid_halign (items-*/justify-items-*) all reach .cb-columns — Canvas Builder resolves which layout mode (columns vs. grid) is active at each viewport and only stamps the matching family's classes there, so both can be configured together without conflict. Tailwind ships justify-items-*, so grid_halign gets full coverage here (unlike Bootstrap, which has no such utility and stays CSS-var-only for that family).
Custom colors¶
Add your palette in CSS with @theme (v4), then update Administration →
Canvas Builder → Styles with matching option rows using the generated class
names:
/* src/input.css */
@import "tailwindcss";
@theme {
--color-primary: #1a56db;
--color-secondary: #6c757d;
}
(Tailwind v3: use theme.extend.colors in tailwind.config.js instead.)
Matching options in settings:
bg_color_classes:
- label: Primary
classes:
mobile: bg-primary
tablet: md:bg-primary
desktop: lg:bg-primary
large_desktop: xl:bg-primary
Notes¶
- The color swatch in the editor reads colors from the preview iframe at runtime — ensure your compiled CSS is loaded in the preview so swatches reflect the real theme palette.
- Re-export the safelist (step 2) and rebuild after every change to your style tables or layout maps, or new class options won't have any CSS.