Customization
Change colors, fonts, spacing, and layouts using Ink's design token system and Nunjucks templates.
Design Tokens
Ink uses CSS custom properties (design tokens) defined in the :root selector of your stylesheet. If you chose the default CSS starter during ink init, tokens live in src/css/main.css. If you chose Tailwind CSS, they live in the @layer base block of src/css/tailwind.css and your brand colors are also configured in tailwind.config.js.
Changing a single variable updates every element that references it -- buttons, links, headings, components, and more.
Colors
:root {
--color-primary: #2563eb;
--color-primary-dark: #1d4ed8;
--color-primary-light: #60a5fa;
--color-secondary: #f59e0b;
--color-background: #ffffff;
--color-surface: #f8fafc;
--color-dark: #0f172a;
--color-text: #334155;
--color-text-muted: #94a3b8;
--color-text-inverse: #ffffff;
--color-border: #e2e8f0;
}
To rebrand your site, change --color-primary and its dark/light variants. The ink init wizard sets these for you during project creation, but you can edit them at any time.
Typography
:root {
--font-body: system-ui, -apple-system, sans-serif;
--font-heading: system-ui, -apple-system, sans-serif;
--font-mono: ui-monospace, "Cascadia Code", monospace;
}
To use a custom font, add a @font-face declaration or a Google Fonts @import at the top of main.css, then update the variable:
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
:root {
--font-body: "Inter", system-ui, sans-serif;
--font-heading: "Inter", system-ui, sans-serif;
}
Font Sizes
Ink uses fluid typography with clamp() values that scale smoothly between viewport sizes:
:root {
--text-sm: clamp(0.8rem, 0.17vw + 0.76rem, 0.89rem);
--text-base: clamp(1rem, 0.34vw + 0.91rem, 1.19rem);
--text-lg: clamp(1.25rem, 0.61vw + 1.1rem, 1.58rem);
--text-xl: clamp(1.56rem, 1vw + 1.31rem, 2.11rem);
--text-2xl: clamp(1.95rem, 1.56vw + 1.56rem, 2.81rem);
--text-3xl: clamp(2.44rem, 2.38vw + 1.85rem, 3.75rem);
--text-display: clamp(3.05rem, 3.54vw + 2.17rem, 5rem);
}
Spacing
Consistent spacing scale used for margins, padding, and gaps:
:root {
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 1.5rem;
--space-xl: 2rem;
--space-2xl: 4rem;
}
Layout Widths
Control the maximum width of content areas:
:root {
--content-width: 72rem;
--content-narrow: 42rem;
--content-wide: 90rem;
--gutter: 1.5rem;
}
Borders and Shadows
:root {
--radius: 0.375rem;
--radius-lg: 0.75rem;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
}
Custom Layouts
Layouts live in src/_layouts/. Every layout extends a base template and defines blocks for content. To create a custom layout:
- Create a new file in
src/_layouts/, for examplelanding.njk:
---
layout: base.njk
---
<main class="landing-page">
<section class="hero">
<h1>{{ title }}</h1>
<p>{{ excerpt }}</p>
</section>
<section class="landing-content">
{{ content | safe }}
</section>
</main>
- Reference it in your content's frontmatter:
---
title: "Spring Sale"
layout: landing.njk
permalink: "/spring-sale/"
---
Adding Partials
Partials (reusable template fragments) live in src/_includes/. Create a new .njk file and include it in any layout or page:
<!-- src/_includes/cta-banner.njk -->
<div class="cta-banner">
<h2>Ready to get started?</h2>
<a href="/contact/" class="btn btn-primary">Contact Us</a>
</div>
Use it in a layout or page:
{% include "cta-banner.njk" %}
Overriding Component Styles
Every installed component's CSS is marked with a comment header in your stylesheet (src/css/main.css or src/css/tailwind.css). To override styles, either:
-
Edit the component's CSS block directly -- Find the
/* Component: component-name */comment and modify the rules. -
Add overrides after the component block -- This keeps the original intact so you can see what changed:
/* Component: contact-form */
/* ... original component styles ... */
/* Custom overrides */
.contact-form .btn-submit {
background: var(--color-secondary);
border-radius: var(--radius-lg);
}
- Use design tokens -- The most maintainable approach. If a component uses
var(--color-primary), changing the token changes the component everywhere.
Dark Mode
Ink does not ship with a built-in dark mode toggle, but the design token system makes it straightforward to add one. Define a dark theme by overriding tokens inside a prefers-color-scheme media query or a .dark class:
@media (prefers-color-scheme: dark) {
:root {
--color-background: #0f172a;
--color-surface: #1e293b;
--color-text: #e2e8f0;
--color-text-muted: #94a3b8;
--color-border: #334155;
}
}
Because every element references these tokens, the entire site adapts automatically.