Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 5 additions & 14 deletions 2-ui/1-document/08-styles-and-classes/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,21 +128,16 @@ setTimeout(() => document.body.style.display = "", 1000); // 1초 후 다시 원

이렇게 `style.display`에 빈 문자열을 할당하면 브라우저는 마치 처음부터 `style.display` 프로퍼티가 없었던 것처럼 CSS 클래스와 브라우저 내장 스타일을 페이지에 적용합니다.

<<<<<<< HEAD
````smart header="`style.cssText`로 완전히 다시 쓰기"
개별 스타일 프로퍼티를 적용할 때는 보통 `style.*`를 사용합니다. 그런데 `div.style` 은 객체이고 읽기 전용이기 때문에 `div.style="color: red; width: 100px"`같은 방식으론 전체 스타일을 설정할 수 없습니다.
=======
Also there is a special method for that, `elem.style.removeProperty('style property')`. So, We can remove a property like this:
이를 위한 특별한 메서드인 `elem.style.removeProperty('style property')`도 있습니다. 아래와 같이 프로퍼티를 제거할 수 있습니다.

```js run
document.body.style.background = 'red'; //set background to red
document.body.style.background = 'red'; // 배경을 빨간색으로 설정

setTimeout(() => document.body.style.removeProperty('background'), 1000); // remove background after 1 second
setTimeout(() => document.body.style.removeProperty('background'), 1000); // 1초 후 배경 제거
```

````smart header="Full rewrite with `style.cssText`"
Normally, we use `style.*` to assign individual style properties. We can't set the full style like `div.style="color: red; width: 100px"`, because `div.style` is an object, and it's read-only.
>>>>>>> upstream/master
````smart header="`style.cssText`로 완전히 다시 쓰기"
개별 스타일 프로퍼티를 적용할 때는 보통 `style.*`를 사용합니다. 그런데 `div.style` 은 객체이고 읽기 전용이기 때문에 `div.style="color: red; width: 100px"`같은 방식으론 전체 스타일을 설정할 수 없습니다.

문자열을 사용해 전체 스타일을 설정하려면 프로퍼티 `style.cssText`를 사용해야 합니다.

Expand Down Expand Up @@ -273,7 +268,6 @@ pseudo
````warn header="`getComputedStyle`엔 프로퍼티 전체 이름이 필요합니다."
`getComputedStyle`을 사용할 때는 `paddingLeft`, `marginTop`, `borderTopWidth`같이 프로퍼티 이름 전체를 정확히 알고 있어야 합니다. 그렇지 않으면 원하는 값을 얻을 수 없는 경우가 생깁니다.

<<<<<<< HEAD
`paddingLeft`나 `paddingTop`엔 값이 지정되어있는데 `getComputedStyle(elem).padding`을 사용해 값을 얻으려 하는 경우를 생각해 봅시다. 어떤 값을 얻을 수 있을까요? 아무것도 얻지 못할까요 아니면 값이 설정되어 있는 `paddingLeft`나 `paddingTop`에서 값을 가져올까요? 이런 상황에 적용할만한 표준은 아직 제정되어있지 않습니다.

따라서 브라우저마다 동작 방식이 다릅니다. Chrome 같은 몇몇 브라우저는 아래 예시와 같이 `10px`을 출력해주는데 Firefox에서 빈 문자열이 출력됩니다.
Expand All @@ -289,9 +283,6 @@ pseudo
alert(style.margin); // Firefox에선 빈 문자열이 출력됩니다.
</script>
```
=======
For instance, if there are properties `paddingLeft/paddingTop`, then what should we get for `getComputedStyle(elem).padding`? Nothing, or maybe a "generated" value from known paddings? There's no standard rule here.
>>>>>>> upstream/master
````

```smart header="`:visited` 링크 관련 스타일은 숨겨져 있습니다."
Expand Down
8 changes: 0 additions & 8 deletions 2-ui/1-document/09-size-and-scroll/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,7 @@ CSS `position` 프로퍼티가 설정되어있는 조상 요소가 없는 경우

따라서 요소(혹은 이 요소의 조상 요소 중 어떤 것이든)의 CSS `display` 프로퍼티가 `none`이거나 문서 내에 해당 요소가 없으면 모든 기하 프로퍼티 값이 0이 됩니다(`offsetParent` 프로퍼티의 값은 `null`).

