JSFiddle - React, Tailwind, and code Playground

by superhead

HTML

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Speed of light</title>
    <style>
        body {
            font-family: sans-serif;
            max-width: 800px;
            margin: 0 auto;
            background-color: skyblue;
        }

        p{
            box-shadow:10px 10px 5px 0px rgba(0,0,0,0.75);
            padding: 10px;
            border-radius: 5px;
            background-color: white;
        }

        #titleOverlay{
            position: fixed;
            margin: 0;
            /*display: none;*/
            width: 30%;
            height: 15%;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: rgba(0,0,0,0.5);
            z-index: 2;
            cursor: pointer;
        }

        #titleText{
            position: absolute;
            top: 20%;
            left: 50%;
            color: white;
            transform: translate(-50%,-50%);
            -ms-transform: translate(-50%,-50%);
        }

    </style>
</head>
<body>
<h1 id="speed-of-light">Speed of light</h1>
<p>From Wikipedia, the free encyclopedia</p>
<div id="container">
<p>
    The <strong>speed of light</strong> in <a href="https://wikipedia.org/wiki/Vacuum" title="Vacuum">vacuum</a>, commonly denoted <strong>c</strong>, is a universal
    <a href="https://wikipedia.org/wiki/Physical_constant" title="Physical constant">physical constant</a> important in many areas of <a href="https://wikipedia.org/wiki/Physics" title="Physics">physics</a>. Its exact value is defined as
    299792458 metres per second (approximately 300000 km/s, or 186000 mi/s).<a href="#cite_note-imperial-4">[Note 3]</a> It is exact because, by international agreement, a
    <a href="https://wikipedia.org/wiki/Metre#Speed_of_light_definition" title="Metre">metre</a> is defined as the length of the path travelled by <a...

JavaScript

// PARAGRAPHS
//Threshold props for Paragraphs
const propObj = [
	{maxThres: 1.0, minThres: 0.9, color:'violet'},
	{maxThres: 0.9, minThres: 0.8, color:'indigo'},
	{maxThres: 0.8, minThres: 0.7, color:'blue'},
	{maxThres: 0.7, minThres: 0.6, color:'green'},
	{maxThres: 0.6, minThres: 0.5, color:'yellow'},
	{maxThres: 0.5, minThres: 0.4, color:'orange'},
	{maxThres: 0.4, minThres: 0.3, color:'red'},
	{maxThres: 0.3, minThres: 0.2, color:'teal'},
	{maxThres: 0.2, minThres: 0.1, color:'purple'},
	{maxThres: 0.1, minThres: 0.0, color:'grey'}
]

const container = document.getElementsByTagName('body')[0]

// PARAGRAPHS => OBSERVER CONFIG
let pOptions = {
	root: null,
	threshold: [...propObj.map(el=>el.maxThres)]
};

// PARAGRAPHS => utils
const getColor = iR => propObj.filter(elem => !(elem.maxThres > iR > elem.minThres))[0].color;

// PARAGRAPHS => OBSERVER
let pObserver = new IntersectionObserver((entries, observer) => {
	entries.forEach(entry=>{
		if(entry.intersectionRatio !== 1 && entry.isIntersecting ){
			entry.target.style.border = `10px solid ${getColor(entry.intersectionRatio)}`
		}else{
			entry.target.style.border = '';
		}
	})
}, pOptions);

// PARAGRAPHS => OBSERVER ITERATION
const pgps = document.querySelectorAll("p");
pgps.forEach(pgp => {
	pObserver.observe(pgp);
});


// TITLES
// TITLES => OBSERVER CONFIG
let titleOptions = {
	root: null,
	threshold: 1
};

// TITLES => CHILD ELEMENTS
const titleOverlay = document.createElement('div');
titleOverlay.id = 'titleOverlay';

const titleText = document.createElement('h2');
titleText.id = 'titleText';

// TITLES => OBSERVER
let titleObserver = new IntersectionObserver((entries, observer) => {
	entries.forEach(entry=>{
		if(entry.intersectionRatio===1){
			titleText.textContent = entry.target.textContent;
		}else{
			titleText.textContent ='';
		}
	})
}, titleOptions);

// TITLES => RENDERING CHILD NODES
titleOverlay.appendChild(titleText);
container.appendChild(titleOverlay);

// TITLES => OBSERVER...