Правильно получить размер элемента DOM

DOM
Правильно получить размер элемента DOM

Как фронтенд-разработчику вам часто приходится иметь дело с элементами DOM, вам также часто нужно что-то делать в зависимости от размера элементов DOM. Но как правильно получить размер элемента DOM? В своей предыдущей работе я часто просто проверял информацию, когда она мне была нужна, и хотя я решил задачу в то время, я не разобрался в этих знаниях глубоко и систематически, чтобы сформировать свою собственную систему знаний. Я написал эту статью с двумя целями: во-первых, я боюсь, что забуду ее в будущем, а если забуду, то прочитаю написанный мной блог; во-вторых, я хочу обсудить ее с вами, чтобы углубить наши отношения. Память. Ну не будем о прочей ерунде, давайте введем текст.

Примечание. Код в этой статье выполняется в браузере Chrome операционной системы Mac, поскольку результаты выполнения кода могут различаться в зависимости от разных операционных систем и браузеров.

Мы получаем размер элемента, в основном по егоclientX,offsetX,scrollXсвойства (гдеXвыражатьwidth,height,left,top). Конкретные свойства можно увидеть в таблице ниже:

clientX offsetX scrollX
clientWidth offsetWidth scrollWidth
clientHeight offsetHeight scrollHeight
clientLeft offsetLeft scrollLeft
clientTop offsetTop scrollTop

Давайте сначала поговорим о свойствах, связанных с clientX,clientLeftУказывает ширину левой границы элемента; следует отметить, что если содержимое внутри элемента создает вертикальную полосу прокрутки, а направление написания текста внутри — справа налево, тоclientLeftВключая полосу прокрутки слева от ширины (браузеры Chrome, Firefox и Opera в системах Windows). Пробуем на практике: HTML-часть выглядит следующим образом:

<div class="clientLeft">这是clientLeft</div>

Часть CSS выглядит следующим образом:

.clientLeft {
    width: 100px;
    height: 100px;
    border-left: 6px solid black;
    padding: 15px;
    background-color: #999;
}

Часть JavaScript выглядит следующим образом:

// 辅助函数
const $ele = function (ele) {
    return document.querySelector(ele);
};
const $log = function () {
    console.log.apply(this, arguments);
};

// 测试clientX 属性
let clientLeft = $ele('.clientLeft');
$log('clientLeft的值是:' + clientLeft.clientLeft);

Мы увидим следующий вывод из консоли:

clientLeft的值是:6

Затем мы модифицируем элементclientLeftCSS, чтобы содержимое текло справа налево и позволяло содержимому выходить за пределы; давайте попробуем:

.clientLeft {
    /* 省略上面已经写过的内容 */
    direction: rtl;
    /* 你需要将clientLeft的内容再增加一下,让里面的内容可以产生滑动 */
    overflow: scroll;
}

Затем смотрим на вывод консоли.На данный момент, если это Chrome под операционной системой Windows, это не будет значение 6. Поскольку на компьютере автора установлена ​​операционная система Mac, вывод консоли по-прежнему равен 6. Ниже приведены результаты тестирования моего браузера Chrome в системе Windows:

Вывод консоли выглядит следующим образом:

clientLeft的值是:23

Далее давайте обсудимclientTopАтрибуты,clientTopОтносится к ширине границы элемента, давайте проверим это свойство. Часть HTML выглядит следующим образом:

<div class="clientTop">这是clientTop,永远都不要放弃你的梦想</div>

Часть CSS выглядит следующим образом:

.clientTop {
    width: 100px;
    height: 100px;
    margin-top: 10px;
    border-top: 6px solid black;
    padding: 15px;
    background-color: #999;
}

Часть JavaScript выглядит следующим образом:

// 测试clientTop 属性
let clientTop = $ele('.clientTop');
$log('clientTop的值是:' + clientTop.clientTop);

Мы видим, что вывод консоли выглядит следующим образом:

clientTop的值是:6

Далее мы обсудимclientWidthа такжеclientHeightИспользование атрибутов; эти два атрибута, один для расчета ширины элемента DOM, а другой для расчета высоты. Однако эти два свойства содержат только ширину и высоту самого элемента, а также ширину и высоту элемента.paddingзначение, но не содержит элементовborderа такжеmarginзначение, давайте проверим его.Также следует отметить, что если содержимое внутри элемента превышает ширину или высоту контейнера и генерируется слайдер, то часть слайдера не будет рассчитана.Часть HTML выглядит следующим образом:

<div class="clientWidth"> 这是clientWidth,永远都不要放弃你的梦想</div>

Часть CSS выглядит следующим образом:

