Tailwind CSS setup¶
Set up the Tailwind v4 build and safelist for Canvas Builder's classes.
Overview¶
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, not 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.js with content (your templates +
../../modules/custom/canvas_builder/components/**/*.twig) and a safelist
array holding the same exported list. v3 calls it content; v4 calls it
@source. Everything else is identical.
Verified
Every class in the shipped Tailwind profile compiles under
Tailwind v4 from the exported safelist: 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-fit, and the container widths, each with its
md:/lg:/xl: variant.
The per-side spacing classes are the reason you must export the safelist
rather than hand-write one: the box-model editor derives pt-6 from p-6
at 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 install inside 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, so 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, so 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 and columns.reverse have no class family. Both resolve
per viewport via CSS custom properties (--cb-columns-count-{breakpoint},
--cb-reverse-{breakpoint}), which one class per enum value cannot express.
section.container_type is base-only by design (mx-auto max-w-screen-lg is already a responsive container, so no infix is 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 shipped gradient rows in
bg_color_classesuse the Tailwind v4 spelling (bg-linear-to-b from-… to-…). On v3 these readbg-gradient-to-b; edit the rows if you are still on v3. heading_scale_classesrows carry acb-type-scalemarker alongside thetext-*size. That marker is what lets a wrapper-level size reach the heading inside. Keep it when you edit or add rows. See Styles.- The color swatch in the editor reads colors from the preview iframe at runtime, so make sure your compiled CSS is loaded in the preview or swatches won't 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.