SuperAPI AI Directory

hebrew-tailwind-preset

Frontend & websites

View repository

Updated 10-15 15:32

About this skill

Hebrew Tailwind Preset

Tailwind CSS v4 recommended (current release v4.3, May 2026); v3.3+ also works: logical utilities arrived and the rtl:/ltr: variants were marked stable in v3.3.0. Works with React, Vue, Angular, Next.js, and Nuxt. No network required.

Instructions

Step 1: Install and Configure Tailwind v4 for RTL

See references/rtl-config.md for complete configuration reference.

Install the Tailwind v4 build plugin first. Tailwind v4 runs through a build plugin (Vite, PostCSS, or webpack) and is configured in CSS; tailwind.config.js is no longer loaded automatically. Pick the plugin matching your toolchain:

# Vite (recommended): install the first-party Vite plugin
npm install tailwindcss @tailwindcss/vite
// vite.config.js -- add the plugin
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  plugins: [tailwindcss()],
});
# PostCSS-based toolchains (Next.js, Webpack, etc.)
npm install tailwindcss @tailwindcss/postcss postcss
// postcss.config.mjs
export default {
  plugins: { '@tailwindcss/postcss': {} },
};

In v4 the @tailwindcss/postcss plugin handles @import inlining and vendor prefixing, so postcss-import and autoprefixer are no longer needed. For a plain webpack build without PostCSS, v4.2 added a loader: npm install @tailwindcss/webpack, then list '@tailwindcss/webpack' after 'css-loader' in the .css rule's use array.

Then load Hebrew fonts with font-display: swap (via a Google Fonts <link> or an @font-face rule) to avoid a Flash of Invisible Text while the Hebrew font file loads. The loading snippet follows the configuration blocks below.

Tailwind v4 (CSS-first configuration):

/* app.css -- imported by your build entry */
@import "tailwindcss";

@theme {
  /* Hebrew font stacks */
  --font-sans: 'Heebo', 'Assistant', 'Noto Sans Hebrew', sans-serif; /* default font for html, body and form controls */
  --font-hebrew: 'Heebo', 'Assistant', 'Noto Sans Hebrew', sans-serif;
  --font-hebrew-serif: 'Frank Ruhl Libre', 'David Libre', serif;
  --font-mono: 'Cousine', 'Fira Code', monospace; /* Cousine carries Hebrew glyphs for code comments; Fira Code does not */

  /* Hebrew-optimized type scale */
  --text-xs: 0.8125rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 1.875rem;
  --text-4xl: 2.25rem;

  /* Hebrew line heights (taller than Latin defaults).
     The --leading-* namespace generates leading-<name> utilities,
     so these names are what make leading-hebrew, leading-hebrew-tight
     and leading-hebrew-relaxed exist. Naming them --leading-tight /
     --leading-normal / --leading-relaxed instead would only override
     the built-in scale and leave every leading-hebrew* class empty. */
  --leading-hebrew: 1.7;
  --leading-hebrew-tight: 1.4;
  --leading-hebrew-relaxed: 1.9;
}

Tailwind v3 (JavaScript configuration):

// tailwind.config.js
module.exports = {
  content: ['./src/**/*.{html,js,jsx,tsx}'],
  theme: {
    extend: {
      fontFamily: {
        hebrew: ['Heebo', 'Assistant', 'Noto Sans Hebrew', 'sans-serif'],
        'hebrew-serif': ['Frank Ruhl Libre', 'David Libre', 'serif'],
      },
      lineHeight: {
        'hebrew': '1.7',
        'hebrew-tight': '1.4',
        'hebrew-relaxed': '1.9',
      },
    },
  },
  plugins: [],
};

Load the Hebrew fonts with font-display: swap. Either add a Google Fonts <link> in your HTML head:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Heebo:wght@400;500;700&family=Assistant:wght@400;600&family=Cousine&display=swap" rel="stylesheet">

Or self-host with an @font-face rule inside the same CSS file as your @theme block:

@font-face {
  font-family: 'Heebo';
  src: url('/fonts/heebo-variable.woff2') format('woff2');
  font-weight: 400 700;
  font-display: swap;
}

The &display=swap query param (link) and the font-display: swap descriptor (@font-face) both give the font an extremely small block period and an infinite swap period: the browser shows fallback text almost at once and swaps in the Hebrew font whenever it arrives, instead of hiding text while it loads.

Next.js: wire next/font through @theme inline. When you self-host with next/font (recommended for Next.js: no external request, no layout shift), the font is exposed as a CSS variable. Point --font-sans at it, because Preflight takes the page's default font from --font-sans and form controls inherit it (font: inherit), so Hebrew becomes the default everywhere without a font-hebrew class on every element:

