EN
React - stretch element content to parent with css transform scale
10 points
In this article, we would like to show how in React create a component that scales content (child element) to container size keeping the content aspect ratio.
That approach is useful when 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 lets us set fixed content size that will be scaled to container component size with keeping content ratio - it solves fluid GPT Ads problem in a web browser.

Note: this article uses component from article that describes how to monitor component size -
AutoSizer
component. To see the article go to this link.
Practical example:
xxxxxxxxxx
1
// Uncomment next line during working with JSX Compiler:
2
// import React from 'react';
3
// import ReactDOM from 'react-dom';
4
5
const AutoSizer = React.memo(({ interval, children, other }) => {
6
const reference = React.useRef();
7
const [size, setSize] = React.useState();
8
React.useEffect(() => {
9
let storedWidth = size?.width;
10
let storedHeight = size?.height;
11
const id = setInterval(() => {
12
const element = reference.current;
13
if (element) {
14
const width = element.offsetWidth;
15
const height = element.offsetHeight;
16
if (width != storedWidth || height != storedHeight) {
17
storedWidth = width;
18
storedHeight = height;
19
setSize({ width, height });
20
}
21
}
22
}, interval ?? 100);
23
return () => {
24
clearInterval(id);
25
};
26
}, [interval]);
27
return (
28
<div ref={reference} {other}>
29
{size && children && children(size.width, size.height)}
30
</div>
31
);
32
});
33
34
const ContentStretcher = ({sizerInterval, contentWidth, contentHeight, children, other}) => (
35
<AutoSizer
36
{other}
37
style={{
38
other.style,
39
position: 'relative',
40
display: 'flex'
41
}}
42
interval={sizerInterval}
43
>
44
{(containerWidth, containerHeight) => {
45
const contentScale =
46
containerHeight * contentWidth < containerWidth * contentHeight
47
? containerHeight / contentHeight
48
: containerWidth / contentWidth;
49
return (
50
<div
51
style={{
52
position: 'absolute',
53
left: '50%',
54
top: '50%',
55
transform: `translate(-50%, -50%) scale(${contentScale})`,
56
transformOrigin: '50% 50%',
57
}}
58
>
59
{children}
60
</div>
61
);
62
}}
63
</AutoSizer>
64
);
65
66
// Usage example:
67
68
// It will create iframe with dirask.com that will be scalled up to container
69
// with keeping content aspect ratio.
70
71
const DiraskFrame = ({containerWidth, containerHeight, contentWidth, contentHeight}) => (
72
<ContentStretcher
73
style={{
74
background: '#e1e1e1',
75
width: `${containerWidth}px`,
76
height: `${containerHeight}px`
77
}}
78
contentWidth={contentWidth}
79
contentHeight={contentHeight}
80
>
81
<iframe
82
src="https://dirask.com/about"
83
style={{
84
border: 'none',
85
width: `${contentWidth}px`,
86
height: `${contentHeight}px`
87
}}
88
/>
89
</ContentStretcher>
90
);
91
92
const App = () => (
93
<div>
94
<DiraskFrame
95
containerWidth={100}
96
containerHeight={100}
97
contentWidth={200}
98
contentHeight={200}
99
/>
100
<br />
101
<DiraskFrame
102
containerWidth={300}
103
containerHeight={300}
104
contentWidth={200}
105
contentHeight={200}
106
/>
107
<br />
108
<DiraskFrame
109
containerWidth={300}
110
containerHeight={200}
111
contentWidth={150}
112
contentHeight={150}
113
/>
114
<br />
115
<DiraskFrame
116
containerWidth={200}
117
containerHeight={300}
118
contentWidth={150}
119
contentHeight={150}
120
/>
121
</div>
122
);
123
124
const root = document.querySelector('#root');
125
ReactDOM.render(<App />, root );