Twin-Macro on CRA with React 17
Jack Herrington
Posted on December 24, 2020
This recipe is based on this excellent article, but with adjustments to make it work with React 17.
- First let’s create a CRA React app:
npx create-react-app tw-test
- Next install all the Tailwind, twin.macro, and emotion libraries:
yarn add tailwindcss twin.macro @emotion/core @emotion/styled @emotion/react
- Next up, we initialize Tailwind.
npx tailwindcss init --full
This creates a tailwind.config.js
file in the root directory, which we point to in the package.json
.
- Add a new babelMacros key to package.json
"babelMacros": {
"twin": {
"config": "tailwind.config.js"
}
},
You can put the tailwind configuration anywhere you like in the tree, just make sure to specify the path correctly in the package.json
.
- Import the tailwind CSS into your
index.js
file
import 'tailwindcss/dist/base.min.css';
This completes the setup.
Watch It On YouTube
Another way you can learn about this is to watch the video for this article.
Using Tailwind
There are several ways to use twin.macro
, the easiest way is to use the tw
attribute on any React element, like so:
/** @jsxImportSource @emotion/react */
import tw from "twin.macro";
function App() {
return (
<div tw="max-w-4xl mx-auto p-5 mt-5">
<h1 tw="text-blue-500 text-4xl">Hello world</h1>
</div>
);
}
export default App;
The @jsxImportSource
syntax is new for React 17. In React 16 the syntax was @jsx
, if you use that syntax you will get an error message that reads:
pragma and pragmaFrag cannot be set when runtime is automatic.
Other Ways To Use Twin-Macro
Other options for twin.macro include creating new React elements in an emotion-styled style, like so:
/** @jsxImportSource @emotion/react */
import tw from "twin.macro";
const Heading = tw.h1`text-blue-500 text-2xl p-2`;
const Container = tw.div`max-w-4xl mx-auto p-5 mt-5`;
function App() {
return (
<Container>
<Heading>My custom heading</Heading>
</Container>
);
}
export default App;
You can also extend these components:
/** @jsxImportSource @emotion/react */
import tw from "twin.macro";
const Heading = tw.h1`text-blue-500 text-2xl p-2`;
const BigHeading = tw(Heading)`text-4xl`;
const Container = tw.div`max-w-4xl mx-auto p-5 mt-5`;
function App() {
return (
<Container>
<BigHeading>My big heading</BigHeading>
</Container>
);
}
export default App;
And you can even do conditional styling:
/** @jsxImportSource @emotion/react */
import tw, { styled } from "twin.macro";
const Heading = tw.h1`text-blue-500 text-2xl p-2`;
const MaybeBigHeading = styled(Heading)(({ big }) => [
big && tw`text-4xl`
]);
const Container = tw.div`max-w-4xl mx-auto p-5 mt-5`;
function App() {
return (
<Container>
<MaybeBigHeading>My custom heading</MaybeBigHeading>
<MaybeBigHeading big>My big heading</MaybeBigHeading>{" "}
</Container>
);
}
export default App;
Next Steps
- Use
yarn build
to create a production deployable version and look at the static asset sizes. - Use Lighthouse on the production build to check out the performance stats on your application when you build it in production mode. I think you will be impressed.
Posted on December 24, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.