Migration from styled-components
We tried to keep the changes you need to know if you're already familiar with styled-components to a minimum.
Familiar API
styled
You can use the styled
tag as you know for all kind of elements.
import styled from 'styled-components';
const Button = styled.button`
background: #BF4F74;
`;
const Nav = styled.nav`
background: #BF4F74;
`;
You can use static or dynamic parts the same way you would use it in styled-components.
import styled from 'styled-components';
const Button = styled.button<{ $primary: boolean }>`
background: #BF4F74;
color: ${props => props.$primary ? "white" : "#BF4F74"};
`;
css
The css
tagged template literal in styled-components is used when you want to use a dynamic
CSS part "outside" of the styled literal. Next-yak works similar but with the difference that you
should use it everytime you want to have dynamic properties where the CSS property isn't known
in the outside literal.
import styled from 'styled-components';
const Button = styled.button<{ $primary: boolean }>`
background: #BF4F74;
${props => props.$primary ? "color: white;" : "color: #BF4F74;"}
`;
Next-yak transforms css
code into a class name that is referenced. So you can think of it as
an additional css class that gets added/subtracted as needed.
css prop
Also the css prop works similar to styled-components. The main difference is that you can't use
dynamic values in the css prop and that you have to use the css
tag to define the css.
<div
css={`
background: papayawhip;
color: ${props => props.theme.colors.text};
`}
/>
<Button
css="padding: 0.5em 1em;"
/>
If you use TypeScript, you can just add the following to your tsconfig.json
to get type checking for the css prop.
{
"compilerOptions": {
"jsxImportSource": "next-yak"
}
}
keyframes
The api for keyframes is exactly the same as in styled-components. You can define your keyframes and use it in your animations.
import styled, { keyframes } from 'styled-components';
const rotate = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
const Rotate = styled.div`
display: inline-block;
animation: ${rotate} 2s linear infinite;
padding: 2rem 1rem;
font-size: 2rem;
`;
attrs
Next-yak also enables .attrs
on your components and has the same behaviour as in styled-components
import styled from 'styled-components';
const Input = styled.input.attrs(props => ({
type: "text",
size: props.size || "1em"
}))`
color: palevioletred;
font-size: 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
References to other components
In order to create a selector that includes another component, you can just reference it in the tagged template literal.
import styled from 'styled-components';
const Button = styled.button`
color: blue;
`;
const Wrapper = styled.div`
${Button} {
color: red;
}
`;
During build time the reference is changed to the actual generated class name of the referenced component.
Mixins
Mixins allow you to predefine CSS styles and reuse them across components. You can just create mixins the same way as you would with styled-components.
import styled, { css } from 'styled-components';
const mixin = css`
color: green;
`;
const MyComp = styled.div`
background-color: yellow;
${mixin}
`;
Migration
Change import
Change the import from styled-components
to next-yak
and change the import of styled
from a default import
to a named import.
import styled, { css, keyframes } from 'styled-components';
import { styled, css, keyframes } from 'next-yak';
Add yak files
Yak files are used to store static values that are extracted during build time. You can create a .yak.ts
file
everywhere in your project and it will be picked up by next-yak.
export const colors = {
primary: "#BF4F74",
secondary: "#F7B801",
};
export const breakpoints = {
mobile: "@media (max-width: 420px)",
tablet: "@media (max-width: 768px)",
desktop: "@media (min-width: 769px)",
};
You can then use these values in your styled components.
import { styled } from 'next-yak';
import { colors, breakpoints } from './constants.yak';
const Button = styled.button`
background: ${colors.primary};
${breakpoints.mobile} {
font-size: 1rem;
}
${breakpoints.tablet} {
font-size: 1.5rem;
}
${breakpoints.desktop} {
font-size: 2rem;
}
`;
It looks and feels like a mixin from styled-components but it's actually a static value that gets injected during build time. This is the reason why you can't use dynamic values in yak files, as they have to be known during build time whereas mixin values can be dynamic.
So this doesn't work:
export const colors = {
primary: "#BF4F74",
secondary: "#F7B801",
dynamic: (props: { $primary: boolean }) => props.$primary ? "#BF4F74" : "white",
};
export const breakpoints = (media: Record<string, string>) => {
return media;
};
Replace styled-components with next-yak
Replace all your styled-components with next-yak. You can use the same API as you would with styled-components.
import styled, { css, keyframes } from 'styled-components';
import { styled, css, keyframes } from 'next-yak';
const Button = styled.button`
background: #BF4F74;
color: ${props => props.$primary ? "white" : "#BF4F74"};
`;
const Input = styled.input.attrs(props => ({
type: "text",
size: props.size || "1em"
}))`
color: palevioletred;
font-size: 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
const Wrapper = styled.div`
${Button} {
color: red;
}
`;
const mixin = css`
color: green;
`;
const MyComp = styled.div`
background-color: yellow;
${mixin}
`;
const rotate = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
const Rotate = styled.div`
display: inline-block;
animation: ${rotate} 2s linear infinite;
padding: 2rem 1rem;
font-size: 2rem;
`;
Replace some mixins with constant yak files.
import styled, { css } from 'styled-components';
import { colors } from "./colors-mixin";
import { css, styled } from 'next-yak';
import { colors } from './colors.yak';
const Button = styled.button`
background: ${colors.primary};
color: ${props => props.$primary ? "white" : colors.primary};
`;
Wrap the imported component in a local component when you want to reference it.
import styled from 'styled-components';
import { styled } from 'next-yak';
import { Button } from './button';
const LocalButton = styled(Button)``;
const Wrapper = styled.div`
${Button} {
${LocalButton} {
color: red;
}
`;
Or add a static class to referenced components outside of the current file.
import styled from 'styled-components';
import { styled } from 'next-yak';
export const Button = styled.button`
color: blue;
`;
export const MyComponent = () => {
return (
<Button
className="myButton"
>
Click me
</Button>);
Missing features
Currently .withConfig
and the as
prop are not supported. We might add support for these features in the future.
Conclusion
next-yak is a drop-in replacement for styled-components that works with Server Components and Client Components. It provides a familiar API and adds the ability to use static values in your styled components. This is especially useful when you want to use the same values across your application and don't want to pass them down the component tree.
If you have any questions or feedback, feel free to reach out to us on GitHub