Twin blends the magic of Tailwind with the flexibility of css-in-js
Demo twin on CodeSandbox β
Use Twinβs tw
prop to add Tailwind classes onto jsx elements:
import "twin.macro";
const Input = () => <input tw="border hover:border-black" />;
Nest Twinβs tw
import within a css prop to add conditional styles:
import tw from "twin.macro";
const Input = ({ 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`}
}
`;
const Input = ({ 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`;
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`,
]);
const Component = () => <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`}
`;
const Component = () => <Input hasHover />;
When babel runs over your code, Twinβs css
and styled
imports get swapped with the real imports from libraries like π
Β styledβcomponents and π©βπ€Β emotion.
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 v2
πΉ 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 up variants whenever you need them
sm:hover:first:bg-black
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)" />
const variantsInGroups = () => <div tw="sm:(bg-black hover:bg-white)">
Take a look at these examples to get started:
π styled-components Β π©βπ€ emotion
π styled-components Β π₯ goober
π styled-components Β π©βπ€ emotion
π styled-components Β π©βπ€ emotion
π styled-components Β π©βπ€ emotion
π styled-components Β π styled-components (TypeScript) Β π©βπ€ emotion
π styled-components (TypeScript)
π styled-components (TypeScript)
π©βπ€ emotion (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 - those features are coming soon.
See list of supported plugins β
Twin fully supports TypeScript projects and includes types for every import except the css
and styled
imports.
How to add the missing css
and styled
types β
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.