Last active
November 6, 2020 16:19
-
-
Save grebenyuksv-preply/fb7e6b488b72fabeca347cedfd1d983d to your computer and use it in GitHub Desktop.
CLS Debug Info
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useCLS } from './useCLS'; | |
import styles from './styles.less'; | |
// the CLS indicator on the bottom right of the screen | |
export const CLSDebugInfo = () => { | |
const cls = useCLS(); | |
return <div className={styles.CLSDebugInfo}>{cls && cls.value.toFixed(5)}</div>; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.CLSDebugInfo { | |
visibility: hidden; | |
position: fixed; | |
bottom: 0; | |
right: 0; | |
z-index: 99; | |
background: white; | |
&:before { | |
content: 'CLS: '; | |
} | |
// the important part | |
// only show the indicator inside .hotjar-css-hover, which is inside the HotJar player | |
:global(.hotjar-css-hover) & { | |
visibility: visible; | |
} | |
} | |
.fade-away() { | |
0% { | |
opacity: 1; | |
} | |
50% { | |
opacity: 0; | |
} | |
} | |
// the important part | |
// only show the highlights inside .hotjar-css-hover, which is inside the HotJar player | |
.CLSElement(@animation) { | |
:global(.hotjar-css-hover) & { | |
position: relative; | |
&:before { | |
content: ''; | |
position: absolute; | |
left: 0%; | |
top: 0; | |
width: 100%; | |
height: 100%; | |
opacity: 0; | |
box-shadow: 0px 0px 0px 10px rgba(217, 156, 255, 1); | |
animation: @animation; | |
} | |
} | |
} | |
.CLSElement1 { | |
@keyframes fade-away-1 { | |
.fade-away(); | |
} | |
.CLSElement(fade-away-1 1s); | |
} | |
.CLSElement2 { | |
@keyframes fade-away-2 { | |
.fade-away(); | |
} | |
.CLSElement(fade-away-2 1s); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState, useEffect } from 'react'; | |
import { getCLS, ReportHandler, Metric } from 'web-vitals'; | |
import styles from './styles.less'; | |
// subscribe on CLS updates to the rest of the app | |
const getCLSCallbacks = new Set<ReportHandler>(); | |
let entryIdx = 0; | |
getCLS((metric: Metric) => { | |
getCLSCallbacks.forEach(cb => cb.call(null, metric)); | |
for (; entryIdx < metric.entries.length; entryIdx += 1) { | |
const entry = metric.entries[entryIdx] as LayoutShift; | |
if (entry.sources) { | |
for (const { node } of entry.sources) { | |
if (node instanceof HTMLElement) { | |
// highlight the node | |
// https://css-tricks.com/restart-css-animation/ | |
node.classList.add(styles.CLSElement1); | |
// classList.toggle isn't cross-browser yet | |
if (node.classList.contains(styles.CLSElement2)) { | |
node.classList.remove(styles.CLSElement2); | |
} else { | |
node.classList.add(styles.CLSElement2); | |
} | |
} | |
} | |
} | |
} | |
}, true); | |
// the hook which exposes the current CLS value to the indicator | |
export const useCLS = () => { | |
const [lastMetric, setLastMetric] = useState<Metric>(); | |
// web-vitals seems to be modifying the same object and passing it into callbacks! | |
const setLastMetricCopy = (metric: Metric) => { | |
setLastMetric({ ...metric }); | |
}; | |
useEffect(() => { | |
getCLSCallbacks.add(setLastMetricCopy); | |
return () => { | |
getCLSCallbacks.delete(setLastMetricCopy); | |
}; | |
}, []); | |
return lastMetric; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment