The main idea is to use an SVG wrapper with foreingObject around the HTML code of the block content. With the SVG wrapper, we can use the viewBox property to make a scalable SVG that maintains its size ratio.
In addition, it uses ResizeObserver and a span wrapper with width: fit-content to monitor changes in the SVG content. That way, we can react to any changes that modify the text dimensions and update viewBox accordingly. This only happens when the text size ratio changes.
(*) The viewBox property is computed in the editor and persisted in the HTML. This effectively sets an initial value for viewBox without JavaScript, which mitigates the problem of scaling the SVG with code. However, that value is not 100% reliable, as different users could see different fonts with different sizes for the same text.
Alternatives
Window 'resize' event + computed font-size
This approach only reacts to changes in the viewport size, meaning that the size won't be re-computed when the element content changes dynamically or when the parent container dimensions change. Also, the font-size prop should be updated anytime the available width changes per frame.
ResizeObserver (95.37%) + computed font-size
This approach is similar to the above, but it uses a ResizeObserver in the parent container rather than subscribing to resize events on window. It can react to the available width, although it still has to update font-sizeper frame.
Container Query Units (90.97%) + ResizeObserver + computed var(--ratio)
This one is similar to the SVG approach. The difference is that it uses container query units to set a font-size value relative to the container's width. The text's height/width ratio is re-calculated whenever the text changes and the font-size value updated accordingly.
Co-authored by @SantosGuillamot
What?
This PR adds a Stretchy block that makes its text fill all the available width. It's built on top of https://github.com/a8cteam51/special-projects-blocks-monorepo/pull/5.
The PR changes the block implementation, using SVGs to maintain the text ratio and some JavaScript code to update it whenever the text changes.
Features:
https://github.com/user-attachments/assets/d41a247c-d600-41f0-ba80-8762d1213370
How?
The implementation uses the following APIs, listed with the global usage % of browsers that support them:
ResizeObserver
(95.37%)foreignObject
(94.9%)fit-content
(94.9%)The main idea is to use an SVG wrapper with
foreingObject
around the HTML code of the block content. With theSVG
wrapper, we can use theviewBox
property to make a scalable SVG that maintains its size ratio.In addition, it uses
ResizeObserver
and aspan
wrapper withwidth: fit-content
to monitor changes in the SVG content. That way, we can react to any changes that modify the text dimensions and updateviewBox
accordingly. This only happens when the text size ratio changes.(*) The
viewBox
property is computed in the editor and persisted in the HTML. This effectively sets an initial value forviewBox
without JavaScript, which mitigates the problem of scaling the SVG with code. However, that value is not 100% reliable, as different users could see different fonts with different sizes for the same text.Alternatives
Window
'resize'
event + computedfont-size
This approach only reacts to changes in the viewport size, meaning that the size won't be re-computed when the element content changes dynamically or when the parent container dimensions change. Also, thefont-size
prop should be updated anytime the available width changes per frame.ResizeObserver
(95.37%) + computedfont-size
This approach is similar to the above, but it uses aResizeObserver
in the parent container rather than subscribing toresize
events onwindow
. It can react to the available width, although it still has to updatefont-size
per frame.Container Query Units (90.97%) +
ResizeObserver
+ computedvar(--ratio)
This one is similar to the SVG approach. The difference is that it uses container query units to set afont-size
value relative to the container's width. The text's height/width ratio is re-calculated whenever the text changes and thefont-size
value updated accordingly.CSS custom properties (89.97%) + Container Query Units This only-CSS solution could be based on Roman Komarov's Fit-to-Width Text technique. We tested it in the
feature/stretchy-type-paragraph
branch. It's reliable in most cases, but some fonts seem to be adjusted incorrectly.