Emotion 11
✏️ Edit this pageEmotion 11 is a slight evolution over the Emotion 10. It focuses mainly on the developer experience, TS types improvements, switches internals to hooks and to the new version of the parser that we use: Stylis.
Package renaming
One of the most significant changes is that most of the user-facing packages have been renamed:
@emotion/core
→@emotion/react
emotion
→@emotion/css
emotion-theming
→ moved into@emotion/react
emotion-server
→@emotion/server
create-emotion
→@emotion/css/create-instance
create-emotion-server
→@emotion/server/create-instance
babel-plugin-emotion
→@emotion/babel-plugin
eslint-plugin-emotion
→@emotion/eslint-plugin
jest-emotion
→@emotion/jest
Most of this renaming can be done automatically via a codemod by running the @emotion/pkg-renaming
rule from @emotion/eslint-plugin
with --fix
over your codebase.
Hooks
Use hooks internally for improved bundle size and a better tree in React DevTools 🎉.
TypeScript
Types overhaul
TypeScript types have been significantly restructured.
- reduce build times when using Emotion, especially in larger projects
- it’s no longer necessary to manually specify generic parameters for your Emotion components in many cases
- union types as props are better supported and should be inferred properly
- the
css
function has been restricted to prevent passing invalid types styled
’s generic parameter has been changed, if you were specifying theComponentType
you will need to remove that generic parameterstyled
no longer takes a secondExtraProps
parameter - instead of that move it to after thestyled
call. So instead of writingstyled<typeof MyComponent, ExtraProps>(MyComponent)({})
you should now be writingstyled(MyComponent)<ExtraProps>({})
If you encounter build issues after upgrade, try removing any manually specified generic types and let them be inferred.
Theme type
It’s now easier to provide a type for Theme
. Instead of creating custom instances (like before) you can augment the builtin Theme
interface like this:
import '@emotion/react'
declare module '@emotion/react' {
export interface Theme {
primaryColor: string
secondaryColor: string
}
}
css prop types
The way in which we provide TypeScript support for the css
prop has changed. Based on the usage of our JSX factories, we can add support for css
prop only for components that support className
prop (as our JSX factory functions take the provided css
prop, resolve it and pass the generated className
to the rendered component).
For the classic runtime this has been implemented using technique described here. What is important - we no longer extend any global interfaces, so people shouldn’t bump anymore into type conflicts for the css
prop when using different libraries with css
prop support, such as styled-components
.
For the automatic runtime this has been implemented by exporting JSX
namespace from the appropriate entries but this is only supported in TypeScript 4.1 or higher.
However, if you are stuck with older version of TypeScript or using the classic runtime implicitly by using our @emotion/babel-preset-css-prop
then it’s not possible to leverage leverage css
prop support being added conditionally based on a type of rendered component. For those cases we have added a special file that can be imported once to add support for the css
prop globally, for all components. Use it like this:
/// <reference types="@emotion/react/types/css-prop" />
In this particular case we are forced to extend the existing React.Attributes
interface. Previously we’ve been extending both React.DOMAttributes
and JSX.IntrinsicAttributes
. This change is really minor and shouldn’t affect any consuming code.
Stylis v4
The parser we use (Stylis) got upgraded. It fixes some long-standing parsing edge cases while being smaller and faster 🚀
It has been completely rewritten and comes with some breaking changes. The most notable ones that might affect Emotion users are:
- plugins written for the former Stylis v3 are not compatible with the new version. To learn more on how to write a plugin for Stylis v4 you can check out its README and the source code of core plugins.
- vendor-prefixing was previously customizable using
prefix
option. This was always limited to turning off all of some of the prefixes as all available prefixes were on by default. Theprefix
option is gone and to customize which prefixes are applied you need to fork (copy-paste) the prefixer plugin and adjust it to your needs. While this being somewhat more problematic to setup at first we believe that the vast majority of users were not customizing this anyway. By not including the possibility to customize this through an extra option the final solution is more performant because there is no extra overhead of checking if a particular property should be prefixed or not. - the prefixer is now just a plugin which happens to be included in the default
stylisPlugins
. If you plan to use customstylisPlugins
and you want to have your styles prefixed automatically you must include prefixer in your customstylisPlugins
. You can importprefixer
from thestylis
module to do that. @import
rules are no longer special-cased. The responsibility to put them first has been moved to the author of the styles. They also can’t be nested within other rules now. It’s only possible to write them at the top level of global styles.
Emotion’s caches
The key
option is now required when creating a custom instance of a cache. Please make sure it’s unique (and not equal to 'css'
) as it’s used for linking styles to your cache. If multiple caches share the same key they might “fight” for each other’s style elements.
The new prepend
option can make Emotion add style tags at the beginning of the specified DOM container instead of the end.
Other
There are a lot of less substantial changes than what has been described here, some of them might even be breaking changes but are not relevant to the majority of users. Therefore to learn more about all of the changes please read through the full list of changes contained in the respective changelogs:
@emotion/babel-plugin
@emotion/babel-preset-css-prop
@emotion/cache
@emotion/css
@emotion/eslint-plugin
@emotion/is-prop-valid
@emotion/jest
@emotion/native
@emotion/primitives-core
@emotion/primitives
@emotion/react
@emotion/serialize
@emotion/server
@emotion/sheet
@emotion/styled
@emotion/utils