diff --git a/src/components/AutoAdjustFontSize/AutoAdjustFontSize.mdx b/src/components/AutoAdjustFontSize/AutoAdjustFontSize.mdx
new file mode 100644
index 0000000..4c5d53d
--- /dev/null
+++ b/src/components/AutoAdjustFontSize/AutoAdjustFontSize.mdx
@@ -0,0 +1,50 @@
+import { Meta, Canvas, Story } from '@storybook/addon-docs/blocks';
+import { AutoAdjustFontSize } from './AutoAdjustFontSize';
+import * as stories from './AutoAdjustFontSize.stories';
+
+
+
+# AutoAdjustFontSize
+
+A component that automatically adjusts the font size of its children to fit within its parent
+container.
+
+## Props
+
+- `children`: The content to be displayed within the component.
+- `minFontSize`: The minimum font size in pixels. Default is 13 (minimal accessible font size).
+- `maxFontSize`: The maximum font size in pixels.
+- `axis`: The axis along which the font size should be adjusted. Can be 'x' or 'y'. Default is
+ undefined (both axes).
+
+## Usage
+
+```tsx
+
+ Hello World!
+
+```
+
+Limit the font adjust to an axis:
+
+```tsx
+
+ Hello World!
+
+```
+
+```tsx
+
+ Hello World!
+
+```
+
+## Demo
+
+
+
+
diff --git a/src/components/AutoAdjustFontSize/AutoAdjustFontSize.stories.tsx b/src/components/AutoAdjustFontSize/AutoAdjustFontSize.stories.tsx
new file mode 100644
index 0000000..b916e57
--- /dev/null
+++ b/src/components/AutoAdjustFontSize/AutoAdjustFontSize.stories.tsx
@@ -0,0 +1,142 @@
+import { expect } from '@storybook/jest';
+import { type Meta, type StoryObj } from '@storybook/react';
+import { within } from '@storybook/testing-library';
+import { createTimeout } from '../../utils/createTimeout/createTimeout.js';
+import { AutoAdjustFontSize } from './AutoAdjustFontSize.js';
+
+const meta = {
+ title: 'Components / AutoAdjustFontSize',
+ component: AutoAdjustFontSize,
+ argTypes: {
+ minFontSize: {
+ control: {
+ type: 'number',
+ },
+ },
+ maxFontSize: {
+ control: {
+ type: 'number',
+ },
+ },
+ axis: {
+ options: ['x', 'y'],
+ control: { type: 'select' },
+ },
+ },
+} satisfies Meta;
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Horizontal: Story = {
+ args: {
+ children: "Hello World, how's life?",
+ axis: 'x',
+ },
+ render(props) {
+ return (
+
+ );
+ },
+};
+
+export const HorizontalStatic: Story = {
+ args: {
+ children: "Hello World, how's life?",
+ axis: 'x',
+ },
+ render(props) {
+ return (
+
+ );
+ },
+ async play({ canvasElement }) {
+ const canvas = within(canvasElement);
+ const element = canvas.getByText("Hello World, how's life?");
+
+ await createTimeout(100);
+
+ expect(element).toHaveStyle({
+ fontSize: '24px',
+ whiteSpace: 'nowrap',
+ });
+ },
+};
+
+export const Vertical: Story = {
+ args: {
+ children: "Hello World, how's life?",
+ axis: 'y',
+ },
+ render(props) {
+ return (
+
+ );
+ },
+};
+
+export const VerticalStatic: Story = {
+ args: {
+ children: "Hello World, how's life?",
+ axis: 'y',
+ },
+ render(props) {
+ return (
+
+ );
+ },
+ async play({ canvasElement }) {
+ const canvas = within(canvasElement);
+ const element = canvas.getByText("Hello World, how's life?");
+
+ await createTimeout(100);
+
+ expect(element).toHaveStyle({
+ fontSize: '24px',
+ whiteSpace: 'nowrap',
+ });
+ },
+};
diff --git a/src/components/AutoAdjustFontSize/AutoAdjustFontSize.tsx b/src/components/AutoAdjustFontSize/AutoAdjustFontSize.tsx
new file mode 100644
index 0000000..545c9f2
--- /dev/null
+++ b/src/components/AutoAdjustFontSize/AutoAdjustFontSize.tsx
@@ -0,0 +1,53 @@
+import { useCallback, useEffect, useState, type ComponentProps, type ReactNode } from 'react';
+import { ensuredForwardRef } from '../../hocs/ensuredForwardRef/ensuredForwardRef.js';
+import { useResizeObserver } from '../../hooks/useResizeObserver/useResizeObserver.js';
+import { adjustFontSize } from '../../utils/adjustFontSize/adjustFontSize.js';
+
+type AutoAdjustFontSizeProps = ComponentProps<'div'> & {
+ children: ReactNode;
+ minFontSize?: number;
+ maxFontSize?: number;
+ axis?: 'x' | 'y';
+};
+
+export const AutoAdjustFontSize = ensuredForwardRef(
+ ({ children, minFontSize, maxFontSize, axis, style }, ref) => {
+ const [parentElement, setParentElement] = useState(null);
+
+ const updateFontSize = useCallback(() => {
+ if (!ref.current) {
+ return;
+ }
+
+ adjustFontSize(ref.current, minFontSize, maxFontSize, axis);
+ }, [axis, maxFontSize, minFontSize, ref]);
+
+ useEffect(() => {
+ if (!ref.current) {
+ return;
+ }
+
+ setParentElement(ref.current.parentElement);
+
+ updateFontSize();
+ ref.current.style.visibility = 'visible';
+ }, [ref, updateFontSize]);
+
+ useResizeObserver(parentElement, updateFontSize);
+
+ return (
+
+ {children}
+
+ );
+ },
+);
diff --git a/src/index.ts b/src/index.ts
index c2c4918..0338099 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,4 +1,5 @@
/* PLOP_ADD_EXPORT */
+export * from './components/AutoAdjustFontSize/AutoAdjustFontSize.js';
export * from './components/AutoFill/AutoFill.js';
export * from './gsap/components/SplitTextWrapper/SplitTextWrapper.js';
export * from './gsap/hooks/useAnimation/useAnimation.js';
@@ -37,6 +38,7 @@ export * from './lifecycle/hooks/useIsMountedState/useIsMountedState.js';
export * from './lifecycle/hooks/useMount/useMount.js';
export * from './lifecycle/hooks/useUnmount/useUnmount.js';
export * from './nextjs/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.js';
+export * from './utils/adjustFontSize/adjustFontSize.js';
export * from './utils/arrayRef/arrayRef.js';
export * from './utils/createTimeout/createTimeout.js';
export * from './utils/isRefObject/isRefObject.js';
diff --git a/src/utils/adjustFontSize/adjustFontSize.mdx b/src/utils/adjustFontSize/adjustFontSize.mdx
new file mode 100644
index 0000000..77faed1
--- /dev/null
+++ b/src/utils/adjustFontSize/adjustFontSize.mdx
@@ -0,0 +1,37 @@
+import { Meta, Canvas, Story } from '@storybook/blocks';
+import { adjustFontSize } from './adjustFontSize';
+
+
+
+# adjustFontSize
+
+Adjusts the font size of an HTML element to fit within its parent container.
+
+## Reference
+
+```ts
+function adjustFontSize(
+ element: HTMLElement,
+ minFontSize = 13,
+ maxFontSize = 113,
+ axis?: 'x' | 'y',
+) => void;
+```
+
+## Parameters
+
+- `element`: The HTML element whose font size needs to be adjusted.
+- `minFontSize`: The minimum font size in pixels. Default is 13 (minimal accessible font size).
+- `maxFontSize`: The maximum font size in pixels.
+- `axis`: The axis along which the font size should be adjusted. Can be 'x' or 'y'. Default is
+ undefined (both axes).
+
+## Usage
+
+```ts
+const element = document.createElement('div');
+element.textContent = 'Hello, world!';
+document.body.appendChild(element);
+
+adjustFontSize(element);
+```
diff --git a/src/utils/adjustFontSize/adjustFontSize.tsx b/src/utils/adjustFontSize/adjustFontSize.tsx
new file mode 100644
index 0000000..60db77e
--- /dev/null
+++ b/src/utils/adjustFontSize/adjustFontSize.tsx
@@ -0,0 +1,57 @@
+/**
+ * Adjusts the font size of an HTML element to fit within its parent container.
+ *
+ * @param element - The HTML element whose font size needs to be adjusted.
+ * @param minFontSize - The minimum font size in pixels. Default is 13 (minimal accessible font size).
+ * @param maxFontSize - The maximum font size in pixels.
+ * @param axis - The axis along which the font size should be adjusted. Can be 'x' or 'y'. Default is undefined (both axes).
+ *
+ * @throws {TypeError} If the parent element is null or if minFontSize is greater than maxFontSize.
+ */
+export function adjustFontSize(
+ element: HTMLElement,
+ // eslint-disable-next-line default-param-last
+ minFontSize = 13,
+ // eslint-disable-next-line default-param-last
+ maxFontSize?: number,
+ axis?: 'x' | 'y',
+): void {
+ if (maxFontSize && minFontSize > maxFontSize) {
+ throw new TypeError('minFontSize is greater than maxFontSize');
+ }
+
+ if (element.parentElement === null) {
+ throw new TypeError('Parent element is null');
+ }
+
+ // minimum font size in pixels
+ let min = minFontSize;
+ // maximum font size in pixels
+ let max =
+ maxFontSize ?? Math.max(element.parentElement.clientWidth, element.parentElement.clientHeight);
+ let lastGoodFontSize;
+
+ while (min <= max) {
+ const mid = Math.floor((min + max) / 2);
+ element.style.fontSize = `${mid}px`;
+
+ const { width: elementWidthAfterLayout, height: elementHeightAfterLayout } =
+ element.getBoundingClientRect();
+ const { width: parentElementWidthAfterLayout, height: parentElementHeightAfterLayout } =
+ element.parentElement.getBoundingClientRect();
+
+ const exceedsWidth = axis !== 'y' && elementWidthAfterLayout > parentElementWidthAfterLayout;
+ const exceedsHeight = axis !== 'x' && elementHeightAfterLayout > parentElementHeightAfterLayout;
+
+ if (exceedsWidth || exceedsHeight) {
+ // If the text is too wide/tall, decrease the font size
+ max = mid - 1;
+ } else {
+ // If the text fits, increase the font size
+ lastGoodFontSize = mid;
+ min = mid + 1;
+ }
+ }
+
+ element.style.fontSize = `${lastGoodFontSize}px`;
+}