/* app/globals.css */
@import "tailwindcss";
@theme inline {
  --font-sans: var(--font-heebo); /* --font-heebo comes from next/font */
  --font-hebrew: var(--font-heebo);
}
// app/layout.tsx
import './globals.css';
import { Heebo } from 'next/font/google';
const heebo = Heebo({ subsets: ['hebrew', 'latin'], variable: '--font-heebo' });
// <html lang="he" dir="rtl" className={heebo.variable}> ... </html>

Keep heebo.variable on <html>, not <body>. Preflight applies the default font on html, so a variable defined lower down never reaches it, with or without inline, and the page silently falls back to Tailwind's default sans stack. Why inline as well: a theme variable that references another variable is resolved where the theme variable is defined (:root), not where the utility is used. With inline, Tailwind writes var(--font-heebo) straight into utilities such as font-hebrew, so they resolve wherever the class is used. The build succeeds either way, which is why both mistakes are easy to miss.

Step 2: Use Logical Property Utilities

Tailwind v4's native logical utilities and rtl:/ltr: variants cover RTL on their own, so the old community tailwindcss-rtl plugin is no longer needed. Always prefer logical utilities over physical directional ones:

Physical (avoid) Logical (use) RTL Behavior
ml-4 ms-4 Right margin in RTL
mr-4 me-4 Left margin in RTL
pl-4 ps-4 Right padding in RTL
pr-4 pe-4 Left padding in RTL
left-0 inset-s-0 Right: 0 in RTL (v4.2+; start-0 is the deprecated alias)
right-0 inset-e-0 Left: 0 in RTL (v4.2+; end-0 is the deprecated alias)
border-l border-s Right border in RTL
border-r border-e Left border in RTL
rounded-l-lg rounded-s-lg Right rounded in RTL
rounded-r-lg rounded-e-lg Left rounded in RTL
text-left text-start Right-aligned in RTL
text-right text-end Left-aligned in RTL
scroll-ml-4 scroll-ms-4 Right scroll margin in RTL
mt-4 / mb-4 mbs-4 / mbe-4 Block-axis margin (v4.2+)
pt-4 / pb-4 pbs-4 / pbe-4 Block-axis padding (v4.2+)
border-t / border-b border-bs / border-be Block-axis border (v4.2+)
top-0 / bottom-0 inset-bs-0 / inset-be-0 Block-axis inset (v4.2+)
w-40 / h-20 inline-40 / block-20 Logical sizing (v4.2+, also min-inline-*, max-block-*)

Tailwind v4.2 inset rename. As of v4.2 (18 February 2026, recapped in the v4.3 blog post) the logical positioning utilities start-*/end-* are deprecated in favor of inset-s-*/inset-e-* (so they line up with inset-bs-*/inset-be-*). The old names still work, but prefer inset-s-0/inset-e-0 in new code. This rename affects only inset/positioning; the margin/padding/border utilities ms-*/me-*/ps-*/pe-*/border-s/border-e are unchanged. Arbitrary values compose with logical utilities too (e.g. ms-[3px], inset-s-[10px]).

Use @source, not a content array. Tailwind v4 auto-detects your templates, so a v3 reader will look for the content: [...] key and find nothing. Paths Tailwind does not scan (an external UI package, anything in .gitignore) are registered in CSS instead, relative to the stylesheet: @source "../node_modules/@acmecorp/ui-lib";. This matters for Hebrew markup that lives in a shared component library.

Step 3: Use Dir Variants for RTL-Specific Styles

How the variants match. In v4, rtl: compiles to :where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) and ltr: to the mirror selector. Set dir="rtl" on <html> before relying on any rtl: utility below. Two consequences are easy to miss. First, ltr: utilities already apply on a page with no dir at all, because the default direction is LTR. Second, a nested dir="auto" island that resolves to LTR inside an RTL page matches BOTH variants: rtl: through the [dir="rtl"] * arm and ltr: through :dir(ltr). For mixed Hebrew/English user content in such islands, use logical utilities (ms-*, text-start) instead of rtl:/ltr: pairs.

Dark mode in v4. The v3 darkMode config key is gone. In v4 you opt into class-based dark mode in CSS with @custom-variant dark (&:where(.dark, .dark *));, then combine freely with direction, e.g. class="dark:bg-gray-900 rtl:bg-linear-to-l". Set dir="rtl" on <html> and toggle .dark on the same element.

When you need direction-specific overrides:

<!-- Root setup -- dir="rtl" here is what activates every rtl: variant -->
<html lang="he" dir="rtl">

<!-- Dir variant usage: flip a directional arrow horizontally -->
<a class="inline-flex items-center gap-2">
  <span>הבא</span>
  <span class="rtl:-scale-x-100">&#8594;</span>
</a>