.clientWidth {
    width: 100px;
    height: 100px;
    margin-top: 10px;
    padding: 15px;
    background-color: #999;
}

Часть JavaScript выглядит следующим образом:

// 测试clientWidth 属性
let clientWidth = $ele('.clientWidth');
$log('clientWidth的值是:' + clientWidth.clientWidth);

Мы увидим следующий вывод из консоли:

clientWidth的值是:130

Это потому, что наш CSS устанавливает ширину элемента равной100px, а элементpaddingзначение15px; поэтому элементclientWidthзначение100+15*2=130. Далее давайте проверим случай, когда содержимое превышает ширину контейнера. Часть CSS выглядит следующим образом:

.clientWidth {
    /* 以下部分是测试内容超出的情况 */
    white-space: nowrap;
    overflow: scroll;
}

Когда мы обновляем страницу, мы видим, что вывод консоли остается прежним:

clientWidth的值是:130

Это потому чтоclientWidthВозвращается ширина видимой части элемента, поэтому, если содержимое внутри выходит за ее пределы, ширина лишнего содержимого не будет рассчитываться;clientHeightсвойства иclientWidthСвойства аналогичны и не будут подробно объясняться здесь. Следует отметить, что если описанная выше ситуация в хроме виндовс, тоclientWidthбудет меньше, потому что создается вертикальная полоса прокрутки; так что мы видим на самом делеclientWidthЧасть становится меньше, что на самом деле является исходным значением за вычетом ширины вертикального ползунка, поэтому нам нужно уделять больше внимания этим проблемам при разработке в будущем. Следующее изображение является частью снимка экрана, который я тестировал в Chrome на Windows:

об элементеclientXНа данный момент мы введем здесь соответствующие атрибуты, а затем представим элементы DOM.offsetXсвязанные свойства. Прежде чем объяснять эти свойства, нам нужно знатьoffsetParentЧто это значит Подробное объяснение можно найти здесьHTMLElement.offsetParent,Так называемыйoffsetParentОн относится к текущему элементу, содержащему самые последние элементы позиционирования. Если вы не найдете элементы, то это самый последнийtable,table cellили корневой элемент (в стандартном режиме,html; в причудливом режимеbody).

Давайте проверим элементoffsetParentатрибуты следующим образом: Часть HTML выглядит следующим образом:

<div class="testWrapper">
    <div class="test">用来测试test的offsetParent元素</div>
</div>

Часть CSS выглядит следующим образом:

.testWrapper {
    margin-top: 15px;
    position: relative;
}
// 测试offsetParent 属性
let test = $ele('.test');
let testWrapper = $ele('.testWrapper');
$log('test的offsetParent的值是:', test.offsetParent === testWrapper);

Результаты печати консоли следующие:

test的offsetParent的值是: true

если не поставитьtestWrapperэлементальpositionсвойство установлено наrelativeилиabsolute, тогдаtestизoffsetParentсобственности больше нетtestWrapper. Далее будем учитьсяoffsetLeftа такжеoffsetTopзначения этих двух свойств, гдеoffsetLeftУказывает расстояние от левого верхнего угла текущего элемента до егоoffsetParentрасстояние от левого края узла элемента; иoffsetTopУказывает расстояние от левого верхнего угла текущего элемента до егоoffsetParentРасстояние верхней границы узла элемента. Далее давайте тестируем: Часть CSS выглядит следующим образом:

.testWrapper {
    margin-top: 15px;
    position: relative;
    width: 200px;
    height: 200px;
    padding: 10px;
    background-color: #999999;
    border: 3px solid #333;
}
.test {
    width: 80px;
    height: 80px;
    float: right;
    padding: 5px;
    background-color: #ccff33;
    margin-top: 36px;
    border: 8px solid #333;
}

Часть JavaScript выглядит следующим образом:

// 测试offsetLeft属性和offsetTop属性
$log('test的offsetLeft的值是:' + test.offsetLeft);
$log('test的offsetTop的值是:' + test.offsetTop);

Вывод консоли выглядит следующим образом:

test的offsetLeft的值是:104
test的offsetTop的值是:46

потому чтоtestсмещается вправо, поэтомуtestизoffsetLeftЗначениеtestWrapperширина плюс левыйpaddingЗначение, затем вычестьtestна всю ширину (включаяborderа такжеpaddingзначение), то есть200 + 10 - (80 + 5 x 2 + 8 x 2) = 104,соответствующийoffsetTopЗначение36 + 10 = 46(marginTopзначение плюсtestWrapperизpaddingTopстоимость). Далее будем учитьсяoffsetWidthа такжеoffsetHeightсвойства, сclientWidthа такжеclientHeightразница в том,offsetWidthа такжеoffsetHeightВключает не только ширину и высоту, заданные CSS самого элемента, но также ширину и высоту внутри элемента.paddingзначение; также содержит элементborderЗначение и ширина вертикального ползунка, если внутреннее содержимое скользит; давайте проверим это. Часть HTML выглядит следующим образом:

