@lform/lwind
v4.1.0
Published
The Lform tailwind framework
Readme
Lwind - Lform Tailwind Setup
The Lwind frontend styling system is designed to use as many Tailwind default-approaches as possible while also allowing for the flexibility required to implement designs produced using the Lform design system. The package is a CSS-first Tailwind 4 setup — theme tokens, utilities, and components are all defined in CSS. Lwind is fully aligned to the Lform design system.
- Requires Tailwind 4.0.0+
Resources
- Lform Design System
- Tailwind Documentation
- Tailwind UI Kits - For reference for building components
Installation
Adding the Lwind system to a project is relatively straightforward:
- Run
npm i @lform/lwind - Included in the package are example entry files you can copy into your project and adapt as needed:
- https://github.com/lform/lwind/blob/master/css/main.example.css
- https://github.com/lform/lwind/blob/master/css/editor.example.css
- NOTE: To customize or override any of the Lwind CSS files, copy the file in question from the package or create a new one in the appropriate directory and update your imports accordingly. You can also include only the components and vendor files your project needs.
- Create your main stylesheet entry, typically based on
css/main.example.css, and adjust the imports for your project. - Update the theme tokens in
css/_theme.cssor your local equivalent to match your project's design system. - Run the build system to confirm that everything is working.
Building
The following scripts are available in the package.json file, if the project uses a build system, the commands may be different.
npm run dev- Builds the development stylesheet fromcss/main.csstodist/app.cssnpm run watch- Builds the development stylesheet and watches for changesnpm run prod- Builds the minified production stylesheet atdist/app.min.css
The following package.json scripts can be added if there is no existing build system (adjust the paths accordingly):
{
"scripts": {
"dev": "npx @tailwindcss/cli -i ./css/main.css -o ./dist/app.css",
"watch": "npx @tailwindcss/cli -i ./css/main.css -o ./dist/app.css --watch",
"prod": "NODE_ENV=production npx @tailwindcss/cli -i ./css/main.css -o ./dist/app.min.css --minify",
"demo": "mkdir -p ./dist && npm run dev && cp ./demo/kitchen-sink.html ./dist/kitchen-sink.html"
}
}Kitchen Sink Demo
A static kitchen sink demo is included for validating the current component and vendor styling in a browser.
npm run demo- Buildsdist/app.cssand copies the demo page todist/kitchen-sink.html
The demo exercises typography, colors, buttons, containers, form messages, flex grid, rich text (standard and inverted), general utilities, WordPress pagination, and Statamic pagination.
Tailwind Config
Tailwind is configured via _theme.css using CSS variables for theme tokens (the standard Tailwind 4 approach to theming). This allows for easy theming and overrides by simply changing the CSS variable values.
IMPORTANT: Always configure the
_theme.cssfile with your project's design tokens BEFORE starting any frontend coding. The default values are there to be customized to align with the project's design system. Implementing them after the fact can lead to a lot of extra work and overrides.
Tailwind Plugins
- @tailwindcss/forms - Used to provide default baseline form styling
- @iconify/tailwind4 - Included by default for icon utilities via Iconify
Breakpoints
The default breakpoints included in Tailwind are used.
Spacing / Gaps
- Designs are implemented using a base spacing sizing of 4 pixels.
- This is Tailwind's default spacing system, refer to the documentation as necessary.
Colors
Branding Colors
Palette
- Primary
- Default:
primary - Light:
primary-light - Dark:
primary-dark - Foreground:
primary-fg— text color for use on aprimarybackground (e.g. button labels)
- Default:
- Secondary
- Default:
secondary - Light:
secondary-light - Dark:
secondary-dark - Foreground:
secondary-fg
- Default:
- Tertiary
- Default:
tertiary - Light:
tertiary-light - Dark:
tertiary-dark - Foreground:
tertiary-fg
- Default:
Guidelines
- Avoid more than 3 core brand colors unless absolutely necessary.
- Remove tertiary or secondary if not needed for the project.
- All brand colors must have a
light,dark, andfgvariant defined in_theme.css. - Never use the
fgcolor except in the context of text on the matching background color. For example,primary-fgshould only be used for text on aprimarybackground, never on its own or on a different background color.
Accent Colors
Palette
accent-{name}(example:accent-cement,accent-sand,accent-olive)
Guidelines
- Accents are brand-aligned colors that are not grays.
- Naming should be descriptive of the color (e.g.
accent-cementinstead ofaccent-1). - Use numeric naming as a fallback if no descriptive name fits.
- If the accents are similar, add a tailwind color scale (e.g.
accent-cement-100,accent-cement-200, etc.) for more flexibility.
Gray Scale
Palette
gray-50gray-100gray-200gray-300gray-400gray-500gray-600gray-700gray-800gray-900gray-950
Guidelines
- Use "gray" (not "grey").
- A full 11-step scale is included by default.
- Add intermediate steps (e.g.
gray-150) directly in_theme.cssif a project needs more granularity.
Feedback Colors
feedback-infofeedback-successfeedback-warningfeedback-error
Constants
black,whiteblack-transparent,white-transparent— semi-transparent variants for overlays and tintstransparent— fully transparent
Social Colors
Common social media brand colors are pre-defined under the social-{platform} namespace (e.g. social-facebook, social-instagram, social-youtube). Include or remove entries in _theme.css as needed per project.
Typography
Fonts Available
There are 3 types of fonts in Lwind:
font-body- The body font used on the site by defaultfont-header- The main header fontfont-accent- Usually used for small text items in a utility context, eg blog post dates
Font Scaling
The typography system uses a modular scale for token definitions and fluid modular scale utilities for responsive type.
- Base is
16pxwith1.125xscaling - The scale included with Lwind goes from
-3to13 - Fixed-size utilities (
text-ms-*) map directly to pixel values from the scale - Fluid utilities (
text-fms-*) useclamp()to scale smoothly between viewport sizes — these are used by header and accent classes at positive scale steps - Refer to the font scale reference for the full list.
Font Size Utilities
-text-ms-3= 11px-text-ms-2= 12px-text-ms-1= 14pxtext-ms-0= 16pxtext-ms-1= 18pxtext-ms-2= 20pxtext-ms-3= 22pxtext-ms-4= 25pxtext-ms-5= 28pxtext-ms-6= 32pxtext-ms-7= 36pxtext-ms-8= 41pxtext-ms-9= 46pxtext-ms-10= 51pxtext-ms-11= 58pxtext-ms-12= 65pxtext-ms-13= 73px
Fluid Size Utilities
text-fms-1= ~18px fluidtext-fms-2= ~20px fluidtext-fms-3= ~22px fluidtext-fms-4= ~25px fluidtext-fms-5= ~28px fluidtext-fms-6= ~32px fluidtext-fms-7= ~36px fluidtext-fms-8= ~41px fluidtext-fms-9= ~46px fluidtext-fms-10= ~51px fluidtext-fms-11= ~58px fluidtext-fms-12= ~65px fluidtext-fms-13= ~73px fluid
Header and accent utility classes
Modular scale header utility classes have been included that include the header font with a default line-height of 1.2. Headers with default line-heights will appear too spaced out between the lines, especially at larger font sizes.
Header Font Classes
Negative steps use fixed pixel sizes; positive steps use fluid clamp() sizing that scales with the viewport.
-h-ms-3= 11px (fixed)-h-ms-2= 12px (fixed)-h-ms-1= 14px (fixed)h-ms= base header font + header line-height (no size override)h-ms-1= ~18px fluidh-ms-2= ~20px fluidh-ms-3= ~22px fluidh-ms-4= ~25px fluidh-ms-5= ~28px fluidh-ms-6= ~32px fluidh-ms-7= ~36px fluidh-ms-8= ~41px fluidh-ms-9= ~46px fluidh-ms-10= ~51px fluidh-ms-11= ~58px fluidh-ms-12= ~65px fluidh-ms-13= ~73px fluid
Accent Font Classes
Accent helpers are generally used for smaller text, labels, and emphasis styles. They apply font-accent and the matching scale size.
-ac-ms-3= 11px (fixed)-ac-ms-2= 12px (fixed)-ac-ms-1= 14px (fixed)ac-ms= base accent font (no size override)ac-ms-1= ~18px fluidac-ms-2= ~20px fluid
Line Heights
All line-height tokens use unitless ratios, which scale cleanly with each element's font size and avoid the inheritance issues caused by percentage-based values.
--leading-header=1.2— Headings and display text, tighter to avoid excessive spacing at large sizes--leading-tight=1.25— Compact UI text--leading-normal=1.5— Body copy and general content--leading-loose=1.75— Spacious layouts or accessibility-sensitive contexts
Border Radius
Three radius sizes are defined in _theme.css and used throughout components. Override as needed per project.
--radius-sm=4px—rounded-sm--radius-md=8px—rounded-md--radius-lg=12px—rounded-lg
Richtext
A custom rich-text implementation is used for all rich-text areas by adding a rich-text class to any area with rich text.
- Add
rich-text invertedto apply white text and adjusted link/list marker colors for rich text on dark backgrounds. - Links inside rich text are always underlined — this is a WCAG requirement and should not be overridden.
- YouTube and Vimeo iframes are automatically forced to
width: 100%with a16/9aspect ratio. - Includes a modernized flow-spacing model, better heading rhythm, improved list styling, cleaner blockquotes, and robust media/table handling.
- WordPress-specific rich text handling is separated into vendor files so editor and frontend content can share the base
rich-textstyles while still supporting WordPress-specific markup. css/editor.cssis available for editor-specific builds and includes the editor base styles plus the shared component stack needed for rich text authoring.- Relevant vendor files, enable and disable them as needed:
css/vendors/_wp-richtext.css
Tailwind Utilities & Components
Buttons
Buttons are utility-first and are intended to be composed by stacking modifier classes on top of the base button utility.
Colors
button- Base button and defaultprimarysolid buttonbutton-secondary- Secondary color variantbutton-tertiary- Tertiary color variant (remove if not needed for the project)
Sizing
button-smbutton-md- Default sizebutton-lg
Format
- Solid - Default format via
button button-outline
Elements
button-icon- Button with an icon, adds padding and size adjustments for icons inside buttonsbutton-full- Full width button
States
- Default - Native button styling
button-hover- Forces hover state stylingbutton-focus- Forces focus-visible stylingbutton-disabled- Forces disabled styling
Native states are also included for :hover, :focus-visible, :disabled, [disabled], and [aria-disabled="true"].
Examples
- Primary solid medium:
class="button" - Secondary outline large:
class="button button-secondary button-outline button-lg" - Full width button with icon:
class="button button-full button-icon"
Containers
Tailwind's default containers are disabled in favor of a fluid container system backed by theme tokens.
- Containers are auto-centered with
margin-left&margin-rightset toauto. - Padding is responsive:
20pxon mobile,24pxat768pxand above. - Container widths & padding are configured through CSS theme variables:
--container-padding(desktop) and--container-padding-mobile container-*utilities resolve against the matching--container-*theme tokens- If a class of
px-0is added to a container, the padding will be disabled - If a class of
mx-0is added to a container, the auto-centering margin will be disabled.
Classes & Default Sizes
container- Default max width of1440pxcontainer-xs-640pxcontainer-sm-768pxcontainer-md-1024pxcontainer-lg-1280pxcontainer-xl-1440px(default)container-2xl-1600pxcontainer-adaptive- See below for details on this special adaptive container class
Adaptive Container
Rather than stretching fluidly to a single max-width, this container snaps through a series of fixed breakpoint widths (768px → 1024px → 1280px → 1440px). This keeps the layout at a predictable, design-friendly width at each viewport range and avoids awkward, time-consuming in-between responsive fixes. Useful when a design is defined at specific widths and fluid scaling between them causes layout issues.
Pagination
css/vendors/_wp-pagination.cssadds support for WordPress paginationcss/vendors/_statamic-pagination.csscontains Statamic-specific pagination styles
Forms
Form messaging uses a form-message component for displaying inline feedback. The base class provides padding, background, and border-radius; modifier classes apply feedback colors from the theme tokens.
Classes
form-message- Base message wrapperform-message-header- Bold header inside a message block
Color Modifiers
info- Uses--color-feedback-infosuccess- Uses--color-feedback-successwarning- Uses--color-feedback-warningerror- Uses--color-feedback-error
WCAG Compliance Requirements
- All fields must have visible labels placed above the input
- Required fields must use an asterisk indicator — color alone is not sufficient
- Placeholder text is not a substitute for labels
- Form feedback must not rely on color alone — always include the state name (e.g. "Error: ...")
Vendor Form Support
css/vendors/_wp-forms.css- Gravity Forms baseline stylingcss/vendors/_statamic-forms.css- Statamic form styling
Example
<div class="form-message success">
<p class="form-message-header">● Success</p>
<p>Your inquiry has been submitted.</p>
</div>Flex Grid
CSS Grid has a limitation in that it does not support centering columns or aligning them outside of the grid structure. This issue is addressed by using a Flex-based grid, which creates a full-width grid with a specified number of columns. In a Flex Grid, any remaining columns at the bottom can be centered effectively.
- Use the class
flex-gridto implement a flex grid. - Flex Grid defaults to a single column. To change this, use
flex-grid-cols-{n}, replacing{n}with the desired number of columns (1 to 10). - Adjust horizontal spacing between Flex Grid items with
flex-grid-gap-{n}. Gaps from0.5to28(2px–112px) are included — see the full list below. - Flex Grid is fully responsive. Use
sm:,md:, andlg:prefixes withflex-grid-cols-{n}orflex-grid-gap-{n}for responsive layouts. - For vertical spacing, use Tailwind's native
gap-y-{n}since Flex Grid, powered by Flexbox, does not add vertical spacing by default. - IMPORTANT: Avoid using
margin-leftormargin-righton elements withflex-grid, as it disrupts the grid layout. Instead, apply margins to a container element.
Classes & Sizing
Base Class
flex-grid
Column Classes
flex-grid-cols-1flex-grid-cols-2flex-grid-cols-3flex-grid-cols-4flex-grid-cols-5flex-grid-cols-6flex-grid-cols-7flex-grid-cols-8flex-grid-cols-9flex-grid-cols-10
Gap Classes
flex-grid-gap-0.5= 2pxflex-grid-gap-1= 4pxflex-grid-gap-1.5= 6pxflex-grid-gap-2= 8pxflex-grid-gap-2.5= 10pxflex-grid-gap-3= 12pxflex-grid-gap-3.5= 14pxflex-grid-gap-4= 16pxflex-grid-gap-5= 20pxflex-grid-gap-6= 24pxflex-grid-gap-7= 28pxflex-grid-gap-8= 32pxflex-grid-gap-9= 36pxflex-grid-gap-10= 40pxflex-grid-gap-11= 44pxflex-grid-gap-12= 48pxflex-grid-gap-14= 56pxflex-grid-gap-16= 64pxflex-grid-gap-20= 80pxflex-grid-gap-24= 96pxflex-grid-gap-28= 112px
Example Usage
<div class="flex-grid flex-grid-cols-2 md:flex-grid-cols-3 flex-grid-gap-2">
<!-- A 3 column flex grid with an 8 pixel gap, 2 columns on tablet -->
</div>General Utilities
Miscellaneous utility classes defined in css/utilities/_elements.css.
Layout
absolute-center- Absolutely positions an element at the center of its nearest positioned ancestor viatranslate(-50%, -50%)clearfix- Clears floated children using a::afterpseudo-elementpy-section- Standard section vertical padding, fluid across breakpoints (py-18→2xl:py-28)
Video
video-frame- Forces an<iframe>inside to 16:9 aspect ratio using padding-bottom technique; compatible across browsers
Image Color Controls
svg-to-white- Applies CSS filter to turn an image/icon fully whitesvg-to-black- Applies CSS filter to turn an image/icon fully black
Accent Text Coloring
Used to apply brand color to inline <span> elements inside a parent, typically for CMS-authored headings where editors wrap a word in a span.
has-primary-text- Colors child<span>elements withtext-primaryhas-secondary-text- Colors child<span>elements withtext-secondary
Iconography
Iconify is baked into Lwind by default through the Tailwind CSS entrypoint:
@plugin "@iconify/tailwind4";The package also includes @iconify/json, so developers can use Iconify selectors immediately without extra setup in a standard Lwind install.
How To Use It
- Find an icon on Iconify.
- Copy the Tailwind CSS selector for that icon.
- Use the selector as a class on an inline element such as
spanori. - Size and color the icon with normal Tailwind utilities.
<span class="icon-[mdi-light--home] inline-block text-2xl text-primary"></span>
<span class="icon-[tabler--arrow-right] inline-block text-gray-700 dark:text-white"></span>Notes
- The default selector prefix is
icon-, so classes follow theicon-[collection--name]pattern. - Icon names use
--between the icon set prefix and the icon name, for examplemdi-light--home. - Icons inherit
currentColor, so text color utilities also control icon color. - Use
inline-block, width, height, or text-size utilities as needed depending on layout.
Sourcing Guidance
The sourcing hierarchy still applies across projects:
- Iconify — default source for all icons. Use the Iconify Figma plugin to keep design and development in sync.
- Flaticon — fallback when Iconify doesn't have a suitable option.
- AI-generated icons — last resort only. Must be reviewed carefully for style consistency, clarity, licensing risk, and brand fit before use.
Avoid designs that depend on a large number of unique icons unless the project scope explicitly accounts for that work. Use icons where content repeats or follows a clear pattern — header items, footer items, resource lists, and other recurring interface elements.
Relevant documentation:
Dark Mode
Lwind overrides Tailwind's default dark mode behavior in the CSS entrypoint:
@variant dark (&:where(.dark, .dark *));This means dark:* utilities are class-driven and can be scoped to any wrapper, not just the root document. The main use case is block-level theming where one section of a page needs to render in dark mode and another in light mode.
How To Use It
- Add
dark:*utilities exactly as you normally would in Tailwind. - Add a
.darkclass to the wrapper that should render in dark mode. - Leave wrappers without
.darkas the default light version. - Because the selector is scoped, you can mix light and dark sections on the same page.
<section class="bg-white text-gray-900">
<h2 class="h-ms-4">Light block</h2>
</section>
<section class="dark bg-gray-900 text-white">
<h2 class="h-ms-4 dark:text-white">Dark block</h2>
<p class="text-gray-700 dark:text-gray-200">
This block opts into the dark variant without changing the rest of the page.
</p>
</section>Practical Guidance
- Treat
.darkas a theme boundary for a component, section, or CMS block. - Put the
.darkclass on the highest wrapper that should inherit dark styling. - If a component must always stay light inside a dark page area, render that component outside the
.darkwrapper or avoid usingdark:*utilities inside it. - Use Tailwind's
scheme-light,scheme-dark, or relatedcolor-schemeutilities when native form controls need to match the block theme.
Relevant documentation:
Sticky Footer Layout
Sticky footer layout utilities defined in css/components/_layout.css. These work by setting body to flex flex-col min-h-screen and using flex grow/shrink on the child regions to push the footer to the bottom of the viewport. All projects should use sticky footers to avoid footer-related issues on short pages.
site-header- Flex child that does not grow or shrinksite-main- Flex child that grows to fill available space, pushing the footer downsite-footer- Flex child that does not grow or shrink
Example
<body>
<header class="site-header">...</header>
<main class="site-main">...</main>
<footer class="site-footer">...</footer>
</body>