화면을 개발할 때 직접 코드를 다 작성하는 경우도 있지만, 경우에 따라 이미 만들어진 라이브러리를 import 해서 구현을 할 때가 있다. 그런데 라이브러리 컴포넌트 UI가 마음에 들지 않아 변경하려고 style을 추가했는데도 전혀 적용이 되지 않는 경우가 있었다. F12를 눌러 개발자도구로 확인했을 때에는 내가 작성한게 하나도 적용이 되지 않고,, 구글링부터 ChatGPT까지 이런 경우에는 어떻게 해야하는지 알아본 과정을 기록하는 포스팅이다.
1. querySelector() + !important
설정 style이 적용이 안되자마자 바로 적용했던 방법이다. 클래스명이나 id명으로 element를 가져온 후, 해당 요소의 스타일 속성을 !important로 설정하는 것이다. 가끔 다른 설정 때문에 내가 작성한 설정이 적용 안될 때 쓰는 방법이다.
- 예시
- 상황 설명 : 요소에 설정한 클래스명이 example-element이고, 이 클래스를 적용한 요소들의 height를 500px이 되게 고정하고 싶은 경우
// 1. 자바스크립트에서 설정
const element = document.querySelector('example-element');
if (element) {
element.style.setProperty('height', '500px', 'important');
}
2. css에서 설정
.exampleElement { height : 500px !important;}
-> 이렇게 설정한 후 웹 개발자 도구를 확인한 결과, 여전히 exampleElement 클래스를 설정한 요소의 height는 500px이 아닌 다른 값이었다.
2. 코드 실행 시점을 바꾸기
라이브러리를 이용하다보니 내가 작성한 코드가 라이브러리 코드 전에 먼저 실행되기 때문에 내가 작성한 코드가 덮어씌어져서 적용이 안되는 걸 수도 있다고 한다. 그래서 addEventListener를 이용해 코드 적용 시점을 바꿔보려고 했었다.
방법은 위 1번에서 작성한 코드를 window.addEventListener() 안에 넣어서 실행하면 된다.
window.addEventListener('load', function() {
const element = document.querySelector('.example-element');
if (element) {
element.style.setProperty('height', '500px', 'important');
}
}
-> 이렇게 했음에도 여전히 example-element 클래스를 적용한 요소의 height: 500px은 적용이 되지 않았다...
3. MutationObserver로 감시해서 강제로 바꾸기
그렇게 chatGPT에게 물어보고 시도해본 결과.. 방법을 찾았는데, 바로 MutationObserver의 observe() 함수를 이용하는 것이었다.
이건 '누가 height를 바꾸면 다시 내가 덮어씌우겠다' 라는 전략이라고 한다. 결국 라이브러리에서 요소의 height를 바꾸는 순간이 있을텐데, 그 순간을 감지한 후 내가 원하는 style을 설정하는 방법이다.
const target = document.querySelector('.example-element');
if (target) {
const observer = new MutationObserver(() => {
target.style.setProperty('height', '500px', 'important');
});
observer.observe(target, {attributes: true, attributeFilter : ['style']});
// 처음에도 한 번 설정
target.style.setProperty('height', '500px', 'important');
}
-> 이렇게 설정해주니 내가 의도한 .example-element 클래스를 적용한 요소의 height가 500px로 고정되는 것을 화면에서 확인할 수 있었다..!
앞선 1, 2번과 다른 점은 new MutationObserver()라는 객체를 생성한 뒤 .observe()를 호출했다는 것이다.
observe()의 인수에 대해 설명해보자면 다음과 같다.
observer.observe(target, {
attributes: true // 속성(attribute)의 변경 감지
,attributeFilter : ['style'] // style 속성만 감지
});
observer.observe(target, options)
1. target : 감시할 DOM 요소(.example-element)
2. options : 어떤 변경을 감시할 건지 설정하는 객체
- options 상세
- attributes : 요소의 속성(attribute)이 변경될 때 감지할지 여부(true/false)
- attributeFilter : 감시할 속성 이름 배열(['style']이면 style의 변경만 감지)
라이브러리를 사용하면 간편하게 구현을 할 수 있다는 장점이 있지만, 어떠한 메커니즘으로 돌아가는 코드인지 정확히 잘 모르기 때문에 다루기가 쉽지는 않은 것 같다. 꼭 바꿔야 하는 경우라면 observe를 적용하는 것이 방법이 될 것 같다.