Rapidly build Kesko-branded websites and applications straight from your HTML, with one stylesheet and a set of utility classes.
Kesko CSS Framework bundles our design tokens, the base Kesko theme, the Skatta Sans UI typeface, and Tailwind-style utility classes in a single lightweight stylesheet, so you need just one package instead of installing @kesko/tokens and @kesko/fonts separately.
Every utility class maps to a design token, so you get the right value without writing CSS of your own, and your styles follow along when a brand theme changes those tokens. All selectors are prefixed with k- to prevent collisions with other frameworks.
Installation #
To install the CSS framework as a dependency in your project, run:
npm install @kesko/csspnpm add @kesko/cssyarn add @kesko/cssbun add @kesko/cssFrom the CDN #
The CSS framework can also be loaded straight from the Kesko CDN, which lets your team use it with a single tag, without installing anything. Add the tag below to the <head> of your page to get the latest version:
<link
rel="stylesheet"
href="https://cdn.kesko.design/css/1.0.0-rc.3/kesko.min.css"
integrity="sha384-+nXisOl3c1677FsguFAVqmER5VVvNO4CB7DFiQARPhNecGhBrHTh6IYxNIrHFb5L"
crossorigin="anonymous"
/>See the CDN guidelines for more details.
Usage #
The package ships a single stylesheet, kesko.min.css, which gives you:
- Design tokens as CSS custom properties, e.g.
var(--k-color-text) - Utility classes for colors, typography, spacing, and more
- Webfonts and their
@font-facedeclarations - Theme for the default Kesko brand
The webfonts ship next to the stylesheet in dist/. How you load the stylesheet depends on whether your project has a bundler.
With a bundler #
Import the package once at the root of your application. Vite, Parcel and Next.js resolve the url() references inside the stylesheet and emit the font files into your build output. A bare Webpack 5 or Rspack config also needs an asset/resource rule for font extensions, see Webfonts:
// src/main.js
import "@kesko/css";/* src/main.css */
@import "@kesko/css";// src/main.scss
@use "@kesko/css";// src/main.scss, compiled with the Node package importer
@use "pkg:@kesko/css";/* src/global.css */
@import "tailwindcss";
@import "@kesko/css";/* app/globals.css */
@import "@kesko/css";In Next.js, don’t combine this with next/font/local. It registers the typeface under a hashed family name and can’t share the @font-face rules @kesko/css already ships. Reference the typeface with var(--k-font-family-sans) instead (see the webfonts guidelines).
Without a bundler #
If you’d rather not host the files yourself, load the framework from the CDN instead. Otherwise, copy the package’s dist/ directory into your static assets as part of your build, so the stylesheet and the font files it references end up next to each other:
{
"scripts": {
"build:css": "cp -r node_modules/@kesko/css/dist/. public/assets/kesko/"
}
}Then link the stylesheet from the <head> of your document. The framework relies on the cascade, so the order of stylesheets matters:
<head>
<!-- 1. Preload the font weights you use (optional, but avoids a flash of fallback text) -->
<link rel="preload" href="/assets/kesko/SkattaSansUI_TT-Regular.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/assets/kesko/SkattaSansUI_TT-Bold.woff2" as="font" type="font/woff2" crossorigin />
<!-- 2. The framework: tokens, fonts and utilities -->
<link rel="stylesheet" href="/assets/kesko/kesko.min.css" />
<!-- 3. A brand theme, if you need one other than Kesko -->
<link rel="stylesheet" href="/assets/kesko/themes/k-rauta.css" />
<!-- 4. Your own styles -->
<link rel="stylesheet" href="/assets/app.css" />
</head>- Font preloads go first so the browser fetches the files before it parses the stylesheet that declares them. Preload only the weights you actually use; see the webfonts guidelines for the full list.
kesko.min.cssdeclares every--k-*custom property on:root, the@font-facerules and the utility classes.- A brand theme from
@kesko/themesonly redefines custom properties on:root, so it must come after the file that declares them. Copy the theme files the same way as the framework (node_modules/@kesko/themes/dist/). - Your own stylesheets come last so they win whenever a rule has the same specificity as a utility class.
The same order applies with a bundler: import @kesko/css first, then the theme, then your own styles.
Brand themes #
To apply a brand theme on top, add a theme override from @kesko/themes after the framework:
@import "@kesko/css";
@import "@kesko/themes/dist/k-rauta.css";Because all utility classes reference design token custom properties via var(), they automatically adapt when a theme overrides those properties. Switching brands means swapping one stylesheet; no utility classes change.
Webfonts #
kesko.min.css includes the same @font-face rules as @kesko/fonts: all eight Skatta Sans UI variants and the metrics-matched system fallback that avoids layout shift as long as you set the family through the var(--k-font-family-sans) token.
The webfonts guidelines cover preloading, cache headers and offline support; they apply here unchanged, with the font files served from wherever you placed dist/.
Utility classes #
Utility classes shipped in the Kesko CSS Framework follow Tailwind CSS conventions, prefixed with k-. Each class name follows the pattern .k-{property}-{value}, for example .k-gap-md.
Some classes also have a side. The diagram below breaks down .k-gap-x-lg: the k prefix, the property gap, the side x (horizontal) and the size lg. Leave out the size to get the default. For example, .k-gap adds the default gap.
Directional variants use CSS logical properties, so your styles continue to work when the writing direction changes. The side suffixes are written as the initial of the logical property they map to:
| Suffix | Logical property | In left-to-right languages |
|---|---|---|
s | inline-start | Left |
e | inline-end | Right |
t | block-start | Top |
b | block-end | Bottom |
x | inline | Left and right |
y | block | Top and bottom |
Values follow the T-shirt size scale (xs, sm, md, lg, …) or a semantic token name (primary, dim, success, …), matching the design tokens they map to.
Text colors #
Set color from the text color tokens.
<p class="k-text">Default text</p>
<p class="k-text-dim">Secondary text</p>
<p class="k-text-primary">Primary text</p>Background colors #
Set background-color from the background, status, theme and highlight color tokens.
<div class="k-bg">Default background</div>
<div class="k-bg-primary">Primary tinted surface</div>
<div class="k-bg-theme">Brand color surface</div>
<div class="k-bg-theme-primary">Same, with the explicit name</div>Borders #
The base .k-border class applies a solid border using --k-size-border width and --k-color-border color. Directional variants use CSS logical properties. Color variants come from the border color tokens and change only the border-color.
<div class="k-border">All sides</div>
<div class="k-border-t">Top only</div>
<div class="k-border k-border-primary">Primary border color</div>Border radius #
Set border-radius from the radius tokens.
<div class="k-rounded">Default radius (md)</div>
<div class="k-rounded-lg">Large radius</div>
<div class="k-rounded-pill">Pill shape</div>Font sizes #
Set font-size from the font size tokens.
<p class="k-text-sm">Small text</p>
<p class="k-text-lg">Large text</p>
<h1 class="k-text-3xl">Heading</h1>Font weights #
Set font-weight from the font weight tokens.
<span class="k-font-normal">Normal</span>
<span class="k-font-bold">Bold</span>
<span class="k-font-black">Black</span>Font families #
Set font-family from the font family tokens.
<p class="k-font-sans">Sans-serif text</p>
<code class="k-font-code">Monospace text</code>Line heights #
Set line-height from the font leading tokens.
<p class="k-leading-sm">Tight leading</p>
<p class="k-leading">Comfortable leading</p>Padding #
The spacing tokens are available as padding and margin utilities. Sides are addressed with the logical side suffixes (s, e, t, b, x, y), so your spacing continues to work when the writing direction changes, and sizes follow the T-shirt scale.
<div class="k-p">16px padding on all sides (default)</div>
<div class="k-px-lg k-py-sm">24px inline, 12px block</div>
<div class="k-pt-xl">32px padding at block-start</div>- Available suffixes:
k-p,k-px,k-py,k-ps,k-pe,k-pt,k-pb - Available sizes:
4xs,3xs,2xs,xs,sm,md,lg,xl,2xl,3xl
Margin #
Same directional pattern as padding (k-m, k-mx, k-my, k-ms, k-me, k-mt, k-mb). Every form also accepts auto (k-m-auto, k-mx-auto, k-ms-auto, …) for centering or pushing an element to the end of a flex or grid container.
<div class="k-m">16px margin on all sides (default)</div>
<div class="k-mx-auto" style="width: 20rem">Centered block</div>
<div style="display: flex"><button class="k-ms-auto">Pushed to the end</button></div>Gap #
Set gap from the spacing tokens, used with flexbox or grid layouts. k-gap-x-{size} sets only column-gap and k-gap-y-{size} only row-gap.
<div class="k-gap" style="display: flex">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
<div class="k-gap-x-lg k-gap-y-xs" style="display: grid; grid-template-columns: repeat(3, 1fr)">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
</div>Box shadows #
Set box-shadow from the shadow tokens.
<div class="k-shadow">Subtle shadow</div>
<div class="k-shadow-float">Floating card</div>
<div class="k-shadow-popover">Popover shadow</div>When classes aren’t enough #
Utility classes cover the common cases, but for anything they don’t (e.g. a hover state), use the design tokens directly in your own CSS. They are the same --k-* custom properties the utilities read, listed on the design tokens page:
.product-card {
max-inline-size: 20rem;
border-start-start-radius: var(--k-radius-lg);
border-start-end-radius: var(--k-radius-lg);
}
.product-card:hover {
background: var(--k-color-bg-surface);
}Because your CSS and the utility classes read the same custom properties, a brand theme or dark stylesheet updates both at once. Prefer the semantic tokens (--k-color-bg-surface) over palette steps (--k-color-neutral-200) so your styles follow the theme.
Example #
Combining utilities to build a card. Classes without a size suffix use the default value. The button uses the .k-button component class, which ships in the separate components.min.css add-on:
Card title
Supporting text in a muted color with comfortable line height.
<div class="k-bg k-p-lg k-rounded-lg k-shadow-float">
<h2 class="k-text k-text-2xl k-font-black k-mb-sm">Card title</h2>
<p class="k-text-dimmer k-text-md k-leading k-mb">Supporting text in a muted color with comfortable line height.</p>
<button class="k-button k-button-primary" type="button">Action</button>
</div>