I'm using material-ui@v5
, ie. the alpha branch.
Currently, I have a custom Timeline
component which does this:
const CustomTimeline = () => {
const mdDown = useMediaQuery(theme => theme.breakpoints.down("md"));
return (
<Timeline position={mdDown ? "right" : "alternate"}>
{/* some children */}
</Timeline>
);
};
It works mostly as intended, but mobile users may experience layout shift because useMediaQuery
is implemented using JS and is client-side only. I would like to seek a CSS implementation equivalence to the above code to work with SSR.
I have thought of the following:
const CustomTimeline = () => {
return (
<Fragment>
<Timeline sx={{ display: { xs: "block", md: "none" } }} position="right">
{/* some children */}
</Timeline>
<Timeline sx={{ display: { xs: "none", md: "block" } }} position="alternate">
{/* some children */}
</Timeline>
</Fragment>
);
};
This will work since the sx
prop is converted into emotion
styling and embedded in the HTML file, but this will increase the DOM size. Is there a better way to achieve that?
Responsive CSS in React has a glaring weakness: it doesn't allow you to responsively change the values of props. Instead of writing CSS wrapped in media queries, responsive props is a method where you specify the value of the prop for predefined breakpoints and logic exists somewhere that chooses the value associated with the active breakpoint.
The guide will start with a very simple label component that will have a prop called text and display it inside a span, then extend this component to highlight the text when the prop is changed by the parent component.
This service works in conjunction with grids and other responsive helper classes (e.g. display ). The breakpoint service is a programmatic way of accessing viewport information within components. It exposes a number of properties on the $vuetify object that can be used to control aspects of your application based upon the viewport size.
Instead of writing CSS wrapped in media queries, responsive props is a method where you specify the value of the prop for predefined breakpoints and logic exists somewhere that chooses the value associated with the active breakpoint. Why would you want to do that? Let's say you have different button sizes: large, medium, small.
I have experienced the same problem before and I was using Next.js to handle SSR. But it does not matter.
Please first install this package and import it on your root, like App.js
import mediaQuery from 'css-mediaquery';
Then, create this function to pass ThemeProvider of material-ui
const ssrMatchMedia = useCallback(
(query) => {
const deviceType = parser(userAgent).device.type || 'desktop';
return {
matches: mediaQuery.match(query, {
width: deviceType === 'mobile' ? '0px' : '1024px'
})
};
},
[userAgent]
);
You should pass the userAgent!
Then pass ssrMatchMedia to MuiUseMediaQuery
<ThemeProvider
theme={{
...theme,
props: {
...theme.props,
MuiUseMediaQuery: {
ssrMatchMedia
}
}
}}>
This should work. I am not using material-UI v5. Using the old one. MuiUseMediaQuery name might be changed but this approach avoid shifting for me. Let me know if it works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With