Custom HTMLElement #
이번 포스팅에선 Custom HTMLElement의 스타일을 변경하는 방법과 만든 Custom HTMLElement를 사용한 예제를 간략하게 포스팅 하겠습니다.
CSS 적용하기 #
const styleText = `
div {
border : 1px solid;
margin: 15px;
width : 200px;
height: 240px;
}`;
class CustomTag extends HTMLElement {
constructor() {
... 중략 ...
// 스타일 적용방법 1
const styleSheet = new CSSStyleSheet();
styleSheet.replaceSync(styleText);
shadowRoot.adoptedStyleSheets= [styleSheet];
// 스타일 적용방법 2
shadowRoot.innerHTML = `
<style>
div > p {
font-weight : bold;
}
</style>`
위와 같은 방법으로 Custom Element에 CSS를 적용할 수 있습니다.
Custom HTMLElement 예제 #
Custom HTMLElement 는 개발자가 HTMLElement를 상속받아 필요한 기능을 정의하여, 재사용할 수 있는 Component화를 가능하게 합니다.
Component 만들기 1 #
Card Component를 예를 들어서 만들어 보겠습니다.
const styleText = `
div {
border : 1px solid;
margin: 15px;
width : 200px;
height: 240px;
}
.default-card-content {
width: 200px;
height: 185px;
}
`;
class CustomTag extends HTMLElement {
constructor() {
super();
// Create a shadow root.
const shadowRoot = this.attachShadow({ mode: "open" });
// 예제를 위해 태그 변경
const div = document.createElement("div");
const paragraph = document.createElement("p");
const cardTitle = document.createElement("slot");
cardTitle.name = "card-title";
paragraph.appendChild(cardTitle);
div.appendChild(paragraph);
const cardContent = document.createElement("slot");
cardContent.name = "card-content";
cardContent.classList.add("fit");
// 이미지를 지정하지 않으면 기본 이미지가 표시됩니다.
const cardContentDefault = document.createElement('img');
cardContentDefault.src = "./noimage.png";
cardContentDefault.alt = "no image";
cardContentDefault.classList.add("default-card-content");
cardContent.appendChild(cardContentDefault);
div.appendChild(cardContent);
// 스타일 변경 1
const styleSheet = new CSSStyleSheet();
styleSheet.replaceSync(styleText);
shadowRoot.adoptedStyleSheets= [styleSheet];
// 스타일 변경 2
shadowRoot.innerHTML = `
<style>
div > p {
font-weight : bold;
}
</style>`
shadowRoot.appendChild(div);
}
}
customElements.define("my-custom-tag", CustomTag);
document객체로 html 요소들을 생성하여 카드 component의 모양을 만들었습니다.
Component 만들기 2 #
위의 코드는 가독성이 떨어지는 것 같습니다. 친숙하고 보기 좋은 HTML 코드로 수정하겠습니다.
const styleText = `
div {
border : 1px solid;
margin: 15px;
width : 200px;
height: 240px;
}
.default-card-content {
width: 200px;
height: 185px;
}
`;
const template = `
<div>
<p>
<slot name="card-title"></slot>
</p>
<slot name="card-content" class="fit">
<img alt="no image" src="./noimage.png" class="default-card-content"/>
</slot>
</div>
`;
class CustomTag extends HTMLElement {
constructor() {
super();
// Create a shadow root.
const shadowRoot = this.attachShadow({ mode: "open" });
let tmpl = document.createElement("template");
tmpl.innerHTML = template;
// 스타일 변경 1
const styleSheet = new CSSStyleSheet();
styleSheet.replaceSync(styleText);
shadowRoot.adoptedStyleSheets= [styleSheet];
// 스타일 변경 2
shadowRoot.innerHTML = `
<style>
div > p {
font-weight : bold;
}
</style>`
shadowRoot.appendChild(tmpl.content.cloneNode(true));
}
}
customElements.define("my-custom-tag", CustomTag);
HTML로 Template 를 만들어서 사용하니 보기 한결 좋아졌습니다. 다른 방법으로는 html에 template태그로 template를 만들고 custom element가 생성될 때, template를 가져오는 방법도 있으나 이번 포스팅에선 제외하겠습니다.
Component 사용해보기 #
이제 만든 Custom HTMLElement를 사용해 봅시다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width" />
<title>Custom Tag</title>
<link rel="stylesheet" type="text/css" href="./index.css" />
<script type="module" src="./custom-tag.js"></script>
</head>
<body>
<div class="wrapper">
<my-custom-tag>
<p slot="card-title">카드 1</p>
</my-custom-tag>
<my-custom-tag>
<p slot="card-title">카드 2</p>
<img class="card-content" alt="stg" slot="card-content" src="./workflow.png"/>
</my-custom-tag>
<my-custom-tag>
<p slot="card-title">카드 3</p>
<img class="card-content" alt="stg" slot="card-content" src="./workflow.png"/>
</my-custom-tag>
<my-custom-tag>
<p slot="card-title">카드 4</p>
<img class="card-content" alt="stg" slot="card-content" src="./strategy.png"/>
</my-custom-tag>
</div>
</body>
</html>
재사용을 하기 위해 만들었기에 최대한 많이 사용해봤습니다.
마치며.. #
여기까지 간단하게 Component를 만들어 봤습니다. 흥미가 생기셨다면 필요한 여러가지 이벤트를 등록하여 Component의 기능을 더욱 완벽하게 해 보시길 바랍니다. 저도 더 공부하여 유익할 정보를 공유하도록 노력하겠습니다.