Skip to content

Taurien/fittext

Repository files navigation

FitText.js (TypeScript)

A vanilla TypeScript port of the original FitText.js - makes font sizes flexible and responsive.

Credits

This project is a TypeScript port of the original FitText.js by @davatron5000. All credit for the original concept and implementation goes to the original authors.

Installation

npm install @taurien/fittext

Or with GitHub Packages:

npm install @taurien/fittext --registry=https://npm.pkg.github.com

Usage

import { fitText } from "@taurien/fittext";

// Using an element reference
const element = document.getElementById("responsive-headline");
const controller = fitText(element, {
  compressor: 1,
  minFontSize: 12,
  maxFontSize: 100,
});

// Or using a selector
fitText("#responsive-headline", {
  compressor: 1.2,
});

// Manually trigger resize
controller.resizer();

// Clean up when done
controller.destroy();

Usage with React (TSX)

Basic Usage with useRef and useEffect

import React, { useEffect, useRef } from "react";
import { fitText, FitTextController } from "@taurien/fittext";

function ResponsiveHeadline() {
  const headlineRef = useRef<HTMLHeadingElement>(null);
  const controllerRef = useRef<FitTextController | null>(null);

  useEffect(() => {
    if (headlineRef.current) {
      controllerRef.current = fitText(headlineRef.current, {
        compressor: 1.2,
        minFontSize: 20,
        maxFontSize: 100,
      });
    }

    // Cleanup on unmount
    return () => {
      controllerRef.current?.destroy();
    };
  }, []);

  return <h1 ref={headlineRef}>Your Responsive Headline</h1>;
}

Custom Hook (Reusable)

import { useEffect, useRef, RefObject } from "react";
import { fitText, FitTextOptions, FitTextController } from "@taurien/fittext";

function useFitText<T extends HTMLElement>(
  options?: FitTextOptions
): RefObject<T> {
  const elementRef = useRef<T>(null);
  const controllerRef = useRef<FitTextController | null>(null);

  useEffect(() => {
    if (elementRef.current) {
      controllerRef.current = fitText(elementRef.current, options);
    }

    return () => {
      controllerRef.current?.destroy();
    };
  }, [options]);

  return elementRef;
}

// Usage:
function MyComponent() {
  const headlineRef = useFitText<HTMLHeadingElement>({
    compressor: 1,
    minFontSize: 16,
    maxFontSize: 80,
  });

  return <h1 ref={headlineRef}>Responsive Text</h1>;
}

Wrapper Component

import React, { useEffect, useRef, ReactNode } from "react";
import { fitText, FitTextOptions, FitTextController } from "@taurien/fittext";

interface FitTextComponentProps extends FitTextOptions {
  children: ReactNode;
  className?: string;
  as?: keyof JSX.IntrinsicElements;
}

function FitTextComponent({
  children,
  className,
  as: Tag = "div",
  compressor,
  minFontSize,
  maxFontSize,
}: FitTextComponentProps) {
  const elementRef = useRef<HTMLElement>(null);

  useEffect(() => {
    if (elementRef.current) {
      const controller = fitText(elementRef.current, {
        compressor,
        minFontSize,
        maxFontSize,
      });

      return () => controller.destroy();
    }
  }, [compressor, minFontSize, maxFontSize]);

  return (
    <Tag ref={elementRef} className={className}>
      {children}
    </Tag>
  );
}

// Usage:
function App() {
  return (
    <FitTextComponent
      as="h1"
      compressor={1.5}
      minFontSize={20}
      maxFontSize={100}
      className="hero-title"
    >
      My Responsive Headline
    </FitTextComponent>
  );
}

API

fitText(element, options)

Parameters:

  • element: HTMLElement | string - DOM element or CSS selector
  • options: FitTextOptions (optional)
    • compressor: number - Controls resize aggressiveness (default: 1)
    • minFontSize: number - Minimum font size in pixels (default: no limit)
    • maxFontSize: number - Maximum font size in pixels (default: no limit)

Returns: FitTextController

  • resizer(): Manually trigger a resize calculation
  • destroy(): Remove event listeners and stop automatic resizing

License

MIT

Packages