<div class="offsetWidth"> 这是offsetWidth,永远都不要放弃你的梦想</div>

Часть CSS выглядит следующим образом:

.offsetWidth {
    margin-top: 15px;
    width: 100px;
    height: 100px;
    padding: 8px;
    overflow: scroll;
    border: 9px solid black;
}

Часть JavaScript выглядит следующим образом:

// 测试offsetWidth属性
let offsetWidth = $ele('.offsetWidth');
$log('offsetWidth的值是:' + offsetWidth.offsetWidth);

Вывод консоли выглядит следующим образом:

offsetWidth的值是:134

Это значение определяется элементомwidthстоимость,paddingценность иborderЗначения складываются вместе, т.100 + 8 x 2 + 9 x 2 = 134. соответствующийoffsetHeightТо же самое верно и для стоимости, которая здесь не демонстрируется. Далее мы будем изучатьscrollXСоответствующие свойства, прежде всегоscrollLeftилиscrollTopАтрибуты, эти два атрибута подходят для скольжения внутри элемента, давайте проверимscrollLeftАтрибуты. Часть HTML выглядит следующим образом:

<div class="scrollLeft">这是scrollLeft,永远都不要放弃你的梦想</div>

Часть CSS выглядит следующим образом:

.scrollLeft {
    width: 100px;
    height: 100px;
    margin-top: 15px;
    white-space: nowrap;
    overflow: scroll;
    border: 3px solid  black;
}

Часть JavaScript выглядит следующим образом:

// 测试scrollLeft属性
let scrollLeft = $ele('.scrollLeft');
$log('scrollLeft的值是:' + scrollLeft.scrollLeft);
// 修改scrollLeft的值
scrollLeft.scrollLeft = 10;
$log('scrollLeft的值是:' + scrollLeft.scrollLeft);

Мы можем увидеть вывод консоли следующим образом:

scrollLeft的值是:0
scrollLeft的值是:10

В начале, поскольку содержимое не скользит, начальное значение равно0, но когда мы меняемscrollLeftПри значении , мы обнаружим, что содержимое внутри перемещается влево, аscrollLeftЗначение также становится значением, которое мы изменили. потому чтоscrollTopа такжеscrollLeftПодобные и здесь демонстрироваться не будут. Далее будем учитьсяscrollWidthа такжеscrollHeightсвойства; так как эти два свойства похожи, мы будем тестировать только ихscrollWidthАтрибуты. Мы продолжаем приведенный выше пример для тестирования. Часть JavaScript выглядит следующим образом:

// 测试scrollWidth属性的值
$log('scrollWidth的值是:' + scrollLeft.scrollWidth);

Мы увидим следующий вывод из консоли:

scrollWidth的值是:294

Поскольку сам наш элемент имеет ширину всего100 + 3 x 2 = 106, Но в консоли есть вывод294, тут пояснить, если содержимое внутри элемента не превышает ширину элемента, тоscrollWidthзначение этого элементаclientWidthШирина; если она превышает ширину элемента, то ширина самого содержимого элемента.До сих пор мы в основном объясняли атрибуты, связанные с размером элемента, но следует отметить, что из-за разных реализаций операционных систем и браузеров одно и то же значение атрибута элемента может быть другим.Есть также некоторые моменты внимания, я перечислил их в таблице ниже, давайте посмотрим:

Атрибуты прочти и напиши Это целое число
clientLeft только чтение округлый (округлый)
clientTop только чтение округлый (округлый)
clientWidth только чтение округлый (округлый)
clientHeight только чтение округлый (округлый)
offsetLeft только чтение округлый (округлый)
offsetTop только чтение округлый (округлый)
offsetWidth только чтение округлый (округлый)
offsetHeight только чтение округлый (округлый)
scrollLeft прочти и напиши округлый (округлый)
scrollTop прочти и напиши округлый (округлый)
scrollWidth только чтение округлый (округлый)
scrollHeight только чтение округлый (округлый)

Онлайн-примеры статей можно найти по адресуздесьпросмотреть или просмотретьисходный код; Если вы считаете, что есть проблема с объяснением, пожалуйста, оставьте сообщение ниже; давайте обсудим это вместе.