Позиционирование блока по центру с учетом скрола
Дата публикации: 17.06.2010
Задача
Спозиционировать блок по центру (вертикально и горизонтально).
Требования
- учет размера самого блока;
- учет прокрутки окна;
- без использования js-библиотек.
Решение
На самом деле, все было бы не так тяжко, если бы нынешние браузеры (в частности ИЕ) следовали одним стандартам. Но, благо, это решаемо. Итак, алгоритм довольно прост:
- Просчитать размер «рабочей области» (размер окна) с учетом размеров всяких панелей и баров
- При необходимости (в случае, если наш блок «резиновый») снять с него «мерки»
- Составить формулу позиционирования и «приклеить» наш блок в нужное место
К примеру имеем такой блок:
<h1>По клику блок выровняется.</h1> <h2>Можно проскролить и кликнуть где-нибудь внизу.</h2> <div id="testBlock"></div>
…и такой CSS (само собой блок должен быть с абсолютным позиционированием):
html {
height: 100%;
}
body {
height: 100%;
}
.wrap {
text-align: center;
height: 3000px; /* зададим большую высоту, чтоб появился вертикальный скролл - нужно для теста */
}
#testBlock {
position: absolute;
top: 150px;
left: 0;
width: 500px;
height: 500px;
color: #fff;
background: #090;
}
Заметка
ИЕ снова показал, что он не такой как все, правда на этот раз к 6-му примкнул и 8-й. Они по разному (не только относительно других браузеров, но и относительно друг друга) реагируют на высоту html и body. Чтобы было все тип-топ, необходим элемент (обычно это div), который растянет body и html как минимум на 100% высоты экрана.
И так, сам скрипт:
window.onload = function(){
var wsize = windowWorkSize(), // размеры "рабочей области"
testElem = document.getElementById("testBlock"), // ложим наш блок в переменную
testElemWid = testElem.offsetWidth, // ширина блока
testElemHei = testElem.offsetHeight; // высота блока
window.document.onclick = function(){ // цетрируем по событию onclick
testElem.style.left = wsize[0]/2 - testElemWid/2 + "px"; // центрируем блок по горизонтали
testElem.style.top = wsize[1]/2 - testElemHei/2 + (document.body.scrollTop || document.documentElement.scrollTop) + "px"; // центрируем блок по вертикали + скролл
};
// фунция определения "рабочего пространства"
function windowWorkSize(){
var wwSize = new Array();
if (window.innerHeight !== undefined) wwSize= [window.innerWidth,window.innerHeight] // для основных браузеров
else
{ // для "особо одарённых" (ИЕ6-8)
wwSizeIE = (document.body.clientWidth) ? document.body : document.documentElement;
wwSize= [wwSizeIE.clientWidth, wwSizeIE.clientHeight];
};
return wwSize;
};
};
Результат. Проверено в:
Вобщем-то весь фокус в функции windowWorkSize(), которая и вычисляет кроссбраузерно высоту и ширину окна. Результат возвращает в виде массива из двух элементов, где элемент[0] — ширина окна, элемент[1] — высота. Дальше остается только прописать формулы для размещения в этой области блока.
Заметки
- ИЕ6-8 не знают, что такое window.innerWidth⁄innerHeight, зато понимают document.body.clientWidth⁄clientHeight.
Обе конструкции возвращают размеры «рабочего окна», под этим определением следует понимать: размер окна = размер экрана — размер панелей
- (document.body.clientWidth) ? document.body : document.documentElement. Зачем такая «мудрёная» конструкция?
Все дело в quirks mode. В этом режиме ИЕ использует не document.body, а document.documentElement для определения высоты скролла. В целом, если не рассчитывать на quirks mode, условие для ИЕ можно сократить до одной строчки: wwSize= [document.body.clientWidth, document.body.clientHeight];
- В формуле просчета координат присутствует конструкция (document.body.scrollTop || document.documentElement.scrollTop).
Её следует использовать если позиционирование происходит с учётом скролла. Конструкция возвращает кол-во пикселей, на которое прокручен скролл и имеет такой вид по следующей причине:
- document.documentElement.scrollTop — понимают IE7-8, Opera, Firefox
- document.body.scrollTop — понимают Chrome, Safari, IE6(ух, возомнил себе!)
