Autoheight WebView
Craft WebView-based components which heights automatically and dynamically adapts to their page content heights, anytime the DOM changes.
Highlights
The width of the viewport will grow to the available horizontal space and won't need to be specified. You can override this behavior by setting explicit
width
as a parameter attribute of useAutoheight hook.The height of the viewport will dynamically adapts to the content height, which has been constrained by the viewport width as we have just mentioned! It means that anytime the content changes or the viewport width changes, such as in screen rotations, the viewport height will get updated.
Look at the screen and notice in the top console how viewport height closely follows content height updates.
This hook will rely on HandleHTMLDimensionsFeature to use the best API available in the browser and dynamically adapt viewport to content size. In order of preference, ResizeObserver, MutationObserver and finally, polling on a regular interval.
note
Basic Example
Invoke useAutoheight in a controlling component and pass returned props to a shell in order to benefit from autoheight behavior. As previously stated, it requires a minima injection of a HandleHTMLDimensionsFeature in the shell to fetch content dimensions:
- Typescript
- JavaScript
Caveats and their Workarounds
Mobile Virtual Viewport
In some circumstances, the mobile browser might use a virtual viewport much larger then the available width in the WebView, often around 980px for websites which have been built for desktop. For this autoheight component to be reliable, you must ensure that the content has a meta viewport element in the header.
solution
This can be enforced by setting responsive layout with ForceResponsiveViewportFeature.
However, the result might be ugly and overflow on the horizontal axis if the page is not responsive (optimized for mobile). Always make sure the content is optimized for mobile, read more about this here.
Cyclic Size Constraints โ
Because the viewport height now depends on content heigh, you must never have a body element height depending on viewport height, such as:
That is an evil cyclic dependency ready to cast an infinite loop! Wikipedia website has such styles. Watch the console on top of screen and notice how the shell is caught in an infinite loop shrinking the height inexorably.
solution
Body width and height can be forced to auto with ForceElementSizeFeature.
Robust Example
In this example, we use the two tips listed in above Caveats section to provide a much resilient implementation.
- Typescript
- JavaScript
Integration with ScrollView
More often than not, an autoheight feature is needed to embed the WebView along with content of unpredictable length, and a ScrollView works just fine. This section summarize best practices and tricks for a perfect integration.
Recommended ScrollView Props Values
Prop | Value | Rationale |
---|---|---|
pinchGestureEnabled | false | Enabling pinch (the default) will conflict with the pinch-to-zoom feature provided by ForceResponsiveViewportFeature maxScale option. When maxScale is above 1 , it will allow for pinch to zoom gestures up to the provided zoom level. |
horizontal | false | When the Web page is ill-designed (not-responsive), the content might overflows horizontally. We suggest to avoid nesting components providing scroll in the same direction, unless necessary. |
hashchange
Events
Handling However, scroll to hash on link press, for example:
will not work, because the underlying WebView will not have vertical scroll anymore.
solution
You can register a prop to listen to haschange events with HandleHashChangeFeature.
After that, you must implement the desired behavior, that is to scroll to the
desired DOM element when a hashchange
event is fired, while accounting for the space
occupied by components above the shell, inside the ScrollView. Below is a complete
example:
- Typescript
- JavaScript