<!-- Do NOT add rtl:flex-row-reverse: dir="rtl" already runs a flex row
     right to left, so reversing it again restores LTR visual order -->

<!-- Icon mirroring for directional icons -->
<button class="flex items-center gap-2">
  <svg class="rtl:scale-x-[-1]"><!-- arrow icon --></svg>
  <span>חזרה</span>
</button>

<!-- Push to the end in both directions: one logical class, no variant pair -->
<div class="ms-auto">...</div>

Step 4: Hebrew Typography Utilities

<!-- Hebrew body text with proper settings -->
<body dir="rtl" class="font-hebrew text-base leading-hebrew
                        tracking-normal">

  <!-- Hebrew heading -->
  <h1 class="text-3xl font-bold leading-hebrew-tight">
    כותרת ראשית
  </h1>

  <!-- Hebrew paragraph -->
  <p class="text-base leading-hebrew">
    טקסט גוף בעברית.
  </p>

  <!-- Mixed Hebrew + English content -->
  <p class="text-base leading-hebrew">
    פריט מספר <span dir="ltr" class="font-mono">ORD-12345</span> אושר
  </p>
</body>

Step 5: RTL-First Component Patterns with Tailwind

RTL-first card:

<div class="rounded-lg border border-gray-200 p-6">
  <div class="flex items-center justify-between mb-4
              border-b border-gray-100 pb-4">
    <h3 class="text-lg font-bold">כותרת הכרטיס</h3>
    <span class="text-sm text-gray-500">פעיל</span>
  </div>
  <p class="text-base leading-hebrew text-gray-700">
    תוכן הכרטיס עם טקסט בעברית.
  </p>
  <div class="mt-4 flex gap-3">
    <button class="bg-blue-600 text-white px-4 py-2 rounded-md">
      אישור
    </button>
    <button class="border border-gray-300 px-4 py-2 rounded-md">
      ביטול
    </button>
  </div>
</div>

RTL-first navigation:

<nav dir="rtl" class="flex items-center justify-between
                       px-6 py-4 bg-white border-b">
  <div class="flex items-center gap-3">
    <img src="/logo.svg" alt="לוגו" class="h-8">
    <span class="font-bold text-xl">שם האתר</span>
  </div>
  <ul class="flex gap-6 text-sm font-medium">
    <li><a href="/" class="text-blue-600">ראשי</a></li>
    <li><a href="/about" class="text-gray-600">אודות</a></li>
    <li><a href="/contact" class="text-gray-600">צור קשר</a></li>
  </ul>
</nav>

RTL-first sidebar layout:

<div class="grid grid-cols-[280px_1fr] min-h-screen">
  <!-- Sidebar: appears on right in RTL automatically -->
  <aside class="border-e border-gray-200 pe-6 p-4">
    <nav class="space-y-2">
      <a href="#" class="block ps-4 py-2 rounded-md
                         bg-blue-50 text-blue-700 border-s-4
                         border-blue-600">לוח בקרה</a>
      <a href="#" class="block ps-4 py-2 rounded-md
                         text-gray-600">הגדרות</a>
    </nav>
  </aside>
  <!-- Main content -->
  <main class="p-6">
    <h1 class="text-2xl font-bold mb-6">לוח בקרה</h1>
  </main>
</div>

Step 6: Form Utilities for Hebrew

<form dir="rtl" class="max-w-lg space-y-6">
  <div>
    <label for="name" class="block text-sm font-medium
                              text-gray-700 mb-2">שם מלא</label>
    <input id="name" type="text"
           class="w-full px-4 py-3 border border-gray-300
                  rounded-md text-base font-hebrew
                  focus:outline-none focus:ring-2
                  focus:ring-blue-500">
  </div>

  <div>
    <label for="phone" class="block text-sm font-medium
                               text-gray-700 mb-2">טלפון</label>
    <input id="phone" type="tel" dir="ltr"
           placeholder="05X-XXXXXXX"
           class="w-full px-4 py-3 border border-gray-300
                  rounded-md text-base
                  focus:outline-none focus:ring-2
                  focus:ring-blue-500">
  </div>

  <div>
    <label for="message" class="block text-sm font-medium
                                 text-gray-700 mb-2">הודעה</label>
    <textarea id="message" rows="4"
              class="w-full px-4 py-3 border border-gray-300
                     rounded-md text-base font-hebrew
                     leading-hebrew
                     focus:outline-none focus:ring-2
                     focus:ring-blue-500"></textarea>
  </div>

  <button type="submit"
          class="w-full bg-blue-600 text-white py-3
                 rounded-md font-medium text-base
                 hover:bg-blue-700 transition-colors">
    שליחה
  </button>
</form>

Examples

Example 1: Set Up Tailwind for Hebrew Project

