I am using NextJS with Mantine to develop a site. I have used createStyles to add stylings. Also I try to use as many mantine components as possible.
When I deployed the site on vercel, I found out all site performance parameters were great except CLS, which was terrible; so terrible that you can feel the content shift while starting the site for the first time.
Just for an example, the code for Header is given below:
import { useState } from 'react';
import {
createStyles, Container, Anchor, Group, ActionIcon, useMantineColorScheme
} from '@mantine/core';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import Sun from '@/public/svg/sun.svg';
import MoonStars from '@/public/svg/moonStars.svg';
const useStyles = createStyles((theme) => ({
inner: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
},
burger: {
[theme.fn.largerThan('sm')]: {
display: 'none',
}
},
links: {
fontWeight: 700,
textTransform: 'uppercase',
textDecoration: 'none',
fontSize: theme.fontSizes.md,
},
mainLink: {
color: theme.colorScheme === 'dark' ? theme.colors.dark[1] : theme.colors.gray[6],
borderBottom: `2px solid transparent`,
transition: 'border-color 100ms ease, color 100ms ease',
'&:hover': {
color: theme.colorScheme === 'dark' ? theme.white : theme.black,
textDecoration: 'none',
},
},
mainLinkActive: {
color: theme.colorScheme === 'dark' ? theme.white : theme.black,
borderBottomColor: theme.colors[theme.primaryColor][theme.colorScheme === 'dark' ? 5 : 6],
},
sideText: {
color: theme.colorScheme === 'dark' ? theme.white : theme.black,
}
}));
export default function Component() {
const { colorScheme, toggleColorScheme } = useMantineColorScheme();
const { classes, cx } = useStyles();
let pathname = usePathname();
const [active, setActive] = useState(() => {
if (pathname.split('/')[1] === '') return 0;
if (pathname.split('/')[1] === 'blog') return 1;
});
let mainLinks = [
{ "link": "/", "label": "About" },
{ "link": "/blog", "label": "Blog" },
]
const mainItems = mainLinks.map((item, index) => (
<Anchor component={Link} href={item.link} key={item.label} py='xl' px='md'
className={cx(classes.mainLink, { [classes.mainLinkActive]: index === active }, classes.links)}
onClick={() => setActive(index)} >
{item.label}
</Anchor>
));
const changeColorScheme = () => {
toggleColorScheme();
localStorage.setItem('color-scheme', colorScheme === 'dark' ? 'light' : 'dark');
}
return (
<Container pos='relative' mb='2rem'>
<Container pos='sticky' className={classes.inner}>
<div className={classes.links}>
<Group spacing={0} >
{mainItems}
</Group>
</div>
<Group position="center" my="xl">
<ActionIcon
onClick={() => changeColorScheme()}
size="lg"
sx={(theme) => ({
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
color: theme.colorScheme === 'dark' ? theme.colors.yellow[4] : theme.colors.blue[6],
})}>
{colorScheme === 'dark' ? <Sun /> : <MoonStars />}
</ActionIcon>
</Group>
{/* <Burger opened={opened} onClick={toggle} className={classes.burger} size="sm" /> */}
</Container>
</Container>
);
}
You can find the website deployed here if you want to try it yourself
One major issue I can think of is that maybe mantine is converting all components into only JS and shipping too much js is making it dynamic and hence all the shifting
If using mantine components is causing the issue, I am ready to shift to native HTML components, but I need to be sure if Mantine's the one causing the issue.
Please help figure out what exactly is causing the high content shift leading to high CLS and how to improve/prevent content shift.