JSFiddle - React, Tailwind, and code Playground

by shin1974

HTML

<!-- 1. Working area -->
<div id="working_area">
	<!-- 1. (1) Sandbox + (2) Pseudo-elements -->
	<div id="sandbox"></div>
  
	<div>
		<!-- 1. (3) Annotation -->
		<div id="annotation">Please click inside the sandbox or the buttons.</div>
	
		<!-- 1. (4) Results -->
		<fieldset id="results">
			<legend>Results</legend>
			<div><span>Cursor: </span><span id="cursor_position"></span></div>
			<div><span>Clicked: </span><span id="clicked_point"></span></div>
			<div id="message"></div>
		</fieldset>
	</div>
</div>
  
<!-- 2. Info area -->
<fieldset id="info_area">
	<legend>Info</legend>
	<div class="title">Actual coordinates and size of pseudo-elements</div>

	<div id="items">
		<!-- 2. (1) Info of :before pseudo-element -->
		<div class="item">
			<div>:before</div>
			<div id="bp_info"></div>
		</div>
	
		<!-- 2. (2) Info of :after pseudo-element -->
		<div class="item">
			<div>:after</div>
			<div id="ap_info"></div>
		</div>
	</div>
</fieldset>

CSS

* {
	box-sizing: border-box;
}

body {
	margin: 0;
	font-size: 14px;
}

/**
 * 1. Working area
 */
#working_area {
	display: flex;
}

/**
 * 1. (1) Sandbox
 */
#sandbox {
	position: relative;
	min-width: 100px;
  max-width: 100px;
	min-height: 100px;
  max-height: 100px;
	border-bottom: 1px dashed #888;
	border-right: 1px dashed #888;
	background: #ffa;
}

/**
 * 1. (2) Pseudo-elements
 */
#sandbox:before,
#sandbox:after {
	position: absolute;
	width: 60px;
	height: 25px;

	display: flex;
	justify-content: center;
	align-items: center;

	border: 2px solid #aaa;
	border-radius: 4px;
	background: #ddd;
	cursor: pointer;
}

#sandbox:before {
	content: ":before";
	top: 10px;
	left: 10px;
}
#sandbox:after {
	content: ":after";
	bottom: 10px;
	right: 10px;
}

/**
 * 1. (3) Annotation
 */
#annotation {
	padding-top: 5px;
	text-align: center;
	font-weight: bold;
	text-decoration: underline;
}

/**
 * 1. (4) Results
 */
#results {
	width: 400px;
	height: 100px;
	margin: 5px 10px;
}

/**
 * 2. Info area
 */
#info_area {
	margin: 0 10px;
	width: 500px;
}

.title {
	text-align: center;
	font-weight: bold;
	text-decoration: underline;
	padding-bottom: 10px;
}

#items {
	display: flex;
	gap: 10px;
}

.item {
	width: 230px;
	border: 1px solid #aaa;
	padding: 5px;
}

/**
 * 2. (1) Info of :before pseudo-element
 *    (2) Info of :after pseudo-element
 */
#bp_info,
#ap_info {
	padding-left: 15px;
}

JavaScript

$(() => {
	const $sandbox = $('#sandbox');
	const sandbox = $sandbox[0];

	/**
	 * Adds mouse move event listener.
	 */
	$sandbox.mousemove((e) => {
		$('#cursor_position').text('(x: ' + e.pageX + ', y: ' + e.pageY + ')');
	});

	/**
	 * Adds click event listener.
	 */
	$sandbox.click((e) => {
		// shows the coordinates of clicked point
		$('#clicked_point').text('(x: ' + e.pageX + ', y: ' + e.pageY + ')');

		// mouse cursor position
		const mousePoint = { x: e.pageX, y: e.pageY };

		if (isMouseOnPseudoElement(mousePoint, e.target, 'before')) {
			$('#message').text('[:before] pseudo-element was clicked!!!').css('color', 'blue');
		} else if (isMouseOnPseudoElement(mousePoint, e.target, 'after')) {
			$('#message').text('[:after] pseudo-element was clicked!!!').css('color', 'blue');
		} else {
			$('#message').text('An area outside the pseudo-element was clicked...').css('color', 'red');
		}
	});

	/**
	 * Shows the actual coordinates and size of pseudo-elements.
	 */
	(() => {
		const bpRect = getPseudoElementRect(sandbox, 'before');
		const apRect = getPseudoElementRect(sandbox, 'after');

		const $bp_root = $('#bp_info');
		$('<div>').text(`top left: (x: ${ bpRect.left}, y: ${bpRect.top})`).appendTo($bp_root);
		$('<div>').text(`bottom right: (x: ${bpRect.right}, y: ${bpRect.bottom})`).appendTo($bp_root);
		$('<div>').text(`width: ${bpRect.right - bpRect.left}, height: ${bpRect.bottom - bpRect.top}`).appendTo($bp_root);

		const $ap_root = $('#ap_info');
		$('<div>').text(`top left: (x: ${ apRect.left}, y: ${apRect.top})`).appendTo($ap_root);
		$('<div>').text(`bottom right: (x: ${apRect.right}, y: ${apRect.bottom})`).appendTo($ap_root);
		$('<div>').text(`width: ${apRect.right - apRect.left}, height: ${apRect.bottom - apRect.top}`).appendTo($ap_root);
	})();
});

	/**
	 * Gets the rectangle info of the pseudo-element.
	 *
	 * @param {DOMElement} element: root element
	 * @param {String} pseudoType: "before" or "after"
	 * @returns {JSON}: rectangle info of...