|
| 1 | +# UI5 Web Components & Tailwind CSS |
| 2 | + |
| 3 | +Tailwind CSS works great with UI5 Web Components — you just need one configuration step to make sure Tailwind's CSS reset doesn't interfere with some web components. |
| 4 | + |
| 5 | +## Why is this needed? |
| 6 | + |
| 7 | +Tailwind's base layer (`@tailwind base`) includes a comprehensive CSS reset called **preflight**. It normalizes margins, fonts, headings, lists, and more across all elements. The most visible conflict with UI5 Web Components comes from rules like: |
| 8 | + |
| 9 | +```css |
| 10 | +*, ::before, ::after { |
| 11 | + border-width: 0; |
| 12 | + border-style: solid; |
| 13 | + box-sizing: border-box; |
| 14 | +} |
| 15 | +``` |
| 16 | + |
| 17 | +Some UI5 Web Components intentionally set styles directly on the **`:host` element** (the custom element tag itself, e.g. `<ui5-input>`) rather than on shadow-internal elements. This is a deliberate design choice: placing styles on the host makes components easier to customize from the outside. So preflight's resets may override the component's own `:host` styles, causing visual issues — most notably missing borders. |
| 18 | + |
| 19 | + |
| 20 | +## Configure Tailwind's preflight. |
| 21 | + |
| 22 | +Choose one of the two options below: |
| 23 | + |
| 24 | +### Option A: Disable preflight entirely (recommended for UI5-based apps) |
| 25 | + |
| 26 | +If your application primarily uses UI5 Web Components for its UI and doesn't rely on Tailwind's base reset for native HTML elements, you can disable preflight altogether. You still get all of Tailwind's utility classes — only the global CSS reset is removed. |
| 27 | + |
| 28 | +#### Tailwind v3 |
| 29 | + |
| 30 | +```js |
| 31 | +// tailwind.config.js |
| 32 | +module.exports = { |
| 33 | + corePlugins: { |
| 34 | + preflight: false, |
| 35 | + }, |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +#### Tailwind v4 |
| 40 | + |
| 41 | +Import Tailwind's parts individually and omit `preflight.css`: |
| 42 | + |
| 43 | +```css |
| 44 | +@layer theme, base, components, utilities; |
| 45 | + |
| 46 | +@import "tailwindcss/theme.css" layer(theme); |
| 47 | +/* @import "tailwindcss/preflight.css" layer(base); — removed */ |
| 48 | +@import "tailwindcss/utilities.css" layer(utilities); |
| 49 | +``` |
| 50 | + |
| 51 | +### Option B: Keep preflight with a targeted restore |
| 52 | + |
| 53 | +If you need Tailwind's preflight for other parts of your application, add a targeted rule to undo preflight for affected UI5 component host elements. |
| 54 | + |
| 55 | +`all: revert-layer` rolls back every property to the value it would have had without the current cascade layer (i.e. before preflight), in a single declaration. |
| 56 | + |
| 57 | +#### Tailwind v3 |
| 58 | + |
| 59 | +```css |
| 60 | +@tailwind base; |
| 61 | + |
| 62 | +/* Undo preflight for UI5 Web Components that you use */ |
| 63 | +@layer base { |
| 64 | + [ui5-button], |
| 65 | + [ui5-input], |
| 66 | + [ui5-step-input], |
| 67 | + [ui5-segmented-button-item], |
| 68 | + [ui5-li], |
| 69 | + [ui5-li-groupheader], |
| 70 | + [ui5-panel], |
| 71 | + [ui5-table-header-row], |
| 72 | + [ui5-table-row], |
| 73 | + [ui5-menu-separator], |
| 74 | + [ui5-bar], |
| 75 | + [ui5-dynamic-page-title], |
| 76 | + [ui5-li-notification] { |
| 77 | + all: revert-layer; |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | +@tailwind components; |
| 82 | +@tailwind utilities; |
| 83 | +``` |
| 84 | + |
| 85 | +#### Tailwind v4 |
| 86 | + |
| 87 | +The `@layer base` block is identical — only the import syntax changes: |
| 88 | + |
| 89 | +```css |
| 90 | +@import "tailwindcss"; |
| 91 | + |
| 92 | +/* Undo preflight for UI5 Web Components that you use */ |
| 93 | +@layer base { |
| 94 | + [ui5-button], |
| 95 | + [ui5-input], |
| 96 | + [ui5-step-input], |
| 97 | + [ui5-segmented-button-item], |
| 98 | + [ui5-li], |
| 99 | + [ui5-li-groupheader], |
| 100 | + [ui5-panel], |
| 101 | + [ui5-table-header-row], |
| 102 | + [ui5-table-row], |
| 103 | + [ui5-menu-separator], |
| 104 | + [ui5-bar], |
| 105 | + [ui5-dynamic-page-title], |
| 106 | + [ui5-li-notification] { |
| 107 | + all: revert-layer; |
| 108 | + } |
| 109 | +} |
| 110 | +``` |
| 111 | + |
| 112 | +## Using Tailwind with UI5 Web Components |
| 113 | + |
| 114 | +Tailwind utility classes work on UI5 component host elements for **page-level layout**: |
| 115 | + |
| 116 | +```html |
| 117 | +<ui5-button class="m-2">Spaced</ui5-button> |
| 118 | + |
| 119 | +<div class="flex gap-4 items-center"> |
| 120 | + <ui5-icon name="home"></ui5-icon> |
| 121 | + <ui5-label>Dashboard</ui5-label> |
| 122 | +</div> |
| 123 | + |
| 124 | +<ui5-card class="w-full max-w-md"> |
| 125 | + <ui5-card-header slot="header" title-text="Info"></ui5-card-header> |
| 126 | + <div class="p-4">Card content</div> |
| 127 | +</ui5-card> |
| 128 | +``` |
| 129 | + |
| 130 | +Layout utilities like `flex`, `gap-*`, `p-*`, `m-*`, and `w-*` all work as expected on the host elements. |
| 131 | + |
| 132 | +However, **Tailwind utilities cannot reach inside the Shadow DOM** of UI5 components. For component-internal styling, use UI5's own theming mechanisms: |
| 133 | + |
| 134 | +- **CSS custom properties** — override `--sapButton_BorderColor`, `--sapField_BorderColor`, etc. |
| 135 | +- **`::part()` selectors** — style exposed shadow parts when available |
| 136 | + |
| 137 | +This is by design: Tailwind handles your page layout, UI5 theming handles component appearance. |
0 commit comments