Skip to content

Instantly share code, notes, and snippets.

@nolanlawson
Last active August 6, 2022 22:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nolanlawson/6a4e514d16331594bef2d4b9ee91f150 to your computer and use it in GitHub Desktop.
Save nolanlawson/6a4e514d16331594bef2d4b9ee91f150 to your computer and use it in GitHub Desktop.
Layout thrashing demo
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css"
integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap-theme.min.css"
integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<style id="theStyle">
/* the goal of these selectors is to be stupidly unperformant */
body:nth-child(2):not(.unused) div:nth-child(2) *[even="true"]:nth-child(even) + *[odd="true"]:nth-child(odd) {
font-size: 1.2em;
}
body:nth-child(2):not(.unused) div:nth-child(2) * :nth-child(even) {
background: aqua;
}
body:nth-child(2):not(.unused) div:nth-child(2) * :nth-child(odd) {
background: chocolate;
}
body:nth-child(2):not(.unused) div:nth-child(2) * :nth-child(even) + :nth-child(odd) {
font-weight: bold;
}
body:nth-child(2):not(.unused) div:nth-child(2) * :nth-child(odd) + :nth-child(even) {
font-size: 1.1em;
}
body:nth-child(2):not(.unused) div:nth-child(2) * [even="true"]:nth-child(even) + [odd="true"]:nth-child(odd) {
font-weight: bold;
}
body:nth-child(2):not(.unused) div:nth-child(2) *:nth-child(even) {
height: 40px;
overflow: hidden;
}
body:nth-child(2):not(.unused) div:nth-child(2) *:nth-child(odd) {
height: 30px;
overflow: hidden;
}
</style>
</head>
<body>
<template id="theHtml">
<div>
<div class="row align-items-start" even="false">
<div class="col" even="false">
One of three columns
</div>
<div class="col" even="true">
One of three columns
</div>
<div class="col" even="false">
One of three columns
</div>
</div>
<div class="row align-items-center" even="true">
<div class="col" even="false">
One of three columns
</div>
<div class="col" even="true">
One of three columns
</div>
<div class="col" even="false">
One of three columns
</div>
</div>
<div class="row align-items-end" even="false">
<div class="col" even="false">
One of three columns
</div>
<div class="col" even="true">
One of three columns
</div>
<div class="col" even="false">
One of three columns
</div>
</div>
</div>
</template>
<div>
<button type="button" id="doThrash" style="all: revert">Thrash</button>
<button type="button" id="doNoThrash" style="all: revert">No thrash</button>
<pre id="display"></pre>
</div>
<div id="container">
</div>
<script type="module">
for (let i = 0; i < 100; i++) {
container.appendChild(theHtml.content.cloneNode(true))
}
for (let i = 0; i < 100; i++) {
const clone = theStyle.cloneNode(true)
clone.id = ''
document.head.appendChild(clone)
}
const write = (el, width) => {
el.style.width = width + 'px'
el.setAttribute('even', (Math.random() < 0.5).toString())
const div = document.createElement('div')
div.setAttribute('even', (Math.random() < 0.5).toString())
document.body.appendChild(div)
}
const read = (el) => {
return el.parentElement.offsetWidth
}
const elements = [...document.querySelectorAll('.col')]
const doIt = (thrash) => {
const channel = new MessageChannel();
channel.port1.onmessage = () => {
performance.mark('end')
performance.measure('total', 'start', 'end')
display.innerHTML += performance.getEntriesByType('measure').slice(-1)[0].duration + '\n'
}
requestAnimationFrame(() => {
performance.mark('start')
if (thrash) {
for (const el of elements) {
const width = read(el)
write(el, width)
}
} else {
const widths = elements.map(el => read(el))
elements.forEach((el, i) => {
write(el, widths[i])
})
}
channel.port2.postMessage(undefined)
})
}
doThrash.addEventListener('click', () => doIt(true))
doNoThrash.addEventListener('click', () => doIt(false))
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment