개발일지
LWC Lightning-Input CSS 수정시 적용이 안될 때 Dom Control하기 본문
LWC의 lightning-input 같은 기본 Lightning Base Components는 Shadow DOM을 사용하기 때문에, 일반적인 CSS로 내부 스타일을 변경할 수 없습니다.
그래서 원래 코드에서 컴포넌트 외부에 style을 선언하고, document.body.appendChild()로 스타일을 추가한 이유는
✅ Shadow DOM이 렌더링되기 전에 스타일을 먼저 삽입하여 강제 적용하기 위해서
하지만 이 방법은 전역 스타일을 수정하는 방식이기 때문에 다른 LWC 컴포넌트에도 영향을 미칠 수 있는 위험이 있습니다.
아래는 실제 개발에서 적용했던 코드입니다.
import { LightningElement, api, wire, track } from 'lwc';
import { getRecord, getFieldValue } from "lightning/uiRecordApi";
export default class test extends LightningElement {
/* 필요한 스타일 객체 선언 */
customStyle = {
id: 'test_input',
style: `
.slds-scope lightning-input .slds-input[disabled], .slds-scope lightning-input .slds-input.slds-is-disabled {
background-color: #FFF;
border-color: rgb(174, 174, 174);
}
`
}
/* 렌더링 할 때 넣어주기 */
connectedCallback() {
console.log('init');
style.set(this.customStyle);
}
/* 렌더링 후 삭제 */
disconnectedCallback() {
style.remove(this.customStyle);
}
}
/* 컴포넌트 밖에 선언 */
const style = {
set: (customStyle) => {
let styleElement = document.createElement("style");
styleElement.setAttribute("id", customStyle.id);
styleElement.innerHTML = customStyle.style;
document.body.appendChild(styleElement);
},
remove: (customStyle) => {
const target = document.querySelector("style#" + customStyle.id);
if(target) target.remove();
}
}
하지만 전역으로 적용 될 위험성이 있어 추천하지 않습니다..
✅ 더 안전한 방법 (전역 스타일을 유지하면서 특정 컴포넌트만 적용)
Lightning Web Components에서 Shadow DOM 내부의 스타일을 수정하는 가장 안정적인 방법은 ::part() 또는 :host()를 사용하는 것입니다.
하지만 Lightning Base Components (lightning-input, lightning-button 등)는 ::part() 지원이 제한적이므로, 전역 스타일을 직접 적용하는 방법을 사용해야 합니다.
🔹 💡 해결 방법 1: document.head에 style 추가 (전역 스타일)
이 방법은 원래 코드와 비슷하지만 스타일을 document.head에 추가하여 관리합니다.
이렇게 하면 전역 스타일을 추가하되, 특정 조건에서만 적용 가능하게 만들 수 있습니다.
import { LightningElement } from 'lwc';
export default class Test extends LightningElement {
customStyle = {
id: 'test_input_style',
style: `
lightning-input .slds-input[disabled],
lightning-input .slds-input.slds-is-disabled {
background-color: #FFF !important;
border-color: rgb(174, 174, 174) !important;
}
`
};
connectedCallback() {
console.log('✅ 스타일 추가');
styleManager.set(this.customStyle);
}
disconnectedCallback() {
console.log('✅ 스타일 삭제');
styleManager.remove(this.customStyle);
}
}
/* 전역 스타일 관리 객체 */
const styleManager = {
set: (customStyle) => {
if (!document.head.querySelector(`#${customStyle.id}`)) {
let styleElement = document.createElement("style");
styleElement.setAttribute("id", customStyle.id);
styleElement.innerHTML = customStyle.style;
document.head.appendChild(styleElement);
}
},
remove: (customStyle) => {
const target = document.head.querySelector(`#${customStyle.id}`);
if (target) target.remove();
}
};
🔹 🛠 이 방법의 장점
✅ document.head에 스타일을 추가하여 전역 적용 가능
✅ 중복 스타일 삽입 방지 (if (!document.head.querySelector()) 체크)
✅ LWC가 제거되면 자동으로 스타일 삭제 → 다른 컴포넌트에 영향을 주지 않음
✅ !important를 사용하여 강제 적용
🔹 💡 해결 방법 2: SLDS 오버라이드 (CSS 변수 활용)
Salesforce에서는 **SLDS (Salesforce Lightning Design System)**에서 제공하는 CSS 변수를 활용하는 것도 가능합니다.
test.css
:host {
--slds-c-input-color-background: #FFF;
--slds-c-input-color-border: rgb(174, 174, 174);
}
lightning-input {
background-color: var(--slds-c-input-color-background) !important;
border-color: var(--slds-c-input-color-border) !important;
}
test.js
import { LightningElement } from 'lwc';
export default class Test extends LightningElement {}
test.html
<template>
<lightning-input label="Disabled Input" disabled></lightning-input>
</template>
🔹 🛠 이 방법의 장점
✅ SLDS CSS 변수를 활용하여 유지보수성 증가
✅ Shadow DOM 내부에서도 적용 가능
✅ 스타일이 전역 적용되지 않고 LWC 내부에서만 적용됨
🚀 결론
방법적용 범위 장점/단점
document.body.appendChild(style) | 전역 | 강제 적용 가능 | 다른 컴포넌트에 영향 |
document.head.appendChild(style) (방법 1) | 전역 | 안전한 전역 적용, 중복 방지 | 전역 스타일이므로 여러 컴포넌트에 영향 가능 |
SLDS 변수 활용 (방법 2) | LWC 내부 | 유지보수 용이, Shadow DOM 안전 | SLDS 변수에 따라 적용 가능 여부 달라짐 |
💡 전역 스타일을 유지하면서 안전하게 적용하려면 document.head.appendChild(style)을 추천!
💡 가능하면 SLDS 변수를 활용하는 것이 가장 좋은 방법! 🚀
'Aura LWC JavaScript' 카테고리의 다른 글
map을 활용해 배열 속 객체를 재구성하기 (1) | 2021.07.09 |
---|---|
[JS] Array.prototype.map() (0) | 2021.07.09 |