Quickstart: No framework
1 Initialize project
npm create vite@latest css-hooks-playground -- --template vanilla-ts cd css-hooks-playground npm install @css-hooks/core remeda
2 Start dev server
npm run dev
Visit http://localhost:5173 to view changes in real time.
3 Set up CSS Hooks
Create a src/css.ts
module with the following contents:
import { buildHooksSystem } from "@css-hooks/core"; const createHooks = buildHooksSystem(); export const { styleSheet, on } = createHooks("&:active"); /** * Converts a style object to a string. * * @remarks * This functionality (or equivalent) would typically be bundled with an app framework. */ export function styleObjectToString(obj: Record<string, unknown>) { return Object.entries(obj) .filter( ([, value]) => typeof value === "string" || typeof value === "number", ) .map( ([property, value]) => `${/^--/.test(property) ? property : property.replace(/[A-Z]/g, x => `-${x.toLowerCase()}`)}: ${value}`, ) .join("; "); }
4 Add style sheet
Modify src/main.ts
to add the style sheet to the document:
import './style.css' import typescriptLogo from './typescript.svg' import viteLogo from '/vite.svg' import { setupCounter } from './counter.ts' import { styleSheet } from './css.ts' document.querySelector<HTMLDivElement>('#app')!.innerHTML = ` <style>${styleSheet()}</style> <div> <a href="https://vitejs.dev" target="_blank"> <img src="${viteLogo}" class="logo" alt="Vite logo" /> </a> <a href="https://www.typescriptlang.org/" target="_blank"> <img src="${typescriptLogo}" class="logo vanilla" alt="TypeScript logo" /> </a> <h1>Vite + TypeScript</h1> <div class="card"> <button id="counter" type="button"></button> </div> <p class="read-the-docs"> Click on the Vite and TypeScript logos to learn more </p> </div> ` setupCounter(document.querySelector<HTMLButtonElement>('#counter')!)
5 Add conditional style
Use the configured &:active
hook to implement an effect when the counter
button is pressed:
// src/main.ts import './style.css' import typescriptLogo from './typescript.svg' import viteLogo from '/vite.svg' import { setupCounter } from './counter.ts' import { styleSheet } from './css.ts' import { on, styleObjectToString, styleSheet } from './css.ts' import { pipe } from 'remeda' document.querySelector<HTMLDivElement>('#app')!.innerHTML = ` <style>${styleSheet()}</style> <div> <a href="https://vitejs.dev" target="_blank"> <img src="${viteLogo}" class="logo" alt="Vite logo" /> </a> <a href="https://www.typescriptlang.org/" target="_blank"> <img src="${typescriptLogo}" class="logo vanilla" alt="TypeScript logo" /> </a> <h1>Vite + TypeScript</h1> <div class="card"> <button id="counter" type="button"></button> <button id="counter" type="button" style="${styleObjectToString( pipe( { transition: 'transform 75ms', }, on('&:active', { transform: 'scale(0.9)' }) ) )}"> </button> </div> <p class="read-the-docs"> Click on the Vite and TypeScript logos to learn more </p> </div> ` setupCounter(document.querySelector<HTMLButtonElement>('#counter')!)