User says: "Configure Tailwind for my Hebrew web app" Result: Add Hebrew font families to Tailwind theme, configure Hebrew-optimized line heights, set up dir="rtl" on root HTML element, and demonstrate using logical utilities (ms-/me-/ps-/pe-) instead of physical ones (ml-/mr-/pl-/pr-).

Example 2: Convert LTR Tailwind Component to RTL

User says: "Make this Tailwind component work in Hebrew RTL" Result: Replace all physical utility classes with logical equivalents (ml- to ms-, pl- to ps-, text-left to text-start, border-l to border-s, rounded-l to rounded-s), add rtl: variants for directional icons, and set font-hebrew class on text elements.

Example 3: Build Hebrew Dashboard with Tailwind

User says: "Create a Hebrew admin dashboard layout with Tailwind" Result: Build grid layout with RTL sidebar (border-e, pe-6), navigation with Hebrew font and RTL flow, card components using logical spacing, and form elements with proper Hebrew typography (font-hebrew, leading-hebrew).

Bundled Resources

References

  • references/rtl-config.md -- Complete Tailwind CSS RTL configuration reference: v4 CSS-first and v3 JavaScript config examples, full physical-to-logical utility mapping table, dir variant usage patterns, Hebrew font stack presets, typography token definitions, and migration guide from physical to logical utilities.

Gotchas

  • Tailwind CSS v3+ supports RTL variants (rtl: prefix), but agents often do not use them, instead hardcoding mr-4 when they should use ms-4 (margin-start) for RTL compatibility.
  • space-x-* IS direction-aware in Tailwind v4: it compiles to margin-inline-start / margin-inline-end, so it already flips under dir="rtl" and needs no override. Do NOT add rtl:space-x-reverse - that sets --tw-space-x-reverse: 1 and moves the spacing to the wrong side. space-x-reverse is only for children rendered in reverse DOM order (flex-row-reverse), in which case it belongs on the same element regardless of direction. The physical-margin behaviour agents remember is Tailwind v3. gap-4 is still the better choice for flex and grid because space-x-* breaks on wrapped rows.
  • Custom font declarations for Hebrew must include font-display: swap to prevent FOIT (Flash of Invisible Text). Agents may omit this, causing Hebrew text to disappear during font loading.
  • Tailwind's text-left and text-right are physical properties. Use text-start and text-end classes for RTL-aware alignment. Agents default to physical direction classes.
  • Gradient and shadow direction is physical, not logical: bg-linear-to-r and offset shadows do not flip in RTL. Add a rtl: override (e.g. rtl:bg-linear-to-l) when the direction is meaningful. Use the v4 bg-linear-* names; bg-gradient-* still compiles as a legacy alias but is no longer the documented spelling.

Reference Links

Source URL What to Check
Tailwind CSS theme docs https://tailwindcss.com/docs/theme Current configuration syntax, v4 migration notes
Tailwind RTL / logical properties https://tailwindcss.com/docs/hover-focus-and-other-states#rtl-support rtl: and ltr: variants
Google Fonts – Heebo https://fonts.google.com/specimen/Heebo Hebrew UI font, weights, loading snippet
Google Fonts – Assistant https://fonts.google.com/specimen/Assistant Hebrew body font
MDN font-display https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@font-face/font-display swap value and FOIT mitigation

Troubleshooting

Error: "Tailwind logical utilities not working"

Cause: Using older Tailwind version without logical property support Solution: Logical utilities (ms-, me-, ps-, pe-, and inset inset-s-/inset-e-, formerly start-/end-) require Tailwind v3.3+, the same release that marked the rtl:/ltr: variants stable. On v3.0-3.2 the variants were still experimental and printed warnings, so upgrade rather than falling back to rtl:mr-4 ltr:ml-4 pairs. Tailwind v4 has full logical property support built in; the inset-s-*/inset-e-* names landed in v4.2 (the older start-*/end-* still resolve).

Error: "Font not applying with font-hebrew class"

Cause: Hebrew font family not defined in Tailwind configuration Solution: Add the Hebrew font stack to your Tailwind theme under fontFamily.hebrew. Ensure the font CSS is imported (Google Fonts link or local @font-face). Verify the class name matches your config key.

Error: "Sidebar appears on wrong side in RTL"

Cause: Grid or flex layout not respecting dir attribute Solution: CSS Grid and Flexbox automatically respect dir="rtl". Ensure dir="rtl" is set on the html element. Use logical properties for borders (border-e instead of border-r) and padding (pe- instead of pr-). Keep the CSS direction value consistent with the HTML dir attribute - prefer setting direction via the dir attribute so the cascade and the rtl:/ltr: variants stay in sync; if you do set direction in CSS, make sure it matches dir.