Languages
[Edit]
EN

React - stretch element content to parent with css transform scale

10 points
Created by:
Marcin
17500

In this article we would like to show how in React create component that scales content (child element) to container size keeping content aspect ratio.

That approach is usefull wne we want to scale some element that must have fixed size, e.g. Google Ads on mobile web browsers that must have fixed size. The code let us to set fixed content size that will be scaled to container component size with keeping content ratio - it solves fluid GPT Ads problem in web browser.

iframe element scaled to container size
iframe element scaled to container size

Note: this article uses component from article that describes how to monotor component size - AutoSizer component. To see the article go to this link.

Practical example:

// ONLINE-RUNNER:browser;

// Uncomment next line during working with JSX Compiler:
// import React from 'react';
// import ReactDOM from 'react-dom';

const AutoSizer = React.memo(({ interval, children, ...other }) => {
	const reference = React.useRef();
	const [size, setSize] = React.useState();
	React.useEffect(() => {
      	let storedWidth = size?.width;
      	let storedHeight = size?.height;
      	const id = setInterval(() => {
          	const element = reference.current;
        	if (element) {
              	const width = element.offsetWidth;
                const height = element.offsetHeight;
              	if (width != storedWidth || height != storedHeight) {
                  	storedWidth = width;
                  	storedHeight = height;
                    setSize({ width, height });
                }
            }
        }, interval ?? 100);
      	return () => {
        	clearInterval(id);
        }; 
	}, [interval]);
	return (
	  <div ref={reference} {...other}>
        {size && children && children(size.width, size.height)}
	  </div>
	);
});

const ContentStretcher = ({sizerInterval, contentWidth, contentHeight, children, ...other}) => (
  <AutoSizer 
    {...other}
    style={{
      ...other.style,
      position: 'relative',
      display: 'flex'
    }}
    interval={sizerInterval}
  >
    {(containerWidth, containerHeight) => {
  		const contentScale = 
              containerHeight * contentWidth < containerWidth * contentHeight
        	? containerHeight / contentHeight 
        	: containerWidth / contentWidth;
  		return (
          <div 
            style={{
              position: 'absolute',
              left: '50%',
              top: '50%',
              transform: `translate(-50%, -50%) scale(${contentScale})`,
              transformOrigin: '50% 50%',
            }}
          >
            {children}
          </div>
        );
    }}
  </AutoSizer>
);

// Usage example:

// It will create iframe with dirask.com that will be scalled up to container
// with keeping content aspect ratio.
//
const DiraskFrame = ({containerWidth, containerHeight, contentWidth, contentHeight}) => (
  <ContentStretcher 
    style={{
        background: '#e1e1e1',
        width: `${containerWidth}px`, 
        height: `${containerHeight}px`
    }}
    contentWidth={contentWidth}
    contentHeight={contentHeight}
  >
    <iframe 
      src="https://dirask.com/about" 
      style={{
        border: 'none',
        width: `${contentWidth}px`,
        height: `${contentHeight}px`
      }} 
    />
  </ContentStretcher>
);

const App = () => (
  <div>
    <DiraskFrame
      containerWidth={100}
      containerHeight={100}
      contentWidth={200}
      contentHeight={200}
    />
    <br />
    <DiraskFrame
      containerWidth={300}
      containerHeight={300}
      contentWidth={200}
      contentHeight={200}
    />
    <br />
    <DiraskFrame
      containerWidth={300}
      containerHeight={200}
      contentWidth={150}
      contentHeight={150}
    />
    <br />
    <DiraskFrame
      containerWidth={200}
      containerHeight={300}
      contentWidth={150}
      contentHeight={150}
    />
  </div>
);

const root = document.querySelector('#root');
ReactDOM.render(<App />, root );

 

Native Advertising
­čÜÇ
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

ÔŁĄ´ŞĆ­čĺ╗ ­čÖé

Join