<<<<<<< HEAD
요소를 만들긴 했지만 아직 문서에 삽입하기 전이라던가, 새롭게 만든 요소의 `display` 프로퍼티가 `none`이면 기하 프로퍼티 값은 0, `offsetParent` 프로퍼티의 값은 `null`이 되는 것이죠.
=======
For example, `offsetParent` is `null`, and `offsetWidth`, `offsetHeight` are `0` when we created an element, but haven't inserted it into the document yet, or it (or its ancestor) has `display:none`.
>>>>>>> upstream/master

이런 특징을 이용하면 요소의 숨김 상태 여부를 아래 같은 방법으로 확인할 수 있습니다.

Expand All @@ -120,11 +116,7 @@ function isHidden(elem) {
}
```

<<<<<<< HEAD
참고로 `isHidden`은 요소가 화면에 있긴 하지만 사이즈가 0일 때(비어있는 `<div>` 등)도 `true`를 반환하기 때문에 주의해서 사용해야 합니다.
=======
Please note that such `isHidden` returns `true` for elements that are on-screen, but have zero sizes.
>>>>>>> upstream/master
````

## clientTop과 clientLeft
Expand Down
102 changes: 7 additions & 95 deletions 2-ui/1-document/10-size-and-scroll-window/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,11 @@

브라우저 창이 차지하는 너비와 높이를 어떻게 구할 수 있을까요? 스크롤 때문에 보이지 않는 영역을 포함하여 문서 전체가 차지하는 너비와 높이는 어떻게 구할 수 있을까요? 자바스크립트를 사용해서 페이지를 스크롤 할 수 있을까요?

<<<<<<< HEAD
이번 챕터에선 위와 같은 물음에 답을 주는 루트 문서 요소인 `document.documentElement`를 살펴볼 예정입니다. `document.documentElement`는 `<html>` 태그와 상응하는 요소로 다양한 메서드를 지원합니다. 유용한 메서드이긴 하지만 몇 가지 주의할 점이 있어 같이 살펴봅시다.
=======
For this type of information, we can use the root document element `document.documentElement`, that corresponds to the `<html>` tag. But there are additional methods and peculiarities to consider.
>>>>>>> upstream/master

## 브라우저 창의 너비와 높이

<<<<<<< HEAD
창이 차지하는 너비와 높이를 알려면 `document.documentElement`의 `clientWidth`와 `clientHeight`를 사용하면 됩니다.
=======
To get window width and height, we can use the `clientWidth/clientHeight` of `document.documentElement`:
>>>>>>> upstream/master

![](document-client-width-height.svg)

Expand All @@ -24,33 +16,20 @@ To get window width and height, we can use the `clientWidth/clientHeight` of `do
<button onclick="alert(document.documentElement.clientHeight)">alert(document.documentElement.clientHeight)</button>
```

<<<<<<< HEAD
````warn header="`window` 객체가 아닌 `document.documentElement`를 쓰는 이유"
브라우저의 `window` 객체 역시 `innerWidth`와 `innerHeight` 프로퍼티를 지원합니다. 이 프로퍼티를 써도 원하는 대로 창 크기를 구할 수 있을 것 같은데 왜 `document.documentElement`의 `clientWidth`나 `clientHeight`를 쓰는 걸까요?

스크롤바가 생기면 스크롤바 역시 공간을 차지하는데, `clientWidth`나 `clientHeight`는 스크롤바가 차지하는 공간을 제외해서 너비나 높이 값을 계산합니다. 눈에 보이는 문서에서 콘텐츠가 실제로 들어가게 될 영역의 너비와 높이 값을 반환하는 것이죠.

그런데 `window.innerWidth/innerHeight`는 스크롤바가 차지하는 영역을 포함해 값을 계산합니다.
=======
````warn header="Not `window.innerWidth/innerHeight`"
Browsers also support properties like `window.innerWidth/innerHeight`. They look like what we want, so why not to use them instead?

If there exists a scrollbar, and it occupies some space, `clientWidth/clientHeight` provide the width/height without it (subtract it). In other words, they return the width/height of the visible part of the document, available for the content.

`window.innerWidth/innerHeight` includes the scrollbar.
>>>>>>> upstream/master

스크롤바가 있는 경우 스크롤 바 역시 공간을 차지하는데, 이럴 때 `window`객체와 `document.documentElement`의 해당 프로퍼티들은 다른 값을 반환합니다.
```js run
alert( window.innerWidth ); // 전체 창 너비
alert( document.documentElement.clientWidth ); // 스크롤바가 차지하는 영역을 제외한 창 너비
```

<<<<<<< HEAD
창 사이즈가 필요한 경우는 스크롤 바 안쪽에 무언가를 그리거나 위치시킬 때가 대다수입니다. 따라서 `documentElement`의 `clientHeight/clientWidth`를 써야 합니다.
=======
In most cases, we need the *available* window width in order to draw or position something within scrollbars (if there are any), so we should use `documentElement.clientHeight/clientWidth`.
>>>>>>> upstream/master
````

```warn header="`DOCTYPE`을 꼭 써주세요."
Expand All @@ -61,15 +40,9 @@ In most cases, we need the *available* window width in order to draw or position

