Скроллбар компенсатор.

Убираем смещение страницы влево.

Вопросы разработчиков (скорее верстальщиков), которые мне встречались, чаще всего звучали так: "Смещение контента при появлении скроллбара" или "Страница дёргается влево, когда появляется прокрутка" и так далее. Кто-то обращает на это внимание, кто-то игнорирует, но так как проблемка существует, а информацию по ней найти не всегда удается из-за небольшого спроса, я решил опубликовать свой вариант решения.

Скроллбар появляется, если контент не помещается в видимую область экрана. Ваш К.О. ;) Появляется он не за пределами нашего сайта, а отхватывая от него драгоценные пиксели. И тут всё очевидно. Проблема актуальна для сайтов с фиксированной шириной макета, отцентрированного по горизонтали. И выглядит это примерно так:

page_no_scrollbar page_has_scrollbar

Решение строится по такому плану: запаковываем всю разметку от <body> до </body> в обёртку, определяем наличие скроллбара, вычисляем ширину скроллбара (у разных браузеров, она может отличаться), и выставляем значение левого поля (padding-left) для обёртки равное ширине скроллбара, если таковой был обнаружен.
Пусть вас не смущает дополнительный элемент-обертка, т.к. он не нуждается в каких-то стилях, которые могут повлиять на вашу существующую разметку.

<body>
  <div id="page_wrapper"><!-- Элемент-обертка :: Begin -->
    <!-- Тут вся ваша существующая разметка -->
  </div><!-- Элемент-обертка :: End -->
</body>

Теперь перейдём к JS/jQuery

// Элемент-обертка
var pageWrapper = $('#page_wrapper');
// Функция для вычисления ширины скроллбара
function getScrollWidth(){
  var measure = $('<div />').css({
      width: 100,
      height: 100,
      overflowY: 'scroll',
      visibility: 'hidden'
    }).appendTo('body'),
      sw = measure.prop('offsetWidth') - measure.prop('clientWidth');
  measure.remove();    
  return sw;
}
// Собственно, сама функция компенсатора скролла
function scrollCompensation(){
  var d = document,
      rootEl = d.compatMode == 'BackCompat'? d.body : d.documentElement,
      hasScroll = rootEl.scrollHeight > rootEl.clientHeight,
      scrollW = getScrollWidth();
  pageWrapper.css('padding-left', (hasScroll ? scrollW : 0));
  return false;
}
// Вызываем функцию при загрузке, а так же, если размеры окна поменялись
$(window).on('load resize', scrollCompensation);

И не забываем оборачивать код в конструкцию DOM-Ready, если подключение расположено в теге <head> или до элементов, с которыми надо работать:

$(function(){
  // тут весь код jQuery
});

Использовать такой "костыль" или нет - дело, конечно же, индивидуальное. Сказать по правде, я не особо заморачиваюсь этим вопросом в своих личных проектах. Но всё меняется, если сайт пишется под заказ и такое желание изъявляет клиент. Поэтому, применять или нет - вопрос второй, а вот знать, что сайт можно избавить от влияния скроллбара, я думаю, что пригодится.

Incode Pro logo

1 комментарий

Гость 15.05.2015 17:02
Было у меня когда то такое. Искал решение но не нашел
Думаю, как в вконтакте ето реализовано, что и себе сделать. но так и не разобрался. Спасибо. Пригодиться
Ваш комментарий:
X