Skip to content

Instantly share code, notes, and snippets.

@ErfanEbrahimnia
Last active August 27, 2024 19:23
Show Gist options
  • Save ErfanEbrahimnia/b63bd71d7db6d48900f96215b1630770 to your computer and use it in GitHub Desktop.
Save ErfanEbrahimnia/b63bd71d7db6d48900f96215b1630770 to your computer and use it in GitHub Desktop.
Adjust element size based on container using CSS transform
import { useLayoutEffect, useRef, useState } from "react";
import { flushSync } from "react-dom";
export function useResizeScale<
ContainerRef extends HTMLElement,
InnerRef extends HTMLElement,
>({ width }: { width: number }) {
const containerRef = useRef<ContainerRef | null>(null);
const innerRef = useRef<InnerRef | null>(null);
const [innerStyle, setInnerStyle] = useState<React.CSSProperties>({});
useLayoutEffect(() => {
const adjustSize = () => {
const iframe = innerRef.current;
const container = containerRef.current;
if (!iframe || !container) return;
const scaleFactor = container.clientWidth / width;
setInnerStyle({
width,
height: container.clientHeight / scaleFactor,
transform: `scale(${scaleFactor})`,
transformOrigin: "top left",
});
};
adjustSize();
const resizeObserver = new ResizeObserver(() => {
// Use flushSync to prevent visual jitter from async state updates.
flushSync(() => {
adjustSize();
});
});
if (containerRef.current) {
resizeObserver.observe(containerRef.current);
}
return () => resizeObserver.disconnect();
}, [width]);
return { innerRef, containerRef, innerStyle };
}
@ErfanEbrahimnia
Copy link
Author

ErfanEbrahimnia commented Aug 27, 2024

Useful for scaling iframes

Demo:

resize_out.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment