Use Tailwind classes within css-in-js libraries
Use Twin’s tw
prop to add Tailwind classes onto jsx elements:
import 'twin.macro'
export default () => <input tw="border hover:border-black" />
Nest Twin’s tw
import within a css prop to add conditional styles:
import tw from 'twin.macro'
export default ({ hasHover }) => (
<input css={[tw`border`, hasHover && tw`hover:border-black`]} />
)
Or mix sass styles with the css import:
import tw, { css } from 'twin.macro'
const hoverStyles = css`
&:hover {
border-color: black;
${tw`text-black`}
}
`
export default ({ hasHover }) => (
<input css={[tw`border`, hasHover && hoverStyles]} />
)
You can also use the tw import to create and style new components:
import tw from 'twin.macro'
const Input = tw.input`border hover:border-black`
export default () => <Input />
And clone and style existing components:
const PurpleInput = tw(Input)`border-purple-500`
Switch to the styled import to add conditional styling:
import tw, { styled } from 'twin.macro'
const Input = styled.input(({ hasHover }) => [
`color: purple;`,
tw`border rounded`,
hasHover && tw`hover:border-black`,
])
export default () => <Input hasHover />
Or use backticks to mix with sass styles:
import tw, { styled } from 'twin.macro'
const Input = styled.input`
color: purple;
${tw`border rounded`}
${({ hasHover }) => hasHover && tw`hover:border-black`}
`
export default () => <Input hasHover />
When babel runs over your code, Twin’s css
and styled
imports are swapped with the real imports from libraries like 👩🎤 emotion and 💅 styled‑components.
Twin offers import presets for both libraries or you can fully customise the imports.
When you use tw
, Twin converts your classes into css objects, ready for passing to your chosen css-in-js library:
import tw from 'twin.macro'
tw`text-sm md:text-lg`
// ↓ ↓ ↓ ↓ ↓ ↓
{
fontSize: '0.875rem',
'@media (min-width: 768px)': {
fontSize: '1.125rem',
},
}
🎨 Style with all classes and variants available in Tailwind v1.8.8
🐹 Adds no size to your build - Twin converts classes you’ve used into css objects using Babel and then compiles away, leaving no runtime code
🛎 Helpful suggestions for mistypings - Twin chimes in with class and variant values from your Tailwind config:
✕ ml-7 was not found
Try one of these classes:
ml-0 [0] / ml-1 [0.25rem] / ml-2 [0.5rem] / ml-3 [0.75rem] / ml-4 [1rem] / ml-5 [1.25rem] / ml-6 [1.5rem]
ml-8 [2rem] / ml-10 [2.5rem] / ml-12 [3rem] / ml-16 [4rem] / ml-20 [5rem] / ml-24 [6rem] / ml-32 [8rem]
ml-40 [10rem] / ml-48 [12rem] / ml-56 [14rem] / ml-64 [16rem] / ml-auto [auto] / ml-px [1px]
🖌️ Use the theme import to add values from your tailwind config
import { theme, css } from 'twin.macro'
const Input = () => <input css={css({ color: theme`colors.purple.500` })} />
See more examples using the theme import →
💥 Add important to any class with a trailing bang!
tw`hidden!`
// ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
{ "display": "none !important" }
🚥 Over 40 variants to prefix on your classes - Unlike Tailwind, the prefixes are always available to add to your classes
- Prefix with
before:
andafter:
to style pseudo-elements - Prefix with
hocus:
to style hover + focus at the same time - Style with extra group states like
group-hocus:
andgroup-active:
- Style form field states with
checked:
,invalid:
andrequired:
- Stack variants for nested styles
sm:hover:
Check out the full list of variants →
🍱 Apply variants to multiple classes at once with variant groups
import 'twin.macro'
const interactionStyles = () => (
<div tw="hover:(text-black underline) focus:(text-blue-500 underline)" />
)
const mediaStyles = () => <div tw="sm:(w-4 mt-3) lg:(w-8 mt-6)" />
const pseudoElementStyles = () => (
<div tw="before:(content block w-10 h-10 bg-black)" />
)
const stackedVariants = () => <div tw="sm:hover:(bg-black text-white)" />
"Vanilla" React | ||
---|---|---|
Emotion | Demo | Docs |
Styled Components | Demo | Docs |
Create React App | ||
---|---|---|
Emotion | Demo | Docs |
Styled Components | Demo | Docs |
Gatsby | ||
---|---|---|
Emotion | Demo | Docs |
Styled Components | Demo | Docs |
Next.js | ||
---|---|---|
Emotion | Demo | Docs |
Styled Components | Demo | Docs |
Vue | |
---|---|
Emotion | Demo (Experimental) |
You can use many Tailwind plugins with twin, like Tailwind UI and Custom forms but there’s no compatibility with other plugins that use the addVariant
or addBase
functions.
Check out the list of supported plugins →
Twin comes with types for the tw
import.
You’ll just need to complete the TypeScript setup for styled
and css
.
Drop into our Discord server for announcements, help and styling chat.
- Lookup that elusive class on Nerdcave’s Tailwind cheat sheet
- Add more TypeScript features with typescript-plugin-tw-template
- Why I Write CSS in JavaScript by Max Stoiber
This project stemmed from babel-plugin-tailwind-components so a big shout out goes to Brad Cornes for the amazing work he produced. Styling with tailwind.macro has been such a pleasure.