## 문서의 너비와 높이

<<<<<<< HEAD
이론상 `document.documentElement`는 문서의 루트 요소에 상응하고, 루트 요소엔 콘텐츠 전부가 들어가기 때문에 우리는 문서의 전체 크기를 `document.documentElement`의 `scrollWidth`와 `scrollHeight`를 사용해 재면 되지 않냐고 생각합니다.

그런데 전체 페이지를 대상으로 했을 때, `document.documentElement`의 프로피터들은 우리가 예상한 대로 동작하지 않습니다. Chrome이나 Safari, Opera에서 스크롤이 없는 경우 `documentElement.scrollHeight`는 `documentElement.clientHeight`보다 작을 때가 있죠. 예상하기엔 같은 값이어야 하는데도 말입니다.
=======
Theoretically, as the root document element is `document.documentElement`, and it encloses all the content, we could measure the document's full size as `document.documentElement.scrollWidth/scrollHeight`.

But on that element, for the whole page, these properties do not work as intended. In Chrome/Safari/Opera, if there's no scroll, then `documentElement.scrollHeight` may be even less than `documentElement.clientHeight`! Weird, right?
>>>>>>> upstream/master

정확한 문서 전체 높이 값을 얻으려면 아래 여섯 프로퍼티가 반환하는 값 중 최댓값을 골라야 합니다.

