Last active
August 6, 2022 22:59
-
-
Save nolanlawson/6a4e514d16331594bef2d4b9ee91f150 to your computer and use it in GitHub Desktop.
Layout thrashing demo
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
<!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