[JS30] JavaScript30 Day 3
서론
오늘은 Day 3!
오늘의 배울 것은 JS로 CSS 변수들을 변경하는 것이다.
구현
링크
Task
- CSS 변수의 값들을 재사용할 수 있게 만들기
:root
가상 클래스 선언
:root
사용하기var()
- user input 들고 오기
- JS에서 변화시키기
1. CSS 변수의 값들을 재사용할 수 있게 만들기
CSS 또한 JS처럼 전역 변수를 선언하는 것이 가능하다. 바로 :root
를 사용하면 된다. MDN에서 :root
가 무엇인지 찾아보자.
CSS :root 의사 클래스는 문서 트리의 루트 요소를 선택합니다. HTML의 루트 요소는 <html> 요소이므로, :root의 명시도가 더 낮다는 점을 제외하면 html 선택자와 똑같습니다.
이 설명만 보면 :root
가 무엇인지 단박에 이해하기 어렵다. 그럼 영어 설명을 보자.
The :root CSS pseudo-class matches the root element of a tree representing the document. In HTML, :root represents the <html> element and is identical to the selector html, except that its specificity is higher.
그렇다. :root
는 pseudo-class
, 즉 가상 클래스이다.
:root can be useful for declaring global CSS variables
문서에 따르면, :root
는 전역 CSS 변수들을 선언할 때 사용된다고 한다.
무엇인지, 그리고 어떻게 사용하는지 알았으니 이제 사용해보자.
controls
의 안에 input
들의 name
에 따라서 속성의 이름을 지었다.
:root {
--base: #ffc600;
--spacing: 10px;
--blur: 10px;
}
2. :root
사용하기
img {
padding: var(--spacing);
background-color: var(--base);
filter: blur(var(--blur));
}
:root
에서 선언한 속성을 사용하려면 var(--*)
형식으로 사용해야 한다. 속성들의 속성값이 변경될 때마다 이미지의 padding
, background-color
, filter
값이 변경되는 것이다.
3. user input 들고 오기
우선 변화시키기에 앞서 얼마큼 변경해야 하는지를 알아야 하니 유저의 입력을 가져오자.
const inputs = document.querySelectorAll(".controls input");
으로 input
요소들을 모조리 가져온다.
inputs.forEach(input => input.addEventListener('change', function));
inputs.forEach(input => input.addEventListener('mousemove', function));
그리고 input
값에 변화가 있을 때마다 값을 변화시킬 함수를 실행하는 것이다. forEach
를 사용하는 이유는 바로 querySelectorAll
의 반환 값이 NodeList
형태이기 때문이다. 참고로 NodeList !== Array
이다.
4. JS에서 변화시키기
이제 CSS에서 전역 변수를 선언하는 법과 사용하는 법, 그리고 변화 값도 알았으니 JS에서 변화할 차례다.
그런데 CSS 내의 값을 어떻게 JS로 들고 와야 할까? :root
문서를 다시 보자.
The :root CSS pseudo-class matches the root element of a tree representing the document. In HTML, :root represents the <html> element and is identical to the selector html, except that its specificity is higher.
HTML에선 :root
가 html 요소임으로 document.documentElement
으로 html 요소를 들고 오면 되는 것이다.
이제 CSS에서 선언된 스타일 속성을 변화시켜야 하니 style.setProperty(속성 이름, 값);
함수를 사용하면 된다.
document.documentElement.style.setProperty(`--${this.name}`, this.value);
이제 실행해보면 분명 값이 변하기는 하는데 화면에 변화가 없다. 왜냐면 단위가 없기 때문이다.
그래서 input
을 살펴보면 data-sizing
이라는 속성이 있다. 이것은 비표준 속성으로, 단위를 저장하기 위해서 따로 만든 속성이다.
데이터 속성 사용에 관해서 궁금하면 MDN의 데이터 속성 사용하기 문서를 참고하도록 하자.
const suffix = this.dataset.sizing || '';
document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix);
suffix 라는 변수를 하나 생성해서, 단위가 있다면 저장하고 단위가 없다면 (색상을 변화하기 위해서 단위가 필요하지 않기 때문에 색상을 입력받는 input
은 단위가 없다.) ''
을 저장하도록 한 뒤, JS로 변화를 화면에 적용하는 것이다.
TLD
CSS로도 전역 변수를 선언할 수 있다는 사실을 처음 알았다! 그리고 그 값을 JS로 변경할 수 있다니 참 신기했다.
또한 속성을 이렇게 사용할 수 있다는 것도 참 놀라웠다. 지금까지 내가 짜왔던 코드들을 돌아보면, 돌아가기만 하는 코드들을 짜고 있었다는 것을 깨달았다.
이젠 돌아가기만 하는 코드가 아니라, 똑똑한 코드를 짤 수 있으면 좋겠다! 그렇게 하려면 더 열심히 공부해야지 히히
최종 코드
CSS:
:root {
--base: #ffc600;
--spacing: 10px;
--blur: 10px;
}
img {
padding: var(--spacing);
background-color: var(--base);
filter: blur(var(--blur));
}
.hl {
color: var(--base);
}
JS:
const inputs = document.querySelectorAll(".controls input");
function handleUpdate() {
const suffix = this.dataset.sizing || '';
document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix);
}
inputs.forEach(input => input.addEventListener('change', handleUpdate));
inputs.forEach(input => input.addEventListener('mousemove', handleUpdate));
댓글남기기