Expand All @@ -87,19 +60,11 @@ alert('스크롤에 의해 가려진 분을 포함한 전체 문서 높이: ' +

## 스크롤 정보 얻기 [#page-scroll]

<<<<<<< HEAD
DOM 요소의 현재 스크롤 상태(스크롤에 의해 가려진 영역에 대한 정보)는 `scrollLeft`와 `scrollTop` 프로퍼티를 통해 구할 수 있습니다.

대부분의 브라우저에서 문서의 스크롤 상태는 `document.documentElement`의 `scrollLeft`나 `scrollTop`을 이용해 구할 수 있습니다. 다만 구버전 WebKit을 기반으로 하는 브라우저에선 버그([5991](https://bugs.webkit.org/show_bug.cgi?id=5991)) 때문에 `document.documentElement`가 아닌 `document.body`를 사용해야 원하는 값을 구할 수 있습니다.

이쯤 되면 스크롤 포지션 정보를 구하기 위해 브라우저별 예외처리까지 다 해야 하나 라는 생각이 들 수 있을 겁니다. 다행히도 `window`객체의 `pageXOffset`과 `pageYOffset`을 사용하면 브라우저 상관없이 스크롤 정보를 구할 수 있어서 이런 예외 상황을 외워두지 않아도 됩니다.
=======
DOM elements have their current scroll state in their `scrollLeft/scrollTop` properties.

For document scroll, `document.documentElement.scrollLeft/scrollTop` works in most browsers, except older WebKit-based ones, like Safari (bug [5991](https://bugs.webkit.org/show_bug.cgi?id=5991)), where we should use `document.body` instead of `document.documentElement`.

Luckily, we don't have to remember these peculiarities at all, because the scroll is available in the special properties, `window.pageXOffset/pageYOffset`:
>>>>>>> upstream/master

```js run
alert('세로 스크롤에 의해 가려진 위쪽 영역 높이: ' + window.pageYOffset);
Expand All @@ -108,40 +73,25 @@ alert('가로 스크롤에 의해 가려진 왼쪽 영역 너비: ' + window.pag

참고로 이 두 프로퍼티는 읽기만 가능합니다.

<<<<<<< HEAD
## scrollTo, scrollBy로 스크롤 상태 변경하기 [#window-scroll]

```warn
자바스크립트를 사용해 스크롤을 움직이려면 DOM이 완전히 만들어진 상태이어야 합니다.

`<head>`에 있는 스크립트에서 페이지 전체의 스크롤을 움직이려 하면 잘 동작하지 않을 수 있습니다.
=======
```smart header="Also available as `window` properties `scrollX` and `scrollY`"
For historical reasons, both properties exist, but they are the same:
- `window.pageXOffset` is an alias of `window.scrollX`.
- `window.pageYOffset` is an alias of `window.scrollY`.
```smart header="`scrollX`와 `scrollY`라는 `window` 프로퍼티로도 사용 가능합니다"
역사적인 이유로 두 프로퍼티가 모두 존재하지만 동일합니다.
- `window.pageXOffset`은 `window.scrollX`의 별칭입니다.
- `window.pageYOffset`은 `window.scrollY`의 별칭입니다.
```

## Scrolling: scrollTo, scrollBy, scrollIntoView [#window-scroll]
## scrollTo, scrollBy, scrollIntoView로 스크롤 상태 변경하기 [#window-scroll]

```warn
To scroll the page with JavaScript, its DOM must be fully built.
자바스크립트를 사용해 스크롤을 움직이려면 DOM이 완전히 만들어진 상태이어야 합니다.

For instance, if we try to scroll the page with a script in `<head>`, it won't work.
>>>>>>> upstream/master
`<head>`에 있는 스크립트에서 페이지 전체의 스크롤을 움직이려 하면 잘 동작하지 않을 수 있습니다.
```

일반 요소의 스크롤 상태는 `scrollTop`이나 `scrollLeft`로 쉽게 변경할 수 있습니다.

<<<<<<< HEAD
페이지 전체의 스크롤 상태 역시 `document.documentElement`의 `scrollTop/scrollLeft`를 사용해 변경 가능하죠(다만, Safari는 `document.body`의 `scrollTop/scrollLeft`를 써야 합니다).

그런데 이보다 더 편하고 브라우저 상관없이 쓸 수 있는 대안이 있긴합니다. 바로 [window.scrollBy(x,y)](mdn:api/Window/scrollBy)와 [window.scrollTo(pageX,pageY)](mdn:api/Window/scrollTo)입니다.
=======
We can do the same for the page using `document.documentElement.scrollTop/scrollLeft` (except Safari, where `document.body.scrollTop/Left` should be used instead).

Alternatively, there's a simpler, universal solution: special methods [window.scrollBy(x,y)](mdn:api/Window/scrollBy) and [window.scrollTo(pageX,pageY)](mdn:api/Window/scrollTo).
>>>>>>> upstream/master

- `scrollBy(x,y)`메서드를 사용하면 페이지의 스크롤 상태를 현재 포지션을 기준으로 상대적으로 조정합니다. `scrollBy(0,10)`는 문서의 스크롤 상태를 현재를 기준으로 스크롤을 `10px`아래로 내린것 처럼 움직여주죠.

Expand All @@ -162,15 +112,10 @@ Alternatively, there's a simpler, universal solution: special methods [window.sc

## scrollIntoView

<<<<<<< HEAD
추가 메서드 [elem.scrollIntoView(top)](mdn:api/Element/scrollIntoView)를 머릿속에 추가해 스크롤 상태를 완벽히 마스터 해봅시다.
=======
For completeness, let's cover one more method: [elem.scrollIntoView(top)](mdn:api/Element/scrollIntoView).
>>>>>>> upstream/master

`elem.scrollIntoView(top)`를 호출하면 전체 페이지 스크롤이 움직여 `elem`이 눈에 보이는 상태로 변경됩니다. `elem.scrollIntoView`는 인수를 하나 받는데, 인수에 따라 다음과 같이 동작합니다.

<<<<<<< HEAD
- `top`이 `true`(디폴트)인 경우, `elem`이 창 제일 위에 보이도록 스크롤 상태가 변경됩니다. `elem`의 위쪽 모서리가 창의 위쪽 모서리와 일치하게 되죠.
- `top`이 `false`인 경우, `elem`이 창 가장 아래에 보이도록 스크롤 상태가 변경됩니다. `elem`의 아래쪽 모서리가 창의 아래쪽 모서리와 일치하게 변합니다.

Expand All @@ -180,32 +125,15 @@ For completeness, let's cover one more method: [elem.scrollIntoView(top)](mdn:ap
<button onclick="this.scrollIntoView()">this.scrollIntoView()</button>

두 번째 버튼을 누르면 버튼의 아래 모서리가 창 밑으로 붙는 것을 확인할 수 있습니다.
=======
- If `top=true` (that's the default), then the page will be scrolled to make `elem` appear on the top of the window. The upper edge of the element will be aligned with the window top.
- If `top=false`, then the page scrolls to make `elem` appear at the bottom. The bottom edge of the element will be aligned with the window bottom.

```online
The button below scrolls the page to position itself at the window top:

<button onclick="this.scrollIntoView()">this.scrollIntoView()</button>

And this button scrolls the page to position itself at the bottom:
>>>>>>> upstream/master

<button onclick="this.scrollIntoView(false)">this.scrollIntoView(false)</button>
```

## 스크롤 막기

<<<<<<< HEAD
때에 따라 문서 스크롤바를 '고정' 해야 하는 경우가 생기곤 합니다. 사용자에게 반드시 전달해야 하는 중요한 메시지가 있어서 이 메시지를 화면에 크게 띄우고, 사용자가 스크롤을 움직여 다른 콘텐츠를 보지 못하게 한 상태에서 메시지를 읽게 하려는 경우가 대표적인 예가 될 수 있습니다.

이럴 때 `document.body.style.overflow = "hidden"`를 사용할 수 있습니다. 해당 스크립트가 동작하면 페이지의 스크롤바 위치가 '고정' 됩니다.
=======
Sometimes we need to make the document "unscrollable". For instance, when we need to cover the page with a large message requiring immediate attention, and we want the visitor to interact with that message, not with the document.

To make the document unscrollable, it's enough to set `document.body.style.overflow = "hidden"`. The page will "freeze" at its current scroll position.
>>>>>>> upstream/master

```online
직접 실습해봅시다.
Expand All @@ -214,7 +142,6 @@ To make the document unscrollable, it's enough to set `document.body.style.overf

<button onclick="document.body.style.overflow = ''">document.body.style.overflow = ''</button>

<<<<<<< HEAD
위쪽 버튼을 누르면 스크롤바가 고정되었다가, 아래 버튼을 누르면 고정이 해제되는 것을 확인할 수 있습니다.
```

Expand All @@ -223,28 +150,13 @@ To make the document unscrollable, it's enough to set `document.body.style.overf
그런데 이 방법은 스크롤바가 사라진다는 단점이 있습니다. 스크롤바는 일정 공간을 차지하는데, 스크롤바가 사라지면 해당 공간을 채우기 위해 콘텐츠가 갑자기 '움직이는' 현상이 발생합니다.

이렇게 페이지 전체의 스크롤 상태가 갑자기 변경되면 사용자 입장에선 이상해 보일 수 있기 때문에 개발자는 스크롤바를 고정시키기 전과 후의 `clientWidth`값을 비교해서 해당 증상을 보정해야 합니다. 스크롤바가 사라질 땐 `clientWidth`값이 커지는데 이때 스크롤바가 차지했던 영역만큼 `document.body`에 `padding`을 줘서 콘텐츠 전체의 너비를 스크롤바가 사라지기 전과 같은 값으로 유지할 수 있습니다.
=======
The first button freezes the scroll, while the second one releases it.
```

We can use the same technique to freeze the scroll for other elements, not just for `document.body`.

The drawback of the method is that the scrollbar disappears. If it occupied some space, then that space is now free and the content "jumps" to fill it.

That looks a bit odd, but can be worked around if we compare `clientWidth` before and after the freeze. If it increased (the scrollbar disappeared), then add `padding` to `document.body` in place of the scrollbar to keep the content width the same.
>>>>>>> upstream/master

## 요약

기하 프로퍼티:

<<<<<<< HEAD
- 사용자 눈에 보이는 문서(콘텐츠가 실제 보여지는 영역)의 너비와 높이: `document.documentElement.clientWidth/clientHeight`
- 스크롤에 의해 가려진 영역을 포함한 문서 전체의 너비와 높이:
=======
- Width/height of the visible part of the document (content area width/height): `document.documentElement.clientWidth/clientHeight`
- Width/height of the whole document, with the scrolled out part:
>>>>>>> upstream/master

```js
let scrollHeight = Math.max(
Expand Down
Loading