xwind
xwind uses a babel plugin that transforms Tailwind classes into CSS object styles or a classes string. The CSS object styles output can be used with your favorite CSS-in-JS library like emotion, styled-components ... The classes string output can be used with the xwind cli to generate a minimal css file of the used Tailwind classes.
Table of Contents
- Basic examples
- objectstyles mode
- classes mode
- API
-
Install
- 0. Prerequisites:
- 1. Install packages
- 2. Add xwind babel plugin to babel config
- 3. Create Tailwind config file
- 4. Choose your preferred xwind mode:
-
4.A "objectstyles" mode install instructions
- 4.1 Add xwind config mode option to tailwind.config.js
- 4.2 Add Tailwind base css
- 4.2.A Using "XWIND_BASE XWIND_GLOBAL" classes
- 4.2.B Create a tailwind.base.css file
- 4.2.1 Add the xwind base tailwind plugin to add support for keyframe, ring and shadow classes.
- 4.2.2 Using Tailwind CLI
- 4.2.3 Import base.css
- 4.B "classes" mode install instructions
- Examples
- Customization
- License
Basic examples
Output mode "objectstyles" example
import xw from "xwind";
//OR
import xw from "xwind/macro";
const styles = xw`text-red-100 hover:text-green-100 hover:bg-blue-200`;
// OR (with custom array syntax)
const styles = xw`text-red-100 hover[text-green-100 bg-blue-200]`;
Transforms by default into Postcss-js / JSS compatible syntax:
const styles = {
"--text-opacity": "1",
color: ["#fde8e8", "rgba(253, 232, 232, var(--text-opacity))"],
"&:hover": {
"--text-opacity": "1",
"--bg-opacity": "1",
color: ["#def7ec", "rgba(222, 247, 236, var(--text-opacity))"],
backgroundColor: ["#c3ddfd", "rgba(195, 221, 253, var(--bg-opacity))"],
},
};
Transform to CSS string syntax with the css plugin:
const styles = `
--text-opacity: 1;
color: #fde8e8;
color: rgba(253, 232, 232, var(--text-opacity));
&:hover {
--text-opacity: 1;
--bg-opacity: 1;
color: #def7ec;
color: rgba(222, 247, 236, var(--text-opacity));
background-color: #c3ddfd;
background-color: rgba(195, 221, 253, var(--bg-opacity));
}
`;
objectstyles plugins make it possible to support any CSS-in-JS library syntax.
Output mode "classes" example
import xw from "xwind";
//OR
import xw from "xwind/macro";
const styles = xw`text-red-100 hover:text-green-100 hover:bg-blue-200`;
// OR (with custom array syntax)
const styles = xw`text-red-100 hover[text-green-100 bg-blue-200]`;
Transforms into a classes string:
const styles = "text-red-100 hover:text-green-100 hover:bg-blue-200";
Generate the css output with with the xwind cli:
npx run xwind
Output file "/src/styles/xwind.css":
/*! Generated with xwind | https://github.com/arthie/xwind */
.hover\:bg-blue-200:hover {
--tw-bg-opacity: 1;
background-color: rgba(191, 219, 254, var(--tw-bg-opacity));
}
.text-red-100 {
--tw-text-opacity: 1;
color: rgba(254, 226, 226, var(--tw-text-opacity));
}
.hover\:text-green-100:hover {
--tw-text-opacity: 1;
color: rgba(220, 252, 231, var(--tw-text-opacity));
}
Import the output file "/src/styles/xwind.css" into your project:
//Javascript:
import "/src/styles/xwind.css";
//OR
//HTML:
<link rel="stylesheet" href="/src/styles/xwind.css" />;
objectstyles mode
In objectstyles mode xwind will transform Tailwind classes into CSS object styles. The CSS object styles output can be used with your favorite CSS-in-JS library like emotion, styled-components. Objectstyles plugins make it possible to support any CSS-in-JS library syntax.
note:
objectstyles mode is recommended if you are using a CSS-in-JS library.
classes mode
In classes mode xwind will transforms Tailwind classes into classes string. The classes string output can be used with the xwind cli to generate a minimal css file of the used Tailwind classes. This allows xwind to be used without a CSS-in-JS library.
note:
classes mode is recommended if you're already using tailwindcss and want the benefits of xwind.
API
//these import will be removed by the babel plugin in build
import xw from "xwind";
//also available as macro variant
import xw from "xwind/macro";
import xw, { cx } from "xwind"; //or "xwind/macro"
//cx is used to compose different classes
//cx uses the clsx library from lukreed: https://github.com/lukeed/clsx#readme
cx(xw`text-green-200`, true && xw`bg-red-500`);
//tagged template syntax
xw`bg-red-100 bg-blue-400`;
//call expression syntax
xw("bg-red-100 bg-blue-400");
xw("bg-red-100", "bg-blue-400", [["text-sm"], "font-sans"]);
//xwind can evaluate static expressions
xw`bg-red-100 ${"bg-red-100"}`;
const bg = "bg-red-100";
xw`bg-red-100 ${bg}`;
xw("bg-red-100", bg);
Install
0. Prerequisites:
- Have node 12 or above installed
- Install and configure your bundler with babel (babel-plugin-macros is optional)
1. Install packages
# with npm
npm install -D xwind tailwindcss postcss autoprefixer
# with Yarn
yarn add -D xwind tailwindcss postcss autoprefixer
note
autoprefixer is optional tailwindcss has it as peerdependency but it's not needed for xwind.
2. Add xwind babel plugin to babel config
This step is optional if you plan on using the "xwind/macro" instead.
// .babelrc
{
"presets": [
//... presets
],
"plugins": [
//add this:
"xwind/babel"
]
}
3. Create Tailwind config file
The tailwind.config.js file is required to configure xwind config options.
npx tailwindcss init
Check out the Tailwind documentation for customizing the Tailwind config file.
4. Choose your preferred xwind mode:
4.A "objectstyles" mode install instructions
4.1 Add xwind config mode option to tailwind.config.js
// tailwind.config.js
module.exports = {
theme: {},
plugins: [],
// ... tailwind config options
//Add this:
xwind: {
mode: "objectstyles",
},
};
4.2 Add Tailwind base css
4.2.A Using "XWIND_BASE XWIND_GLOBAL" classes
You can add the Tailwind base styling and classes global styling with the special xwind classes:
-
XWIND_BASE
adds Tailwind base styling -
XWIND_GLOBAL
adds global classes styling e.g. keyframes and ring / shadow css variables
example with emotion
import { Global } from "@emotion/react";
import xw from "xwind";
<Global
//add tailwind base + keyframes ... to global styles
styles={xw`XWIND_BASE XWIND_GLOBAL`}
/>;
Generate base CSS with Tailwind cli
4.2.B Create a tailwind.base.css file
/* tailwind.base.css */
@tailwind base;
4.2.1 Add the xwind base tailwind plugin to add support for keyframe, ring and shadow classes.
// tailwind.config.js
module.exports = {
theme: {},
// ... tailwind config options
//Add this:
plugins: [require("xwind/plugins/base")],
xwind: {
mode: "objectstyles",
},
};
4.2.2 Using Tailwind CLI
# Use the `npx tailwindcss help build` command to learn more about the various CLI options.
npx tailwindcss build tailwind.base.css -o base.css
Tip: add this command to your package.json scripts section
4.2.3 Import base.css
import "base.css";
4.B "classes" mode install instructions
4.1 Add xwind config mode option to tailwind.config.js
// tailwind.config.js
module.exports = {
theme: {},
plugins: [],
// ... tailwind config options
//Add this:
xwind: {
mode: "classes",
classes: {
//entry files location all files containing xwind imports
entry: "./src", // string | string[] / required
//output css file location
output: "./styles/xwind.css", //string / required
},
},
};
4.2 Create the output css file
Create a new css file at the location specified in the xwind config output option.
4.3 Generate the tailwind classes
Run the xwind cli to generate a minimal css file of the used Tailwind classes.
# Use the `npx xwind --help` command to learn more about the various CLI options.
npx xwind
# Run the xwind cli in watch mode, file changes will trigger rebuilds.
npx xwind -w
Tip: add this command to your package.json scripts section
Examples
objectstyles mode
Codesandbox with Typescript, Nextjs and Emotion
Official Next.js example - Tailwind CSS with Emotion.js
classes mode (WIP)
coming soon!
Customization
Babel plugin config options
// .babelrc
{
"presets": [
/* ...presets */
],
"plugins": [
[
"xwind/babel",
{
"config": "./tailwind.config.js" //Path to tailwind config default: 'tailwind.config.js'
}
]
/* ...other plugins */
]
}
Babel macro plugin configuration
// .babelrc
{
"presets": [
/* ...presets */
],
"plugins": [
[
"macros",
{
"xwind": {
"config": "./tailwind.config.js" //Path to 'tailwind.config.js'
}
}
]
/* ...other plugins */
]
}
// package.json
"babelMacros": {
"xwind": {
"config": "./tailwind.config.js", //Path to 'tailwind.config.js'
}
},
// babel-plugin-macros.config.js
module.exports = {
xwind: {
config: "./tailwind.config.js", //Path to 'tailwind.config.js'
},
};
xwind config
The xwind config options are set in the tailwind.config.js
file
classes mode
// tailwind.config.js
module.exports = {
theme: {},
plugins: [],
// ... tailwind config options
xwind: {
//select xwind output mode
mode: "classes", // "classes" / required
classes: {
//include tailwindcss base styles
includeBase: true, // boolean / optional / default: true
//entry files location all files containing xwind imports
entry: "./src", // string | string[] / required
//output css file location
output: "./styles/xwind.css", //string / required
},
},
};
objectstyles mode
// tailwind.config.js
module.exports = {
theme: {},
plugins: [],
// ... tailwind config options
xwind: {
//select xwind output mode
mode: "objectstyles", // "objectstyles" / required
objectstyles: {
//enable babel cache warning
warningCache: true, // boolean / optional / default: true,
plugins: [
/* objectstyles plugins / optional */
],
},
},
};
objectstyles plugins
To support the different CSS-in-JS syntaxes we need a way to change the default output this can be done with xwind objectstyles plugins.
CSS string
// tailwind.config.js
module.exports = {
//... tailwind config options
xwind: {
mode: "objectstyles",
objectstyles: {
plugins: [require("xwind/plugins/objectstyles/css")],
},
},
};
CSS string plugin output example
Default
const styles = {
"--text-opacity": "1",
color: ["#fde8e8", "rgba(253, 232, 232, var(--text-opacity))"],
"&:hover": {
"--text-opacity": "1",
"--bg-opacity": "1",
color: ["#def7ec", "rgba(222, 247, 236, var(--text-opacity))"],
backgroundColor: ["#c3ddfd", "rgba(195, 221, 253, var(--bg-opacity))"],
},
};
With CSS string plugin
const styles = `
--text-opacity: 1;
color: #fde8e8;
color: rgba(253, 232, 232, var(--text-opacity));
&:hover {
--text-opacity: 1;
--bg-opacity: 1;
color: #def7ec;
color: rgba(222, 247, 236, var(--text-opacity));
background-color: #c3ddfd;
background-color: rgba(195, 221, 253, var(--bg-opacity));
}
`;
Remove fallbacks
// tailwind.config.js
module.exports = {
//... tailwind config options
xwind: {
mode: "objectstyles",
objectstyles: {
plugins: [require("xwind/plugins/objectstyles/removeFallbacks")],
},
},
};
Remove fallbacks plugin output example
Defaultconst styles = {
"--text-opacity": "1",
color: ["#fde8e8", "rgba(253, 232, 232, var(--text-opacity))"],
"&:hover": {
"--text-opacity": "1",
"--bg-opacity": "1",
color: ["#def7ec", "rgba(222, 247, 236, var(--text-opacity))"],
backgroundColor: ["#c3ddfd", "rgba(195, 221, 253, var(--bg-opacity))"],
},
};
With remove fallbacks plugin
const styles = {
"--text-opacity": "1",
color: "rgba(253, 232, 232, var(--text-opacity))",
"&:hover": {
"--text-opacity": "1",
"--bg-opacity": "1",
color: "rgba(222, 247, 236, var(--text-opacity))",
backgroundColor: "rgba(195, 221, 253, var(--bg-opacity))",
},
};
License
MIT. Copyright (c) 2020 Arthur Petrie.