custom element と shadow DOM で作るお知らせカテゴリマーク

Shadow DOM 使用例

Shadow DOM 使用例

custom element と shadow DOM で作るお知らせカテゴリマーク

カスタムエレメントにシャドーDOMを組み込んだマークやボタンの作成例。
お知らせリストのカテゴリ表示など、小さなマークをJavaScript内に封じ込め。 Shadow DOM なのでスタイルを封じ込みできる。

使用結果

informCategoryOther
informCategoryNews
informCategoryProduct
informCategoryExhibition
informCategoryAbout
informCategoryRecruit
使用方法
[HTML]

<ce-inform-category>informCategoryOther</ce-inform-category>
<ce-inform-category>informCategoryNews</ce-inform-category>

<script defer src="./js/ce_inform_category.js"></script>
		
現時点のコードは以下の通り:
/**
 * お知らせのカテゴリー表示
 *
 * @author ao-system, Inc.
 * @date 2022-03-18
 * @date 2024-01-20
 *
 * e.g.
 * <ce-inform-category>informCategoryOther</ce-inform-category>
 * <ce-inform-category>informCategoryNews</ce-inform-category>
 * <script defer src="ce_inform_catrgory.js"></script>
 *
 */

(() => {
	'use strict';
	const categoryMark = new class {
		#constProperties = [
			{	prop: 'categories',
				value: [
					{name:'informCategoryOther',		text:'その他',		color:'#666'},
					{name:'informCategoryNews',			text:'お知らせ',	color:'#111'},
					{name:'informCategoryProduct',		text:'製品',		color:'#a0a'},
					{name:'informCategoryExhibition',	text:'展示会',		color:'#0a0'},
					{name:'informCategoryAbout',		text:'会社情報',	color:'#a00'},
					{name:'informCategoryRecruit',		text:'採用',		color:'#00a'},
				],
			},
			{	prop: 'style',
				value: `
					:host > div {
						padding: 4px 5px;
						font-size: 14px;
						line-height: 1;
						width: 5em;
						min-width: 5em;
						box-sizing: border-box;
						background-color: #fff;
						border: solid 1px;
						white-space: nowrap;
						user-select: none;
						overflow: hidden;
						display: flex;
						justify-content: space-around;
					}
				`,
			},
			{	prop: 'spanSplit',
				value: text => '<span>' + text.split('').join('</span><span>') + '</span>',
			},
		];
		constructor() {
			this.#constProperties.forEach((obj) => Object.defineProperty(this, obj.prop, {value:obj.value, writable:false}));
		}
		render(elementRef) {
			//<style>
			const styleElm = document.createElement('style');
			styleElm.textContent = this.style;
			//<div>
			const categoryIndex = this.categories.findIndex(x => x.name === elementRef.innerHTML);
			const divElm = document.createElement('div');
			divElm.innerHTML = this.spanSplit(this.categories[categoryIndex].text);
			divElm.style.borderColor = this.categories[categoryIndex].color;
			divElm.style.color = this.categories[categoryIndex].color;
			//shadow
			const shadowClosed = elementRef.attachShadow({mode:'closed'});
			shadowClosed.appendChild(styleElm);
			shadowClosed.appendChild(divElm);
		}
	};
	//
	customElements.define('ce-inform-category',
		class extends HTMLElement {
			constructor() {
				super();
				categoryMark.render(this);
			}
		}
	);
})();
適用のイメージ:

展開前↓:

<ce-inform-category>informCategoryOther</ce-inform-category>

展開後のイメージ↓:
(ブラウザの開発ツールで見るとこんな具合に表示されます)

<ce-inform-category>
	#shadow-root (closed)
		<style>
			:host > div {
				padding: 4px 5px;
				font-size: 14px;
				line-height: 1;
				width: 5em;
				min-width: 5em;
				box-sizing: border-box;
				background-color: #fff;
				border: solid 1px;
				white-space: nowrap;
				user-select: none;
				overflow: hidden;
				display: flex;
				justify-content: space-around;
			}
		</style>
		<div style="border-color: rgb(102, 102, 102); color: rgb(102, 102, 102);">
			<span>そ</span>
			<span>の</span>
			<span>他</span>
		</div>
</ce-inform-category>
		
資料
custom element:
https://developer.mozilla.org/ja/docs/Web/API/Web_components/Using_custom_elements
shadow DOM:
https://developer.mozilla.org/ja/docs/Web/API/Web_components/Using_shadow_DOM
2024年1月初版
このサイトについてのお問い合わせはエーオーシステムまでお願いいたします。
ご使用上の過失の有無を問わず、本プログラムの運用において発生した損害に対するいかなる請求があったとしても、その責任を負うものではありません。