JSFiddle - React, Tailwind, and code Playground
by Nicholas Berlette
HTML
<div id="app" class="!opacity-100">
<div class="controls">
<button class="btn">Randomize</button>
<button class="timer-btn">start timer</button>
</div>
<div class="box">
<p>
<span>Box</span>
</p>
</div>
</div>
<script>
window.windicssRuntimeOptions = {
timing: 'immediate',
// enabled preflight
preflight: true,
// scan the entire dom tree to infer the classnames on page loaded
extractInitial: true,
// generate mock classes for browser to do the auto-completeion
mockClasses: true,
// the windi config you are used to put in `windi.config.js`
config: {
darkMode: 'media',
safelist: ['btn-download', 'todo-list', 'hidden', 'pb-2', 'mb-2'],
shortcuts: {
'app-divider': 'border-dashed border-blue-700/30 dark:border-cyan-400/30',
'app-text': 'text-gray-900 dark:text-gray-50',
'app': 'w-full h-auto sm:rounded-xl px-10 pb-10 pt-14 mb-16 !leading-12 ring-1 ring-offset-1 ring-offset-gray-100 ring-white bg-white text-gray-900 dark:(bg-gray-800 text-gray-50 ring-offset-gray-800 ring-emerald-700/20) !opacity-100 shadow-lg hover:shadow-xl transition-shadow duration-500 ease-in',
'wrapper': 'max-w-2xl mx-auto mt-20',
'h1': 'text-3xl my-0 p-0 mb-6 lowercase flex flex-row justify-between place-items-center align-center !text-primary-500',
'title': 'text-4xl tracking-tighter font-thin',
'page': 'font-medium text-2xl app-text opacity-50 hover:opacity-80 transition-opacity duration-500 ease-in cursor-default relative top-1',
'link': 'text-[1.05em] app-text font-semibold',
'input-ring': 'ring-1 ring-offset-1 ring-gray-400/20 ring-offset-white dark:(ring-white/15 ring-offset-gray-800) focus:(!ring-1.5 outline-blue-400/40 dark:!outline-blue-400/30 outline-solid)',
'input-text': 'rounded mr-4 px-3 pt-[9px] pb-2 text-sm border-none bg-gray-200/10 dark:!bg-gray-900/10 text-black dark:!text-white input-ring shadow-sm hover:shadow transition-all duration-500 ease-in w-full...
CSS
@import "https://unpkg.com/@typehaus/[email protected]/400.css";
@import "https://unpkg.com/@typehaus/[email protected]/600.css";
#app {
max-width: 40vw;
margin: 40% auto;
text-align: center;
}
.box p {
border: 10px solid rgb(0, 0, 0);
background-color: #8dddff;
color: #123;
font-size: 2.5rem;
padding: 1rem 2rem;
border-radius: 1rem;
display: inline-block;
transition: all 500ms ease-out;
background-clip: padding-box;
text-shadow: 0 3px 0 #fff;
outline: 10px 0 #fff;
filter: saturation(0.5) contrast(0.5);
}
.box p span {
filter: saturation(150%);
transition: all 333ms ease-in;
}
.controls {
display: flex;
flex-direction: row;
gap: 1rem;
justify-items: space-evenly;
}
.controls button {
font-size: 1.2rem;
text-transform: lowercase;
letter-spacing: -0.02rem;
font-weight: 400;
line-height: 1.2rem;
font-family: 'Metropolis', sans-serif;
padding: 0.6rem 1.5rem 0.45rem;
border-radius: 9999px;
border: 1.5px solid #ddd;
box-shadow: inset 0px 1px 0 #fff;
background: linear-gradient(0deg, #e3e3e3, #f0f0f0);
cursor: pointer;
transition: background 500ms ease-in, color 400ms ease-in;
white-space: nowrap;
}
.controls button:hover {
background: #f0f0f0;
}
.timer-active {
color: #900;
border-color: #c44 !important;
font-weight: 600 !important;
background: linear-gradient(0deg, #fee, #fff0f0) !important;
}
JavaScript
const btn = document.querySelector('.btn');
const timerBtn = document.querySelector('.timer-btn');
const box = document.querySelector('.box');
const text = document.querySelector('.box p span');
const stylesheet = document.styleSheets[2];
let boxParaRule;
for (let i = 0; i < stylesheet.cssRules.length; i++) {
if (stylesheet.cssRules[i].selectorText === '.box p') {
boxParaRule = stylesheet.cssRules[i];
}
}
function randomize() {
function random(min, max) {
const num = Math.floor(Math.random() * (max - min)) + min;
return num;
}
function randomColor() {
return `rgb(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)})`;
}
function setRandomBorder() {
const borderStyles = ['single', 'solid', 'double', 'dotted', 'dashed', 'dotted', 'solid', 'grooved', 'doubled'];
// const borderStyle = borderStyles[random(0, borderStyles.length - 1)];
const borderStyle = 'solid';
const borderColor = randomColor();
text.style.setProperty('color', borderColor);
const newBorder = `${random(1, 20)}px ${borderStyle} ${borderColor}`;
boxParaRule.style.setProperty('border', newBorder);
}
function setRandomBorderRadius() {
const radii = [0, 2, 3, 4, 5, 6, 8, 10, 12, 15, 18, 20, 25, 35, 100, 200];
const newBorderRadius = random(0, 100) % 3 ? `${radii[random(0, radii.length - 1)]}px ${radii[random(0, radii.length - 1)]}px` : `${radii[random(0, radii.length -1)]}px`;
boxParaRule.style.setProperty('border-radius', newBorderRadius, "important");
}
function setRandomColor() {
const newBgColor = randomColor();
boxParaRule.style.setProperty('background-color', newBgColor);
}
function setRandomPadding() {
const pX = random(20, 50);
const pY = pX * random(0.5, 2.5);;
const newPadding = `${pX}px ${pY}px`;
boxParaRule.style.setProperty('padding', newPadding, "important");
}
setRandomPadding();
setRandomColor();
setRandomBorder();
...