Как получить динамические значения смещения данных для метода ассемблера Bootstrap 3
Я хотел бы использовать метод Affix, описанный в документации Bootstraps (http://getbootstrap.com/javascript/#affix), однако навигационная панель, которую я хотел бы установить на начало страницы после прокрутки к ней может иметь разные значения смещения в зависимости от содержимого над ним.
Вот пример навигатора:
<div class="navbar navbar-default" data-spy="affix" data-offset-top="200">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link</a></li>
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
</ul>
</div>
Как вы можете видеть, data-offset-top
в настоящее время установлен в 200. Это работает отлично, если содержание выше 200px высотой, но содержимое выше динамическое, и поэтому высота над этой навигационной панелью не всегда одинакова. Как я могу сделать vale для data-offset-top
динамическим?
Я предполагаю, что мне нужно будет использовать способ javascript, но я уверен.
Ответы
Ответ 1
Вы можете использовать jQuery для получения высоты динамического содержимого над navbar
. Например:
$('#nav').affix({
offset: {
top: $('header').height()
}
});
Рабочая демонстрация: http://bootply.com/69848
В некоторых случаях, offset.bottom также должен быть рассчитан, чтобы определить, когда "un-affix" элемент. Вот пример аффикс-дна
Ответ 2
Я был абсолютно расстроен тем, как это работает, каждый раз выполняя некоторые пользовательские вычисления и создавая смещение от высот элементов выше желаемого аффикса.
Здесь лучше всего прикрепите к нему.
Нормальный аффикс boostrap не учитывает позиции естественного смещения сверху, вы должны вручную передать его в качестве атрибута. Это позаботится об этом и учитывает изменение верхней границы смещения при изменении размера окна.
var $attribute = $('[data-smart-affix]');
$attribute.each(function(){
$(this).affix({
offset: {
top: $(this).offset().top,
}
})
})
$(window).on("resize", function(){
$attribute.each(function(){
$(this).data('bs.affix').options.offset = $(this).offset().top
})
})
Я также разместил это на обзоре кода.
Ответ 3
Данные ThomasReggi-smart-affix не работали для меня в некоторых случаях (при изменении размера документа или когда столбец с надписью был слишком высоким). Но это дало мне простую идею: добавьте пустой элемент перед прикрепленным контентом и используйте его для получения смещения. Хорошо работает при изменении размера.
Пока я был на нем, я также устанавливал ширину элемента как естественную ширину в исходном родителе. Здесь мое решение:
$('[data-affix-after]').each( function() {
var elem = $(this);
var parent_panel = elem.parent();
var prev = $( elem.data('affix-after') );
if( prev.length != 1 ) {
/* Create a new element immediately before. */
prev = elem.before( '<div></div>' ).prev();
}
var resizeFn = function() {
/* Set the width to it natural width in the parent. */
var sideBarNavWidth = parent_panel.width()
- parseInt(elem.css('paddingLeft'))
- parseInt(elem.css('paddingRight'))
- parseInt(elem.css('marginLeft'))
- parseInt(elem.css('marginRight'))
- parseInt(elem.css('borderLeftWidth'))
- parseInt(elem.css('borderRightWidth'));
elem.css('width', sideBarNavWidth);
elem.affix({
offset: {
top: prev.offset().top + prev.outerHeight(true),
bottom: $('body>footer').outerHeight(true)
}
});
};
resizeFn();
$(window).resize(resizeFn);
});
HTML, который идет с ним:
<div id='before-affix'></div><!-- leave this empty -->
<div data-affix-after='#before-affix'>
Put content to affix here.
</div>
или
<div data-affix-after='#create'><!-- any ID that doesn't exist -->
Put content to affix here.
</div>
Необходимый CSS:
.affix { top: 0px },
.affix-bottom { position: absolute; }
Если вы хотите отключить аффикс (например, при выравнивании нужного столбца), используйте CSS:
.affix, .affix-bottom { position: static; }
внутри соответствующего медиа-запроса.
GI
Ответ 4
Я предлагаю вам добавить обертку вокруг прикрепленного div - чтобы избежать "прокрутки" с прикрепленным навигатором. Томас опубликовал хорошее решение, но он не содержит затухающего пространства после аффикса, и он не работает в версии 2.x boostrap, которую я должен использовать. Поэтому я решил написать совершенно новую реализацию аффикса. Он не нужен boostrap, просто jquery. Это мой первый javascript, поэтому, пожалуйста, помилуй:), но, возможно, это поможет кому-то. Всегда приятно иметь решение без бутстрапа
function myaffix() {
var affixoffset = $('.navbar').offset().top
$('#nav-wrapper').height($(".navbar").height());
$(window).scroll(function () {
if ($(window).scrollTop() <= affixoffset) {
$('.navbar').removeClass('affix');
} else {
$('.navbar').addClass('affix');
}
});
};
$(document).ready(function () {
myaffix();
$(window).on("resize", function () {
myaffix();
});
});
Здесь вы можете найти пример:
http://jsfiddle.net/3ss7fk92/
Ответ 5
Скелли выше правильно, и нет лучшего способа сделать это. Единственное возможное решение с "родным" бутстрапом - это присоединение параметров аффикса с вызовом JavaScript (как упоминалось выше в fooobar.com/questions/218471/...).
В особенности не можно использовать атрибут data-offset
для достижения такого же эффекта (даже если это было бы намного удобнее, и даже если документация для Affix at http://getbootstrap.com/2.3.2/javascript.html#affix повышает надежду, что можно это сделать).
Таким образом, можно написать
data-offset='{"top":42}'
но один не разрешен для записи, например:
data-offset='{"top":$("#banner").height()}'
Причина в том, что атрибуты данных анализируются с помощью API JQuery .data()
, который позволяет анализировать только чистые значения JSON, см. https://api.jquery.com/data/.
Ответ 6
Thnx ThomasReggi за идею. Но может быть правильнее написать:
$(this).data('bs.affix').options.offset.top = $(this).offset().top
для таких, как я, которым также нужно было нижнее значение, которое будет писать аналогично.
Кстати, я думаю, что оберните его в декораторе на основе setTimeout (несколько как debounce).
Ответ 7
У меня были проблемы с этим раньше, и по какой-то причине я не мог получить ни одно из решений, которые другие люди предлагали работать. Я относительно новичок в Bootstrap и JQuery, поэтому я, вероятно, делал что-то неуловимое, которого я не ловил. Независимо от того, я нашел решение, которое работает очень хорошо, хотя он строго использует функциональность аффикса, как предполагает Bootstrap. Я сохранил свой #thisElement.affix {top: desiredFixedPosition;}
CSS неповрежденным, но избавился от атрибутов data-spy
и data-offset-top
от тега #thisElement HTML. Я тогда жестко закодировал это в JQuery:
var newAffix = function() {
if($("otherElementsAboveThisElement").height() <= $(window).scrollTop()) {
$("#thisElement").addClass("affix");
} else {
$("#thisElement").removeClass("affix");
}
}
$(document).ready(function() {
$(window).resize(newAffix);
$(window).scroll(newAffix);
}
Насколько я тестировал, это работает независимо от того, насколько сильно вы изменяете размер страницы или прокручиваете, и если вы сориентируетесь с тем, как вы называете ее в функции $(document).ready()
, вы можете даже оставить меню в правильном порядке положение во время анимации высоты. Как уже было сказано, это технически не полностью "одобренное Bootstrap" решение, но оно достаточно хорошо интегрируется в сайт Bootstrap, что он должен работать для некоторых:)