5-1 CSSOM & Rules

CSS 도 마찬가지로 javascript 를 통해 수정할 수 있다.

DOM 에 인라인 스타일을 넣는 것이 아니라. CSS 그 자체를 수정한다.

CSSOM

  • CSS 를 모델링 해서 OBJECT 화 한 것

CSS Object Model#

Style Dom Element

<style></style>

  • 스타일 태그를 의미
<style id="s">
.test { background: #ff0 }
</style>
const el = document.querySelector("#s");

note CSS 의 실체! 스타일 태그 안의 sheet 속성#

CSS 의 실체는 DOM 으로 포장해서 html document 에 집어넣은 것이다.

태그

태그는 실체가 아닌, 어떤 것을 html 에 끼워넣기 위한 래핑 객체인 것이다.

sheet 안에는 CSSStyleSheet 라는 객체가 들어있다. style 태그의 실제 실체인 것이다.

const sheet = el.sheet;

sheet 는 CSSRules 라는 List(유사 배열) 를 갖고 있다.

  • 수 많은 룰들을 소유하고 있다.

image

const rules = sheet.cssRules;

item 하나하나가 rule 이 된다.

const rule = rules[0];

image

이 때 0 번에 들어있는 것은 .test { backgound:#ff0 }

이다. 하나의 CSS 정의가, 하나의 RULE 이 된다.

image

RULE 에는 속성이 여러가지가 있다.

  • Type
  • selectorText
  • style 객체
    • CSSStyleDeclaration 클래스의 객체
    • DOM Element 에도 똑같은 style 객체가 들어있다.
    • 인라인 스타일을 주관한다
    • element 의 style 속성을 이용해서 조작한다.
const el = document.querySelector("#s");
const sheet = el.sheet;
const rules = sheet.cssRules;
const rule = rules[0];
console.log(rule.selectorText); // .test
console.log(rule.style.background); // rgb(255, 255, 0)

html text 를 통해서 정의했던 css 가 실제로 브라우저에서 해석과정을 거치고나면 메모리에는 이러한 형태의 객체로 저장이 된다

CSS Rule Type#

image 1번 타입의 Rule 이라는 뜻이다. 일반적으로 1번은 CSS 정의에 대한 Rule 이다

이 type 의 종류는 굉장히 많다.

https://developer.mozilla.org/en-US/docs/Web/API/CSSRule/type

css 에서 사용할 수 있는 모든 구문은 전부다
대응되는 특별한 rule 객체로 바껴서 rules 안에 들어간다

Insert Rule#

다음은 동적으로 CSS 를 추가하는 문제이다.

css는 어디에 추가하는 것이냐면 rules 라는 list 에 append 를 하는 것이 아닌
sheet 에다가 직접 추가한다.

const sheet = el.sheet;
const rules = sheet.cssRules;
sheet.insertRule('.red{background:red}', rules.length);
sheet.insertRule('.blue{background:blue}', rules.length);
console.log(Array.from(rules)
.map(v => v.cssText)
.join('/n'));

insertRule 의 첫번째 문자열 인자를 알아서 파싱해준다.
두번째 인자는 인덱스 번호를 지정한다.

length 를 넣으면 젤 마지막에 추가한다.

css 는 rulesList 안에 순서가 중요하다.
아래에 있는 것이 덮어쓴다.

<body>
<div class="red">red</div>
<div class="blue">blue</div>
</body>
<style id="s">
.test { background: #ff0 }
</style>
<script>
const el = document.querySelector("#s");
const sheet = el.sheet;
const rules = sheet.cssRules;
const rule = rules[0];
sheet.insertRule('.red{background:red}', rules.length);
sheet.insertRule('.blue{background:blue}', rules.length);
</script>

image

docuemnt 는 document 의 sheet 객체에 변화가 생기면 repaint 를 한다.
상황에 따라서는 reflow 까지 처리를 한다.
화면을 다시 리랜더링 하는 효과가 있다.

document.querySelector('.red').onclick = () => {
sheet.insertRule('.red{background:red}', rules.length);
sheet.insertRule('.blue{background:blue}', rules.length);
}

document 에 style 이 어떻게 변화했는지 어떻게 알까?
document 에 처음부터 style 태그를 박아놨기 때문이다.

image

<style id="s">
.test { background: #ff0 }
</style>
<style id="s2">
.test2 { background: #ff0 }
</style>

image

image

styleSheet 도 마지막에 있는 것이 더 우선된다. sheet 객체별로 관리할 수도 있다.

disable 라는 속성이 있다. 현재 모두 false 이다.

document.styleSheets[0].disabled = true;

를 하면 스타일이 disable 이 된다.

image

Delete Rule#

sheet.deleteRule(rules.length - 1); // 가장 마지막 요소 제거

deleteRule 은 인덱스만 쓸 수 있다.

document.querySelector('.blue').onclick = () => {
sheet.deleteRule(rules.length - 1);
}

image

스타일 시트를 건드리면 인라인 태그를 건들이는 것보다 훨씬더 좋은일이 일어난다.#

  • 스타일 하나만 건들이면 스타일이 적용되어있는 것이 전부다 적용된다.
  • 성능상의 저하가 전혀 없다.
  • 비용도 싸다.
  • 태그에는 미리 클래스를 적용해 놔도 아무 문제가 없다.
Last updated on