Skip to content

Instantly share code, notes, and snippets.

@Iamsheye
Created May 29, 2024 10:37
Show Gist options
  • Save Iamsheye/6eaba85f50febd7b5e98f99cc43e04a9 to your computer and use it in GitHub Desktop.
Save Iamsheye/6eaba85f50febd7b5e98f99cc43e04a9 to your computer and use it in GitHub Desktop.
Fit Text to width
"use client";
import React, { useEffect, useRef, useCallback } from "react";
type IFittyProps = {
children: React.ReactNode;
minSize?: number;
maxSize?: number;
multiLine?: boolean;
};
const Fitty = ({
children,
minSize = 16,
maxSize = 512,
multiLine = true,
}: IFittyProps) => {
const ref = useRef<HTMLDivElement | null>(null);
const fitText = useCallback(() => {
const element = ref.current;
if (!element) return;
const parentElement = element.parentElement;
if (!parentElement) return;
const style = window.getComputedStyle(element);
const parentWidth = parentElement.clientWidth;
const currentWidth = element.scrollWidth;
const previousFontSize = parseFloat(style.fontSize);
const newFontSize = Math.min(
Math.max(minSize, (parentWidth / currentWidth) * previousFontSize),
maxSize,
);
element.style.whiteSpace =
multiLine && newFontSize === minSize ? "normal" : "nowrap";
element.style.fontSize = `${newFontSize}px`;
}, [minSize, maxSize, multiLine]);
useEffect(() => {
const handleResize = () => {
fitText();
};
window.addEventListener("resize", handleResize);
fitText();
return () => {
window.removeEventListener("resize", handleResize);
};
}, [fitText]);
return (
<div ref={ref} style={{ display: "inline-block", whiteSpace: "nowrap" }}>
{children}
</div>
);
};
export default Fitty;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment