Часто бывает: запись длиннее сайтбара (при том что там несколько виджетов). В этом случае можно сделать фиксирование сайтбара.
Скрипт (с условием, что существует div id=aside)
В начале скрипта (выделено жирным) можно выставить верхний и нижний отступы фиксирования.
if($("div").is("#aside")) {
(function(){
var a = document.querySelector('#aside'), b = null, K = null, Z = 0, P = 60, N = 60; // если у P ноль заменить на число, то блок будет прилипать до того, как верхний край окна браузера дойдёт до верхнего края элемента, если у N — нижний край дойдёт до нижнего края элемента. Может быть отрицательным числом
window.addEventListener('scroll', Ascroll, false);
function Ascroll() {
var Ra = a.getBoundingClientRect(),
R1bottom = document.querySelector('#content').getBoundingClientRect().bottom;
if (Ra.bottom < R1bottom) {
if (b == null) {
var Sa = getComputedStyle(a, ''), s = '';
for (var i = 0; i < Sa.length; i++) {
if (Sa[i].indexOf('overflow') == 0 || Sa[i].indexOf('padding') == 0 || Sa[i].indexOf('border') == 0 || Sa[i].indexOf('outline') == 0 || Sa[i].indexOf('box-shadow') == 0 || Sa[i].indexOf('background') == 0) {
s += Sa[i] + ': ' +Sa.getPropertyValue(Sa[i]) + '; '
}
}
b = document.createElement('div');
b.className = "stop";
b.style.cssText = s + ' box-sizing: border-box; width: ' + a.offsetWidth + 'px;';
a.insertBefore(b, a.firstChild);
var l = a.childNodes.length;
for (var i = 1; i < l; i++) { b.appendChild(a.childNodes[1]); } } var Rb = b.getBoundingClientRect(), Rh = Ra.top + Rb.height, W = document.documentElement.clientHeight, R1 = Math.round(Rh - R1bottom), R2 = Math.round(Rh - W); if (Rb.height > W) {
if (Ra.top < K) { // скролл вниз if (R2 + N > R1) { // не дойти до низа
if (Rb.bottom - W + N <= 0) { // подцепиться
b.className = 'sticky';
b.style.top = W - Rb.height - N + 'px';
Z = N + Ra.top + Rb.height - W;
} else {
b.className = 'stop';
b.style.top = - Z + 'px';
}
} else {
b.className = 'stop';
b.style.top = - R1 +'px';
Z = R1;
}
} else { // скролл вверх
if (Ra.top - P < 0) { // не дойти до верха if (Rb.top - P >= 0) { // подцепиться
b.className = 'sticky';
b.style.top = P + 'px';
Z = Ra.top - P;
} else {
b.className = 'stop';
b.style.top = - Z + 'px';
}
} else {
b.className = '';
b.style.top = '';
Z = 0;
}
}
K = Ra.top;
} else {
if ((Ra.top - P) <= 0) {
if ((Ra.top - P) <= R1) {
b.className = 'stop';
b.style.top = - R1 +'px';
} else {
b.className = 'sticky';
b.style.top = P + 'px';
}
} else {
b.className = '';
b.style.top = '';
}
}
}
}
})()
}
Надо добавить в CSS два стиля
.sticky {position: fixed;}
.stop {position: relative;}
Верстка данного решения следующая: Общий div, внутри div id=»content» (мы его указываем в скрипте), и div id=»aside» (фиксируемый сайтбар).
<div class="box">
<div class="block-18 with-right-sidebar" id="content" >Контент</div>
<div class="block-6" id="aside"><?php get_sidebar(); ?></div>
</div>
Скрипт theia-sticky-sidebar
Нашел еще одно решение, работает более стабильно (даже если внутри есть элементы со свойством float:left).
Подключаем скрипт:
wp_enqueue_script( 'theia-sticky-sidebar', plugins_url('/theia-sticky-sidebar.js', __FILE__), array('jquery'), '1.0', true );
Инициируем и настраиваем функционал
jQuery(document).ready(function() {
jQuery('#content, #sidebar').theiaStickySidebar({
// Settings
additionalMarginTop: 60,
additionalMarginBottom: 30
});
});
#content, #sidebar — объекты на которые воздействует скрипт.
Подключение стилей не требуется. additionalMarginTop, additionalMarginBottom — отступы сверху и снизу в px.
Также можно сделать с карточкой товара woocommerce, если мы графически разделяем блоки #wrapper-wc-image и .entry-summary, просто добавив их далее через запятую.
Версия для планшета
Если в мобильной версии данный функционал не нужен, то с планшетами сложнее. При горизонтальной ориентации данный эффект нужен. Так что родной запрос wordpress wp_is_mobile не подойдет.
Вариант разделения запросов с мобильных устройств (с телефона/с планшета) с помощью плагина.
Возможные ошибки
В одном проекте почему под футером получалось пространство, пришлось экранировать сайтбар:
#sidebar {overflow: hidden !important;}