CSS、JSで中窓 半透明のレイヤーの中に透明の枠を追加したい

一部だけ目立たせる方法の一つに対象以外を半透明のレイヤーを乗せたい…けどそんなコトはできないっぽいので無理やり対応

作成日:2024-03-15, 更新日:2024-03-18

サンプル

中窓にしたいdivタグとそれを囲むdivタグをセット。必要最低限のクラスにしてみた

<div id="nakamado">中窓のように透明にしたい</div>
<div class="overlay" style="display:none;" id="overlay-top"></div>
<div class="overlay" style="display:none;" id="overlay-right"></div>
<div class="overlay" style="display:none;" id="overlay-bottom"></div>
<div class="overlay" style="display:none;" id="overlay-left"></div>
<style>
	.overlay {
		background: rgba(0, 0, 0, 0.5);
		position: fixed;
		z-index: 10;
	}
	#nakamado {
		position: absolute;
		z-index: 15;
		top: 50px;
		left: 50px;
		width: 200px;
		height: 100px;
	}
</style>
<script>
	class SpotlightAreaUtility {
		constructor(nakamadoId, overlayClass) {
			this.nakamadoId = nakamadoId;

			// ▼動的に中窓を作成するときゴニョゴニョする
			this.nakamadoElement = document.getElementById(nakamadoId);
			this.nakamadoElement.style.width = '150px';
			// ▲動的に中窓を作成するときゴニョゴニョする

			this.overlayElements = document.querySelectorAll('.' + overlayClass);
			this.updateOverlays();
			window.addEventListener('resize', () => this.updateOverlays());
		}

		updateOverlays() {
			this.nakamadoElement = document.getElementById(this.nakamadoId);
			const rect = this.nakamadoElement.getBoundingClientRect();
			for ( let overlay of this.overlayElements ) {
				switch ( overlay.id ) {
					case 'overlay-top':
						const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
						const viewPortBottom = scrollTop + window.innerHeight;
						const btm = scrollTop + viewPortBottom;
						if ( (btm <= rect.top) || (0 <= rect.top && rect.top <= btm) ) {
							overlay.style.top = '0px';
							overlay.style.left = '0px';
							overlay.style.right = '0px';
							overlay.style.height = `${rect.top}px`;
							overlay.style.display = '';
						}
						else {
							overlay.style.display = 'none';
						}
					break;

					case 'overlay-right':
						overlay.style.top = `${rect.top}px`;
						overlay.style.left = `${rect.right}px`;
						overlay.style.bottom = `${window.innerHeight - rect.bottom}px`;
						overlay.style.width = `${window.innerWidth - rect.right}px`;
						overlay.style.display = '';
					break;

					case 'overlay-bottom':
						overlay.style.top = `${rect.bottom}px`;
						overlay.style.left = '0px';
						overlay.style.right = '0px';
						overlay.style.bottom = '0px';
						overlay.style.display = '';
					break;

					case 'overlay-left':
						overlay.style.top = `${rect.top}px`;
						overlay.style.bottom = `${window.innerHeight - rect.bottom}px`;
						overlay.style.right = `${window.innerWidth - rect.left}px`;
						overlay.style.width = `${rect.left}px`;
						overlay.style.display = '';
					break;
				}
			}
		}
	}

	document.addEventListener('DOMContentLoaded', () => {
		const SpotlightArea_Util = new SpotlightAreaUtility('nakamado', 'overlay');
	});
</script>