diff --git a/2-ui/1-document/14-styles-and-classes/article.md b/2-ui/1-document/14-styles-and-classes/article.md index cd73976a..5659f895 100644 --- a/2-ui/1-document/14-styles-and-classes/article.md +++ b/2-ui/1-document/14-styles-and-classes/article.md @@ -287,46 +287,11 @@ function getStyle(elem) { Он основан на свойствах `runtimeStyle` и `pixelLeft`, работающих только в IE. -В следующем примере функция `getIEComputedStyle(elem, prop)` получает значение в пикселях для свойства `prop`, используя `elem.currentStyle` и метод Дина Эдвардса. +В [edit src="getiecomputedstyle"]песочнице[/edit] вы можете найти функцию `getIEComputedStyle(elem, prop)`, которая получает значение в пикселях для свойства `prop`, используя `elem.currentStyle` и метод Дина Эдвардса, и пример её применения. Если вам интересно, как он работает, ознакомьтесь со свойствами с runtimeStyle и pixelLeft в MSDN и раскройте код. -```js -//+ src="getIEComputedStyle.js" hide="Раскрыть код" - -``` - - - -Рабочий пример (только IE): - -```html - -
-
-Вы можете открыть документ [edit src="metric"]по этой ссылке[/edit].
-## Получение width/height из CSS
-
-Какой способ первый приходит на ум, когда есть задача определить `width/height`?
-
-Если вы внимательно читали до этого момента, то уж точно знаете, что CSS-высоту и ширину `width/height` можно установить с помощью `elem.style` и извлечь, используя `getComputedStyle()/currentStyle`, которые в подробностях обсуждаются в главе [](/styles-and-classes).
-
-Решение может быть таким:
+Получение ширины может быть таким:
```js
//+ run
var elem = document.body;
-
-var style = window.getComputedStyle ? getComputedStyle(elem, "") : elem.currentStyle;
-alert(style.width); // вывести CSS-ширину body
+alert( getComputedStyle(elem).width ); // вывести CSS-ширину для body
```
Всегда ли такой подход сработает? Увы, нет!
-
+Вы можете открыть этот документ [edit src="metric"]в песочнице[/edit].
-### scrollWidth/Height
+У элементов существует ряд свойств, содержащих их внешние и внутренние размеры. Мы будем называть их "метриками".
-Ширина и высота контента *с учетом прокручиваемой области*.
+Метрики, в отличие от свойств CSS, содержат числа, всегда в пикселях и без единиц измерения на конце.
-
-
+На картинке все они с трудом помещаются, но, как мы увидим далее, их значения просты и понятны.
-Эти свойства можно использовать, чтобы "распахнуть" элемент на всю ширину/высоту:
+Будем исследовать их снаружи элемента и вовнутрь.
-```js
-element.style.height = element.scrollHeight + 'px';
-```
+## offsetWidth/Height
-Нажмите на кнопку, чтобы распахнуть элемент:
-
-
-
-[smart header="`scrollLeft/scrollTop` можно изменять"]
-**В отличие от большинства свойств, которые доступны только для чтения, значения `scrollLeft/scrollTop` можно изменить, и браузер выполнит прокрутку элемента**.
-
-При клике на следующий элемент будет выполняться код `elem.scrollTop += 10`. Поэтому он будет прокручиваться на `10px` вниз:
-
-
-Эти свойства показывают *внешние* ширину и высоту блока, то как блок выглядит снаружи.
-
-### clientTop/Left
-
-Отступ *клиентской области* от внешнего угла блока.
-
-Другими словами, это ширина верхней/левой рамки(border) в пикселях.
-
-
-
-Казалось бы, зачем еще какие-то свойства, если ширину рамки можно получить напрямую из CSS? Обычно они действительно не нужны.
-
-Но есть две ситуации, когда эти свойства бывают полезны:
-
-
-
-
[smart header="Метрики для невидимых элементов равны нулю."]
@@ -242,13 +166,102 @@ function isHidden(elem)
+
+Казалось бы, зачем еще какие-то свойства, если ширину рамки можно получить напрямую из CSS? Да, можно. Обычно они действительно не нужны.
+
+Но в случае, когда документ располагается *справа налево* (арабский язык, иврит), полоса прокрутки находится слева, и тогда свойство `clientLeft` включает в себя еще и ширину полосы прокрутки.
+
+## clientWidth/Height
+
+Эти свойства -- размер внутренней зоны элемента внутри рамок `border`.
+
+Она включает в себя как ширину содержимого `width`, так и поля `padding`:
+
+
+
+Как видно на рисунке выше, `clientWidth` в нашем документе складывается из ширины области содержимого (`284px`) плюс левый и правый `padding` (по `20px`), то есть всего `324px`.
+
+Аналогично, `clientHeight` -- это высота области содержимого (`200px`) плюс верхний и нижний `padding` (по `20px`), то есть `240px`. На рисунке выше нижний `padding` заполнен текстом, но это неважно: по правилам он всегда входит в `clientHeight`.
+
+
+**Если `padding` нет, то `clientWidth/Height` в точности равны размеру области содержимого, внутри рамок и полосы прокрутки.**
+
+
+
+Поэтому в тех случаях, когда мы точно знаем, что `padding` нет, их используют для определения внутренних размеров элемента. И, в отличие от `getComputedStyle(elem).width`, эти свойства всегда работают верно.
+
+## scrollWidth/Height
+
+Эти свойства -- аналоги `clientWidth/clientHeight`, но с учетом прокрутки.
+
+Свойства `clientWidth/clientHeight` относятся только к видимой области элемента, а `scrollWidth/scrollHeight` добавляют к ней прокрученную по горизонтали/вертикали.
+
+На рисунке выше:
+
+
+Эти свойства можно использовать, чтобы "распахнуть" элемент на всю ширину/высоту:
+
+```js
+element.style.height = element.scrollHeight + 'px';
+```
+
+[online]
+[pre no-typography]
+Нажмите на кнопку, чтобы распахнуть элемент:
+
+
+
+[smart header="`scrollLeft/scrollTop` можно изменять"]
+В отличие от большинства свойств, которые доступны только для чтения, значения `scrollLeft/scrollTop` можно изменить, и браузер выполнит прокрутку элемента.
+
+[online]
+При клике на следующий элемент будет выполняться код `elem.scrollTop += 10`. Поэтому он будет прокручиваться на `10px` вниз:
+
+
-
-**Прокрутку *элемента* можно прочитать или изменить через свойства `scrollLeft/Top`.**
-
-В этой главе мы считали, что страница находится в режиме соответствия стандартам. В режиме совместимости -- всё так же, но некоторые старые браузеры требуют `document.body` вместо `documentElement`.
+В этой главе мы считали, что страница находится в режиме соответствия стандартам. В режиме совместимости -- некоторые старые браузеры требуют `document.body` вместо `documentElement`, в остальном всё так же. Конечно, по возможности, стоит использовать только режим соответствия стандарту.
diff --git a/2-ui/1-document/15-metrics/summary2.png b/2-ui/1-document/15-metrics/summary2.png
new file mode 100644
index 00000000..a68b1c74
Binary files /dev/null and b/2-ui/1-document/15-metrics/summary2.png differ
diff --git a/2-ui/1-document/16-metrics-window/1-get-document-scrolls/task.md b/2-ui/1-document/16-metrics-window/1-get-document-scrolls/task.md
index b04f07cd..7a5b8cd4 100644
--- a/2-ui/1-document/16-metrics-window/1-get-document-scrolls/task.md
+++ b/2-ui/1-document/16-metrics-window/1-get-document-scrolls/task.md
@@ -1,4 +1,4 @@
-# Получить прокрутки документа
+# TODO: перенеси меня в координаты? Тут координат еще не было
[importance 5]
diff --git a/2-ui/1-document/16-metrics-window/article.md b/2-ui/1-document/16-metrics-window/article.md
index e1d93a2b..f91c999d 100644
--- a/2-ui/1-document/16-metrics-window/article.md
+++ b/2-ui/1-document/16-metrics-window/article.md
@@ -1,7 +1,11 @@
# Размеры и прокрутка страницы
-Многие метрики для страницы работают совсем не так, как для элементов. Поэтому рассмотрим решения типичных задач для страницы отдельно.
+Многие метрики для страницы работают совсем не так, как для элементов.
+
+Поэтому мы рассмотрим решения типичных задач для страницы отдельно.
+
[cut]
+
## Ширина/высота видимой части окна
Свойства `clientWidth/Height` для элемента `document.documentElement` позволяют получить ширину/высоту видимой области окна.
@@ -12,49 +16,69 @@
Этот способ -- кросс-браузерный.
-## Ширина/высота всей страницы, с учётом прокрутки
+[warn header="Не `window.innerWidth/Height`"]
+Все браузеры, кроме IE8-, также поддерживают свойства `window.innerWidth/innerHeight`. Они хранят текущий размер окна.
-Если прокрутка на странице присутствует, то полные размеры страницы можно взять в `document.documentElement.scrollWidth/scrollHeight`.
+Выглядят они короче, чем `document.documentElement.clientWidth`, однако есть один нюанс.
+
+Свойства `clientWidth/Height` берут в расчёт полосу прокрутку, а эти свойства -- нет.
+
+Если справа часть страницы занимает полоса прокрутки, то эти строки выведут разное:
+```js
+//+ run
+alert( window.innerWidth ); // вся ширина окна
+alert( document.documentElement.clientWidth ); // ширина минус прокрутка
+```
+
+Обычно нам нужна именно *доступная* ширина окна, например, чтобы нарисовать что-либо, то есть за вычетом полосы прокрутки. Поэтому используем `document.documentElement.clientWidth`.
+[/warn]
+
+## Ширина/высота страницы с учётом прокрутки
+
+Если прокрутка на странице заведомо присутствует, то полные размеры страницы можно взять в `document.documentElement.scrollWidth/scrollHeight`.
Проблемы с этими свойствами возникают, когда *прокрутка то есть, то нет*. В этом случае они работают некорректно.
-В браузерах Chrome/Safari и Opera при отсутствии прокрутки значение `document.documentElement.scrollHeight` в этом случае может быть даже меньше, чем `document.documentElement.clientHeight` (нонсенс!). Эта проблема -- именно для `document.documentElement`, то есть для всей страницы. С обычными элементами здесь всё в порядке.
+В браузерах Chrome/Safari и Opera при отсутствии прокрутки значение `document.documentElement.scrollHeight` в этом случае может быть даже меньше, чем `document.documentElement.clientHeight` (нонсенс!).
-Надёжно определить размер с учетом прокрутки можно, взяв максимум из двух свойств:
+Эта проблема возникает именно для `document.documentElement`, то есть для всей страницы. С обычными элементами здесь всё в порядке.
+
+Надёжно определить размер страницы с учетом прокрутки можно, взяв максимум из нескольких свойств:
```js
//+ run
-var scrollHeight = document.documentElement.scrollHeight;
-var clientHeight = document.documentElement.clientHeight;
-
-*!*
-scrollHeight = Math.max(scrollHeight, clientHeight);
-*/!*
+var scrollHeight = Math.max(
+ document.body.scrollHeight, document.documentElement.scrollHeight,
+ document.body.offsetHeight, document.documentElement.offsetHeight,
+ document.body.clientHeight, document.documentElement.clientHeight
+);
alert('Высота с учетом прокрутки: ' + scrollHeight);
```
-## Прокрутка страницы [#page-scroll]
+Почему так? Лучше и не спрашивайте, это одно из редких мест, где просто обходятся ошибки в браузерах. Глубокой логики здесь нет.
-### Получение текущей прокрутки
+## Получение текущей прокрутки [#page-scroll]
Значение текущей прокрутки страницы хранится в свойствах `window.pageXOffset/pageYOffset`.
-Но эти свойства:
+```js
+//+ run
+alert('Текущая прокрутка сверху: ' + window.pageYOffset);
+alert('Текущая прокрутка слева: ' + window.pageXOffset);
+```
+
+Эти свойства: