The CSS Helper is experimental. The API may change in future versions.
The CSS Helper provides CSS-in-JS functionality with automatic scoping, allowing you to write CSS directly in your TypeScript/JavaScript code.
Import
import { css, cx, keyframes, Style, createCssContext } from 'hono/css'
Functions
css()
Defines scoped CSS styles and returns a unique class name.
function css(
strings: TemplateStringsArray,
...values: CssVariableType[]
): Promise<string>
strings
TemplateStringsArray
required
The CSS template string
values
CssVariableType[]
required
Values to interpolate into the CSS (variables, other css() results, etc.)
A unique class name for the scoped styles
Example
import { Hono } from 'hono'
import { css, Style } from 'hono/css'
import { html } from 'hono/html'
const app = new Hono()
app.get('/', (c) => {
const className = css`
background-color: #f0f0f0;
color: #333;
padding: 20px;
border-radius: 8px;
&:hover {
background-color: #e0e0e0;
}
`
return c.html(html`
<html>
<head>
${Style()}
</head>
<body>
<div class="${className}">
Hello, styled world!
</div>
</body>
</html>
`)
})
cx()
Combines multiple class names, similar to the popular classnames library.
function cx(
...args: (CssClassName | Promise<string> | string | boolean | null | undefined)[]
): Promise<string>
args
(CssClassName | Promise<string> | string | boolean | null | undefined)[]
required
Class names to combine. Falsy values are ignored.
Combined class names as a single string
Example
app.get('/button', (c) => {
const baseStyles = css`
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
`
const primaryStyles = css`
background-color: #007bff;
color: white;
`
const isActive = true
const activeStyles = css`
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.5);
`
const className = cx(
baseStyles,
primaryStyles,
isActive && activeStyles
)
return c.html(html`
<html>
<head>${Style()}</head>
<body>
<button class="${className}">Click me</button>
</body>
</html>
`)
})
keyframes()
Defines CSS keyframe animations.
function keyframes(
strings: TemplateStringsArray,
...values: CssVariableType[]
): CssClassNameCommon
strings
TemplateStringsArray
required
The keyframes template string
values
CssVariableType[]
required
Values to interpolate
A keyframes name that can be used in CSS animations
Example
import { css, keyframes, Style } from 'hono/css'
import { html } from 'hono/html'
app.get('/animation', (c) => {
const fadeIn = keyframes`
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
`
const animatedBox = css`
animation: ${fadeIn} 0.5s ease-in-out;
padding: 20px;
background: #007bff;
color: white;
`
return c.html(html`
<html>
<head>${Style()}</head>
<body>
<div class="${animatedBox}">Animated content!</div>
</body>
</html>
`)
})
Style()
Renders the <style> tag containing all accumulated CSS.
function Style(args?: { children?: Promise<string>; nonce?: string }): HtmlEscapedString
Optional CSS content to include in the style tag
Optional nonce attribute for Content Security Policy
A style tag containing all CSS styles used in the current render
Example
app.get('/', (c) => {
return c.html(html`
<html>
<head>
<title>My App</title>
${Style({ nonce: 'random-nonce-123' })}
</head>
<body>
<!-- Your content -->
</body>
</html>
`)
})
viewTransition()
Creates styles for view transitions API.
function viewTransition(
strings: TemplateStringsArray,
...values: CssVariableType[]
): Promise<string>
function viewTransition(content: Promise<string>): Promise<string>
function viewTransition(): Promise<string>
The CSS template for view transition
Example
import { css, viewTransition, Style } from 'hono/css'
import { html } from 'hono/html'
app.get('/transition', (c) => {
const transition = viewTransition`
slide-from-right
`
const element = css`
view-transition-name: ${transition};
padding: 20px;
`
return c.html(html`
<html>
<head>${Style()}</head>
<body>
<div class="${element}">Transitioning element</div>
</body>
</html>
`)
})
createCssContext()
Creates an isolated CSS context with a custom style ID.
function createCssContext({ id }: { id: string }): {
css: CssType
cx: CxType
keyframes: KeyframesType
viewTransition: ViewTransitionType
Style: StyleType
}
A unique identifier for the style tag
An object containing isolated versions of css, cx, keyframes, viewTransition, and Style
Example
import { createCssContext } from 'hono/css'
// Create isolated context for a specific part of your app
const { css, Style } = createCssContext({ id: 'my-component' })
app.get('/component', (c) => {
const className = css`
color: red;
`
return c.html(html`
<html>
<head>${Style()}</head>
<body>
<div class="${className}">Isolated styles</div>
</body>
</html>
`)
})
Features
Automatic Scoping
All styles defined with css() are automatically scoped with unique class names, preventing style conflicts:
const style1 = css`color: red;`
const style2 = css`color: blue;`
// Generates unique class names like: css-abc123, css-def456
Nesting Support
Supports CSS nesting for pseudo-classes and nested selectors:
const button = css`
padding: 10px;
&:hover {
background: #eee;
}
&.active {
font-weight: bold;
}
`
CSS Variables
Interpolate values and other styles:
const primaryColor = '#007bff'
const spacing = '20px'
const card = css`
padding: ${spacing};
background: ${primaryColor};
border-radius: 8px;
`
- Styles are generated on-demand during rendering
- Duplicate styles are automatically deduplicated
- The Style component must be included in the
<head> for styles to render
Types
type CssClassName = HtmlEscapedString & CssClassNameCommon
interface CssClassNameCommon {
[CLASS_NAME]: string
[STYLE_STRING]: string
[SELECTOR]: string
[SELECTORS]: Array<{
[CLASS_NAME]: string
[STYLE_STRING]: string
}>
}
type CssVariableType = string | number | CssClassNameCommon