css-template-components v0.1.5
CSS-TEMPLATE-COMPONENTS
A simple CSS in JS library for client and server-side React Components
Github: @adaup1/css-template-components
INSTALLATION
npmnpm i css-template-components
yarn
yarn add css-template-components
pnpm
pnpm add css-template-components
SERVER-SIDE RENDERING SETUP (SKIP IF CLIENT-SIDE ONLY)
Using css-template-components with server-side rendering requires just a *tiny bit of extra setup. If you are only using css-template components on the client-side you can skip this section. For this documention, we'll be using Next.js with App Router.
1. Import the getServerStyles function from "css-template-components/server" into the root component of the project. In Next.js using App Router, this will the root layout.tsx.
import { getServerStyles } from "css-template-components/server";
2. Inside the RootLayout Component, call getServerStyles and assign it to a variable
const serverStyles = getServerStyles();
3. Add a tag inside the of your RootLayout with a child of { serverStyles } or whatever you named your variable. Optionally, you can add an id.
Here is an example full implementation:
import { getServerStyles } from "css-template-components/server ";
export default function RootLayout({ children }) {
const serverStyles = getServerStyles();
return (
<html>
<head>
<style>{serverStyles}</style>
</head>
<body>{children}</body>
</html>
);
}
Using Styles
Css-template-components uses a function called styled which returns a React Component with CSS styles.
No need to add a className since styled automatically adds a unique className to the component. Under the hood, css-template-components generates style sheets with these classNames. This means you don't need to mannually create any style sheets.
If you are familiar with tagged template strings in styled-components, you'll find using css-template-components very familiar, with only a few small differences.
Styled-components is an incredible library, but it uses React.context under the hood, which prevents it from being used in Next.js server components.
For server components
import { styled } from "css-template-components/server";
For client components
import { styled } from "css-template-components/client";
From here on out, usage is the same!
The styled function requires two arguments: First Argument:
- A JSX element string (keyof JSX.IntrinsicElements) (Example:
'div', 'p', 'a', 'ul', ..etc
) - A React Components (React.ComponentType)
Second Argument:
- A tagged template string (For static styles)
- An callback returning a tagged template string (For dynamic styles)
Tagged template strings should contain valid CSS
Code Examples
Example 1
Create a p element with static styles inside a client component:
"use client";
import { styled } from "css-template-components/client";
export const MyComponent = () => {
return <StyledParagraph>My styles are static!</StyledParagraph>;
};
const StyledParagraph = styled(
"p",
`
padding: 1rem;
color: purple;
`
);
Example 2
Create a div element with dynamic styles inside a server component:
import { styled } from "css-template-components/server";
export const MyComponent = () => {
return (
<StyledDiv name="Frank">
My styles are dynamic based on my properties!
</StyledDiv>
);
};
const StyledDiv = styled(
"div",
({ name }) => `
background-color: ${name === "Frank" ? "#ff0000" : "#00ffff"};
`
);
Example 3
Style a child component inside the parent with static styles.
import { styled } from "css-template-components/server";
// Child component that will be styled in the parent
const ChildComponent = () => {
return <>I'm the child!</>;
};
// The parent component that returns the styled version of ChildComponent (see below for styles)
export const ParentComponent = () => {
return <StyledChildComponent />;
};
// Styled ChildComponent with static styles for use inside ParentComponent
const StyledChildComponent = styled(
ChildComponent,
`
background: #ff0000;
color: white;
padding: 1rem;
`
);
Example 4
This is the most complex example. We'll be creating a ChildComponent and ParentComponent. The ChildComponent will include a styled div with static styles. The ParentComponent will include a styled version of the ChildComponent with dynamic styles. We'll even add a touch of Typescript.
"use client";
import { styled } from "css-template-components/client";
// Child component that will be styled in the parent
const ChildComponent = ({ name, age }: { name: string, age: number }) => {
return (
<>
<StyledFlexContainer>
<p>{`name: ${name}`}</p>
<p>{`age: ${age}`}</p>
</StyledFlexContainer>
</>
);
};
// A styled div element with static styles for use inside ChildComponent
const StyledFlexContainer = styled(
"div",
`
display: flex;
gap: 1rem;
padding: 0.5rem;
width: 100%;
color: black;
`
);
// Some data
const people = [
{ name: "Marissa", age: 28, id: 1 },
{ name: "Dave", age: 34, id: 2 },
{ name: "Ronald", age: 54, id: 3 },
{ name: "Sarah", age: 47, id: 4 },
];
// The parent component that will map over the data and return the styled version of ChildComponent (see below for styles)
export const ParentComponent = () => {
return (
<>
{people.map((person) => (
<StyledChildComponent
name={person.name}
age={person.age}
id={person.id}
key={person.id}
/>
))}
</>
);
};
// Styled ChildComponent with dynamic styles based on props for use inside ParentComponent
const StyledChildComponent = styled(
ChildComponent,
({ name, age }: { name: string, age: number }) => `
background-color: ${name === "Ronald" ? "green" : "blue"};
:hover {
background-color: yellow;
}
> * {
color: ${age === 34 && "red"};
}
`
);
Tips and Tricks
Callbacks still work for static styles, just don't pass in any props.
Example:
// Static styles with string for second argument
const StyledDiv = styled(
"div",
`
padding: 1rem;
`
);
// Static styles with callback for second argument
const StyledDiv = styled(
"div",
() => `
padding: 1rem;
`
);
className override
Passing a custom className prop won't break css-template-components. Just keep in mind it may result in extra css-generation if more than one element shares the same css properties.
Example:
"use client";
import { styled } from "css-template-components/client";
export const MyComponent = () => {
return (
<StyledParagraph className="customClassName">
I have a custom className!
</StyledParagraph>
);
};
const StyledParagraph = styled(
"p",
`
padding: 1rem;
color: purple;
`
);