tightset
v0.1.5
Published
Variable-weight text fitting engine — fill any rectangle with kinetic typography
Maintainers
Readme
Every line stretches to fill the width, with heavier weight on larger lines. Works with any variable-weight font. Ships with React, Svelte, Vue, Angular, vanilla Canvas, and DOM/Tailwind renderers.
Install
npm install tightsetQuick Start
import { fit } from 'tightset'
import { render } from 'tightset/canvas'
await document.fonts.ready // always wait for fonts before canvas rendering
const result = fit('Every Line Fills The Width', {
width: 800,
height: 500,
fontFamily: 'Inter',
})
render(document.querySelector('canvas'), result, {
fontFamily: 'Inter',
color: '#ffffff',
background: '#0d0d0d',
})Font loading: Canvas mode measures text via the Canvas 2D API, so the font must be fully loaded before calling
fit(). Wait fordocument.fonts.readyor use the CSS Font Loading API. The framework components (tightset/react,tightset/vue, etc.) use canvas internally — ensure your fonts are loaded before they mount, or trigger a re-render once fonts are ready.
Packages
| Import | What |
|--------|------|
| tightset | Core engine: fit(), clearCache(), setMeasureContext() |
| tightset/canvas | Canvas 2D draw() and render() |
| tightset/dom | renderToHTML(), renderToDOM(), getLineStyles() — for Tailwind/CSS |
| tightset/react | <Tightset> React component |
| tightset/svelte | <Tightset> Svelte component |
| tightset/vue | <Tightset> Vue component |
| tightset/angular | <TightsetComponent> Angular standalone component |
React
import { Tightset } from 'tightset/react'
<Tightset
text="Make It Tight"
width={800}
height={500}
fontFamily="Inter"
color="#fff"
background="#000"
/>Svelte
<script>
import Tightset from 'tightset/svelte'
</script>
<Tightset
text="Hello World"
width={800}
height={500}
fontFamily="Inter"
color="#fff"
background="#000"
/>Vue
<script setup>
import Tightset from 'tightset/vue'
</script>
<template>
<Tightset
text="Hello World"
:width="800"
:height="500"
fontFamily="Inter"
mode="html"
/>
</template>Angular
Note: The Angular component is shipped as TypeScript source (not pre-compiled), so it cannot be consumed directly from
node_moduleswith AOT compilation. Copy the component into your project fromnode_modules/tightset/dist/angular/tightset.component.ts, or use the source from src/angular.
// Copy tightset.component.ts into your project, then:
import { TightsetComponent } from './tightset.component'
@Component({
standalone: true,
imports: [TightsetComponent],
template: `
<tightset
text="Make It Tight"
[width]="800"
[height]="500"
fontFamily="Inter"
color="#ffffff"
background="#0d0d0d"
/>
`,
})
export class MyComponent {}Tailwind / DOM
import { fit } from 'tightset'
import { renderToHTML } from 'tightset/dom'
const result = fit('Style Me', { width: 800, height: 400, fontFamily: 'Inter' })
const html = renderToHTML(result, {
fontFamily: 'Inter',
containerClass: 'bg-black rounded-2xl',
lineClass: 'tracking-tight drop-shadow-lg',
})Or get style objects for JSX:
import { getLineStyles } from 'tightset/dom'
const styles = getLineStyles(result, { fontFamily: 'Inter' })
result.lines.map((line, i) => <div style={styles[i]} className="drop-shadow-lg">{line}</div>)Options
| Option | Default | Description |
|--------|---------|-------------|
| width | — | Box width (px, required) |
| height | — | Box height (px, required) |
| fontFamily | 'sans-serif' | Font family name |
| padX | 60 | Horizontal padding |
| padY | 40 | Vertical padding |
| gap | 20 | Line gap |
| maxWeight | 900 | Heaviest font weight |
| spread | 150 | Weight range (heavy − light) |
| maxLines | 8 | Max lines |
| uppercase | true | Uppercase transform |
Node.js / SSR
import { createCanvas } from 'canvas'
import { setMeasureContext, fit } from 'tightset'
setMeasureContext(createCanvas(1, 1).getContext('2d'))
const result = fit('Server Side', { width: 800, height: 400 })Demo
Live demo → dmoptimal.github.io/tightset
Or run locally:
npx serve .
# Open http://localhost:3000/docs/License
MIT
