Skip to content

Features

next-yak is a featured packed static CSS-in-JS framework with a minimal runtime aspect.

Table of contents

  1. Static CSS
  2. Dynamic styles
  3. Compatible with utility-first CSS frameworks (e.g. Tailwind)
  4. Animations
  5. Mixins
  6. Automatic CSS variables
  7. Theming
  8. CSS Prop

Static CSS

At the heart of next-yak lies the extraction of static CSS. You can write your styles as you normally would with styled-components. During build time, these styles are extracted, and your component is assigned a class that encapsulates these styles.

import { styled } from 'next-yak';
 
const Headline = styled.h1`
  font-size: 2rem;
  font-weight: bold;
  color: rgba(253, 29, 29, 1);
`;
 
const Component = () => {
  return <Headline>Hello there!</Headline>
}
See transformed output
input
const Headline = styled.h1`
  font-size: 2rem;
  font-weight: bold;
  color: rgba(253, 29, 29, 1);
`;

Dynamic styles

The static functionality itself is already very useful, but the bread and butter is an easy way to create dynamic styles. Styled-components popularized the approach of using props to drive dynamic CSS parts. With next-yak, you can use the exact same familiar API.

javascript
import { css, styled } from 'next-yak';
 
const Paragraph = styled.p`
  background: ${props => props.$primary ? "#BF4F74" : "white"};
  ${props => props.$primary ? 
    css`
      color: white; 
    ` : 
    css`
      color: #BF4F74
    `};
  font-size: 2rem;
  font-weight: bold;
`;
 
const Component = () => {
  return (
    <>
      <Paragraph $primary>Hello there primary!</Paragraph>
      <Paragraph>Hello there non-primary!</Paragraph>
    </>
  );
}

The CSS templates create their own class which is referenced during runtime when the function returns them. The other function which returns strings directly without setting new CSS properties, will be changed to a CSS variable, which is set on the element itself directly based on the functions return value.

See transformed output
input
const Paragraph = styled.p`
  background: ${props => props.$primary ? "#BF4F74" : "white"};
  ${props => props.$primary ? 
    css`
      color: white; 
    ` : 
    css`
      color: #BF4F74;
    `}
  font-size: 2rem;
  font-weight: bold;
`;

Compatible with utility-first CSS frameworks (e.g. Tailwind)

next-yak is fully compatible with utility-first CSS frameworks like Tailwind. Just use the atoms function to reference classes from these frameworks.

javascript
import { styled, atoms } from 'next-yak';
 
const Header = styled.nav`
  ${({$variant}) => $variant === "primary"
    ? atoms("mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8")
    : atoms("bg-white hover:bg-gray-100 text-gray-800 font-semibold py-2 px-4 border border-gray-400 rounded shadow")
  }
`
See transformed output
input
const Header = styled.nav`
  ${({$variant}) => $variant === "primary"
    ? atoms("mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8")
    : atoms("bg-white hover:bg-gray-100 text-gray-800 font-semibold py-2 px-4 border border-gray-400 rounded shadow")
  }
`

Animations

In order to create CSS animations, you can use the keyframes API and specify the keyframes for the animation you want to create. This can be used in your animation declarations within the same file.

import { keyframes, styled } from 'next-yak';
 
const fadeIn = keyframes`
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
`
 
const FadeInButton = styled.button`
  animation: 1s ${fadeIn} ease-out;
`
See transformed output
input
const fadeIn = keyframes`
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
`
 
const FadeInButton = styled.button`
  animation: 1s ${fadeIn} ease-out;
`

Mixins

Mixins are declarations of the css utility function. You can declare a variable which holds the css declaration and use it inside your styled declarations.

import { css, styled } from 'next-yak';
 
const mixin = css`
  color: green;
`;
 
const MyComp = styled.div`
  background-color: yellow;
  ${mixin}
`;

You can also make it dynamic, where the props are passed to the mixin.

import { css, styled } from 'next-yak';
 
const mixin = css`
  color: ${(props) => props.$green ? 'green' : 'blue'};
`;
 
const MyComp = styled.div`
  background-color: yellow;
  ${mixin}
`;

During build time the CSS literal is converted to a class name (or multiple class names) and can be referenced by other CSS styles.

See transformed output
input
const mixin = css`
  color: ${(props) => props.$green ? 'green' : 'blue'};
`;
 
const MyComp = styled.div`
  background-color: yellow;
  ${mixin}
`;

Automatic CSS variables

You may noticed that we sometimes used css`` and sometimes just a literal string. If the property name is already present and you want to have dynamic values of that property, you can just use literal strings. These get transformed into CSS variables during build time.

javascript
import { styled } from 'next-yak';
 
const Box = styled.div`
  font-size: ${props => props.$variant === "primary" ? "2rem" : "1rem" };
  color: ${props => props.$color};
  display: flex;
`

The value of the CSS variable is set via the style property of the component, ensuring no interference with potential CSS variable names that share the same name.

See transformed output
input
const Box = styled.div`
  font-size: ${props => props.$variant === "primary" ? "2rem" : "1rem" };
  color: ${props => props.$color};
  display: flex;
`

Theming

As your application grows, theming becomes increasingly important as a shortcut to pass the same values to components. Next-yak integrates it in a hassle free manner that works for both Server Components and Client Components without a difference in usage for you. Wrap your root with the ThemeProvider and add a yak.context.ts file to your root directory and you're ready to go.

yak.context.ts
import { cookies } from 'next/headers'
import { cache } from "react";
const hasHighContrast = cache(() => {
    const cookieStore = cookies()
    return cookieStore.get("highContrast")?.value === "true"
});
 
export function getYakThemeContext() {
    return {
        // here we provide a hightContrast to all components
        highContrast: hasHighContrast()
    }
}
 
declare module "next-yak" {
    export interface YakTheme extends ReturnType<typeof getYakThemeContext> { }
}

Once this context file is in place, you can access the theme props on every component.

some-component.jsx
import { styled, css } from 'next-yak';
 
const Button = styled.button`
  display: block;
  ${(props) =>
    props.theme.highContrast
      ? css`
          color: #000;
        `
      : css`
          color: #009688;
        `}
`;

CSS Prop

We support out of the box the css prop which is a shorthand for adding styles to an element. Similiar to inline-styles it allows you to write local styles for certain elements on your page. Differently than inline-styles, it allows you to use selectors that target wrapped elements.

import { css } from 'next-yak';
 
const Component = () => {
  return <div css={{ color: 'red' }}>Hello there!</div>
}

It's meant for simple styling requirements, where you don't have to think about a name for a specialized component.

TypeScript

To use it with the correct types just add the following line to the top of the file

/** @jsxImportSource next-yak */
 
import { css } from 'next-yak';
 
const Component = () => {
  return <div css={{ color: 'red' }}>Hello there!</div>
}

Or just add this to your tsconfig.json and all your css props will have the correct types.

{
  "compilerOptions": {
    "jsxImportSource": "next-yak"
  }
}