Learn EmotionJS during your morning coffee – it‘s that easy
As a seasoned full-stack developer, I‘ve had the opportunity to work with a wide range of styling solutions across countless web projects. From old-school CSS to modern CSS-in-JS libraries, I‘ve experienced firsthand the profound impact the right tools and methodologies can have on the maintainability and scalability of styling complex applications.
In recent years, a new player has emerged that has completely revolutionized my approach to styling React components: EmotionJS. With its simple yet expressive API, impressive performance, and rich feature set, EmotionJS has quickly become my go-to library for writing modular, reusable styles.
But don‘t just take my word for it. In this deep dive, we‘ll explore what makes EmotionJS so special and why you should consider using it in your next project. As you‘ll see, getting started with EmotionJS is so straightforward, you can pick up the basics in the time it takes to enjoy your morning coffee. Let‘s jump in!
Why EmotionJS?
Before we delve into the specifics of using EmotionJS, it‘s worth taking a moment to understand what sets it apart from other styling solutions. While there are several excellent CSS-in-JS libraries out there, EmotionJS has a few key advantages that make it a compelling choice.
Intuitive, flexible API
One of the things I love most about EmotionJS is how easy it is to get up and running. If you‘ve ever used tagged template literals in JavaScript, the syntax will feel very natural. Here‘s a simple example of styling a button component:
import styled from ‘@emotion/styled‘
const Button = styled.button`
background: ${props => props.primary ? ‘blue‘ : ‘white‘};
color: ${props => props.primary ? ‘white‘ : ‘blue‘};
padding: 16px 32px;
border-radius: 4px;
text-transform: uppercase;
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
`
As you can see, we define our styles between the backticks of the styled.button
tagged template literal. We can use plain CSS properties like padding
and border-radius
, as well as insert dynamic values based on props using the ${}
interpolation syntax.
But EmotionJS doesn‘t stop there. It also provides a css
prop that allows us to pass styles as an object to any component:
import { css } from ‘@emotion/react‘
const Card = props => (
<div
{...props}
css={{
background: ‘white‘,
borderRadius: 4,
boxShadow: ‘0px 4px 8px rgba(0, 0, 0, 0.1)‘,
‘&:hover‘: {
boxShadow: ‘0px 8px 16px rgba(0, 0, 0, 0.1)‘
}
}}
/>
)
I find the css
prop particularly useful when I need to apply styles conditionally based on props or state. It‘s also handy for doing quick one-off styles without having to create a separate styled component.
Stellar performance
Another area where EmotionJS shines is performance. Compared to other CSS-in-JS libraries, EmotionJS has a smaller runtime footprint and supports features like Dead Code Elimination out of the box.
Dead Code Elimination, or DCE for short, is a compiler optimization that removes code that isn‘t actually used in the final bundle. With EmotionJS, if you only use a subset of the library‘s features, the unused code will be stripped out automatically by your bundler (assuming it supports DCE), resulting in a smaller bundle size.
To put this into perspective, here‘s a quick comparison of the minified bundle sizes of some popular CSS-in-JS libraries:
Library | Minified Size |
---|---|
EmotionJS | 7.3 KB |
Styled Components | 16.3 KB |
Radium | 16.5 KB |
JSS | 18.0 KB |
As you can see, EmotionJS comes out ahead by a significant margin. This can have a big impact on performance, especially for users on slower networks or devices.
It‘s worth noting that EmotionJS also supports server-side rendering out of the box, with a simple API for extracting critical styles and inlining them in your HTML. This helps ensure your site is usable and looks correct even before JavaScript is loaded on the client.
Rich ecosystem and excellent documentation
EmotionJS benefits from a large and active community of users and contributors. The library‘s GitHub repo has over 11,000 stars as of this writing, and there are tons of great articles, tutorials, and examples available online.
The official documentation is also top-notch, with clear explanations and practical examples covering every aspect of the library. Whether you‘re a beginner or an advanced user, you‘ll find the docs to be an invaluable resource.
One of my favorite things about the EmotionJS ecosystem is the wide variety of tools and plugins available. For example, if you‘re using Gatsby, there‘s an official gatsby-plugin-emotion
that makes it easy to integrate EmotionJS into your site with support for server-side rendering and automatic vendor prefixing.
There are also great tools for testing, like jest-emotion
, which provides a set of custom matchers for validating EmotionJS styles in your unit tests. And if you‘re transitioning an existing project to EmotionJS, libraries like emotion-normalize
can help you reset default browser styles to a consistent baseline.
Advanced features and techniques
Now that we‘ve covered some of the high-level benefits of EmotionJS, let‘s take a closer look at some of the more advanced features and techniques you can leverage in your projects.
Composing styles with objects
One of the most powerful features of EmotionJS is the ability to define and compose styles as JavaScript objects. This is incredibly useful for creating reusable style snippets that can be shared across multiple components.
Here‘s a simple example:
import { css } from ‘@emotion/react‘
const flex = {
display: ‘flex‘,
alignItems: ‘center‘,
justifyContent: ‘space-between‘
}
const Card = ({ title, children }) => (
<div
css={css`
background: white;
border-radius: 4px;
padding: 16px;
${flex};
`}
>
<h2>{title}</h2>
{children}
</div>
)
In this snippet, we define a reusable flex
object containing some common flexbox styles. We can then spread this object into our styles using the ${flex}
syntax, which will merge the styles into the final CSS output.
This approach is incredibly powerful for creating design systems and ensuring consistency across your application. You can define a set of base styles for things like typography, colors, and spacing, then easily apply them to any component using the object composition syntax.
Animations and keyframes
EmotionJS has excellent support for CSS animations and keyframes. You can define your animations using the keyframes
helper and then apply them to your components using the animation
property.
Here‘s an example of a simple fade-in animation:
import { keyframes, css } from ‘@emotion/react‘
const fadeIn = keyframes`
from {
opacity: 0;
}
to {
opacity: 1;
}
`
const Button = ({ children }) => (
<button
css={css`
animation: ${fadeIn} 0.2s ease-in;
`}
>
{children}
</button>
)
By defining our animation with the keyframes
helper and then interpolating it into our button styles, we can create smooth, performant animations that run natively in the browser.
EmotionJS also supports more advanced animation techniques like chaining and composition. You can define multiple animations on a single element and control their timing and sequencing using the animation
shorthand property.
Theming and global styles
As your application grows in complexity, it becomes increasingly important to maintain a consistent visual language across your components. EmotionJS makes this easy with its powerful theming and global styles features.
To use theming, you‘ll first need to define a theme object with your desired values:
const theme = {
colors: {
primary: ‘#007bff‘,
secondary: ‘#6c757d‘,
success: ‘#28a745‘,
error: ‘#dc3545‘
},
fontSizes: {
small: ‘12px‘,
medium: ‘16px‘,
large: ‘20px‘
},
spacing: {
small: ‘4px‘,
medium: ‘8px‘,
large: ‘16px‘
}
}
You can then pass this theme object to EmotionJS‘s ThemeProvider
component, which will make it available to all styled components under the theme
prop:
import { ThemeProvider } from ‘@emotion/react‘
const App = () => (
<ThemeProvider theme={theme}>
{/* Your app components */}
</ThemeProvider>
)
With the theme in place, you can easily reference its values in your styled components:
import styled from ‘@emotion/styled‘
const Button = styled.button`
background: ${props => props.theme.colors.primary};
color: white;
padding: ${props => props.theme.spacing.medium};
font-size: ${props => props.theme.fontSizes.medium};
`
EmotionJS also supports global styles, which can be useful for applying styles to base elements like body
and html
, or for defining utility classes that can be reused throughout your app.
To create a global style, use the Global
component from @emotion/react
:
import { Global, css } from ‘@emotion/react‘
const GlobalStyles = () => (
<Global
styles={css`
body {
font-family: ‘Helvetica Neue‘, Arial, sans-serif;
font-size: 16px;
line-height: 1.5;
margin: 0;
padding: 0;
}
.screen-reader-only {
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
position: absolute;
}
`}
/>
)
By wrapping your global styles in the Global
component, EmotionJS will ensure they‘re injected into the document head and applied consistently across your app.
Real-world use cases and examples
To illustrate the power and flexibility of EmotionJS, let‘s take a look at a few real-world examples of how it‘s being used in production.
Chakra UI
Chakra UI is a popular component library for React that provides a set of accessible, reusable building blocks for creating modern web applications. Under the hood, Chakra UI uses EmotionJS to style its components and expose a simple theming API for customization.
Here‘s an example of how you might use Chakra UI‘s Button
component in your app:
import { Button } from ‘@chakra-ui/react‘
const MyComponent = () => (
<>
<Button colorScheme="blue">
Click me!
</Button>
<Button colorScheme="red" variant="outline">
Cancel
</Button>
</>
)
By leveraging EmotionJS‘s theming capabilities, Chakra UI makes it easy to create consistent, accessible user interfaces without writing a lot of custom CSS.
Framer Motion
Framer Motion is a powerful animation library for React that makes it easy to add declarative animations and gestures to your components. It uses EmotionJS under the hood to apply styles and animations in a performant, flexible way.
Here‘s an example of a simple card component that fades in and scales up when it mounts:
import { motion } from ‘framer-motion‘
const Card = ({ children }) => (
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
css={{
background: ‘white‘,
borderRadius: 8,
boxShadow: ‘0 5px 15px rgba(0, 0, 0, 0.1)‘,
padding: 16
}}
>
{children}
</motion.div>
)
By combining the declarative API of Framer Motion with the styling power of EmotionJS, you can create complex, interactive animations with very little code.
SignalNoise
SignalNoise is a creative studio based in Vancouver, Canada that specializes in interactive web experiences. They use EmotionJS extensively in their projects to create stunning, immersive animations and page transitions.
One of my favorite examples is their work on the website for the virtual reality company Oculus. The site features a series of beautiful 3D product renderings that animate and respond to user input, all styled with EmotionJS.
To achieve this effect, the SignalNoise team used EmotionJS to define a set of base styles for the 3D elements, then dynamically applied additional styles based on the user‘s scroll position and cursor location. The result is an incredibly smooth and engaging experience that really showcases the power of combining EmotionJS with WebGL and other advanced web technologies.
Conclusion
As you can see, EmotionJS is an incredibly powerful tool for styling modern web applications. With its simple, expressive API, strong performance, and rich ecosystem of plugins and tools, it offers a compelling alternative to traditional CSS stylesheets and other CSS-in-JS libraries.
Throughout this article, we‘ve explored some of the key features and benefits of EmotionJS, from its flexible styling options and powerful theming capabilities to its support for animations, global styles, and more. We‘ve also looked at some real-world examples of EmotionJS in action, from popular component libraries like Chakra UI to stunning interactive experiences built by creative studios like SignalNoise.
Whether you‘re a seasoned full-stack developer looking to optimize your styling workflow or a curious beginner exploring the world of CSS-in-JS for the first time, I highly recommend giving EmotionJS a try. Its intuitive API and excellent documentation make it easy to get started, while its advanced features and performance optimizations provide plenty of room for growth and experimentation.
So what are you waiting for? Grab a cup of coffee, fire up your favorite code editor, and start exploring the world of EmotionJS today. I think you‘ll be amazed at how quickly and easily you can create beautiful, maintainable styles for your web projects. Happy coding!