Я хотел бы создать div, который расположен под блоком содержимого, но который после того, как страница прокручена достаточно, чтобы коснуться ее верхней границы, фиксируется на месте и прокручивается вместе со страницей.
Как я могу сделать div-стик в верхней части экрана после его прокрутки?
Ответы (21)
Вы можете использовать просто css, позиционируя свой элемент как фиксированный:
.fixedElement {
background-color: #c0c0c0;
position:fixed;
top:0;
width:100%;
z-index:100;
}
Изменить: у вас должен быть элемент с абсолютной позицией, как только смещение прокрутки достигнет элемента, его следует изменить на фиксированное, а верхнее положение должно быть установлено на ноль.
Вы можете определить смещение верхней прокрутки документа с помощью функции scrollTop:
$(window).scroll(function(e){
var $el = $('.fixedElement');
var isPositionFixed = ($el.css('position') == 'fixed');
if ($(this).scrollTop() > 200 && !isPositionFixed){
$el.css({'position': 'fixed', 'top': '0px'});
}
if ($(this).scrollTop() < 200 && isPositionFixed){
$el.css({'position': 'static', 'top': '0px'});
}
});
Когда смещение прокрутки достигнет 200, элемент будет придерживаться в верхней части окна браузера, потому что он размещен как фиксированный.
if ($(this).scrollTop() < 200 && $el.css('position') == 'fixed') { $('.fixedElement').css({'position': 'static', 'top': '0px'}); }
- person Derrick Petzold; 09.03.2012
new example
ссылка, которую вы дали, настолько чиста и ясна, что я даже не могу ее увидеть! -_-
- person sohaiby; 14.05.2015
Вы видели этот пример на странице проблем Google Code и ( только недавно) на странице редактирования Stack Overflow.
Ответ CMS не меняет положение при прокрутке вверх. Вот бессовестно украденный код из Stack Overflow:
function moveScroller() {
var $anchor = $("#scroller-anchor");
var $scroller = $('#scroller');
var move = function() {
var st = $(window).scrollTop();
var ot = $anchor.offset().top;
if(st > ot) {
$scroller.css({
position: "fixed",
top: "0px"
});
} else {
$scroller.css({
position: "relative",
top: ""
});
}
};
$(window).scroll(move);
move();
}
<div id="sidebar" style="width:270px;">
<div id="scroller-anchor"></div>
<div id="scroller" style="margin-top:10px; width:270px">
Scroller Scroller Scroller
</div>
</div>
<script type="text/javascript">
$(function() {
moveScroller();
});
</script>
И простая живая демонстрация.
Новой альтернативой без скриптов является position: sticky
, которая поддерживается в Chrome, Firefox и Safari. См. статью о HTML5Rocks и демо и Документы Mozilla.
offset
, должно быть, прекратил принимать объект в качестве входных данных api.jquery.com/offset. @Eddie Ваша модификация должна быть безопасной с текущим jQuery.
- person Graeme; 14.12.2011
var d = $("#scroller-anchor").offset().top;
на var d = $("#sidebar").offset().top;
и полностью избавиться от пустого div-скроллера с привязкой? Вот моя вилка, демонстрирующая то, о чем я говорю.
- person Mike Deck; 27.01.2012
По состоянию на январь 2017 года и выпуск Chrome 56 большинство широко используемых браузеров поддерживают свойство position: sticky
в CSS.
#thing_to_stick {
position: sticky;
top: 0px;
}
помогает мне в Firefox и Chrome.
В Safari по-прежнему нужно использовать position: -webkit-sticky
.
Полифиллы доступны для Internet Explorer и Edge; https://github.com/wilddeer/stickyfill кажется хорошим вариантом.
px
не сработала для меня и заставила меня думать, что липкий просто не работает. Это должно быть просто top: 0;
- person Akaisteph7; 03.04.2021
У меня была та же проблема, что и у вас, и в итоге я создал плагин jQuery, чтобы решить эту проблему. Он фактически решает все проблемы, перечисленные здесь, а также добавляет пару дополнительных функций.
Параметры
stickyPanelSettings = {
// Use this to set the top margin of the detached panel.
topPadding: 0,
// This class is applied when the panel detaches.
afterDetachCSSClass: "",
// When set to true the space where the panel was is kept open.
savePanelSpace: false,
// Event fires when panel is detached
// function(detachedPanel, panelSpacer){....}
onDetached: null,
// Event fires when panel is reattached
// function(detachedPanel){....}
onReAttached: null,
// Set this using any valid jquery selector to
// set the parent of the sticky panel.
// If set to null then the window object will be used.
parentSelector: null
};
https://github.com/donnyv/sticky-panel
демонстрация: http://htmlpreview.github.io/?https://github.com/donnyv/sticky-panel/blob/master/jquery.stickyPanel/Main.htm
И вот как без jquery (ОБНОВЛЕНИЕ: см. Другие ответы, где теперь вы можете сделать это только с помощью CSS)
var startProductBarPos=-1;
window.onscroll=function(){
var bar = document.getElementById('nav');
if(startProductBarPos<0)startProductBarPos=findPosY(bar);
if(pageYOffset>startProductBarPos){
bar.style.position='fixed';
bar.style.top=0;
}else{
bar.style.position='relative';
}
};
function findPosY(obj) {
var curtop = 0;
if (typeof (obj.offsetParent) != 'undefined' && obj.offsetParent) {
while (obj.offsetParent) {
curtop += obj.offsetTop;
obj = obj.offsetParent;
}
curtop += obj.offsetTop;
}
else if (obj.y)
curtop += obj.y;
return curtop;
}
* {margin:0;padding:0;}
.nav {
border: 1px red dashed;
background: #00ffff;
text-align:center;
padding: 21px 0;
margin: 0 auto;
z-index:10;
width:100%;
left:0;
right:0;
}
.header {
text-align:center;
padding: 65px 0;
border: 1px red dashed;
}
.content {
padding: 500px 0;
text-align:center;
border: 1px red dashed;
}
.footer {
padding: 100px 0;
text-align:center;
background: #777;
border: 1px red dashed;
}
<header class="header">This is a Header</header>
<div id="nav" class="nav">Main Navigation</div>
<div class="content">Hello World!</div>
<footer class="footer">This is a Footer</footer>
Вот как я сделал это с помощью jquery. Все это было собрано из различных ответов о переполнении стека. Это решение кэширует селекторы для повышения производительности, а также решает проблему «прыжков», когда липкий div становится липким.
Проверьте это на jsfiddle: http://jsfiddle.net/HQS8s/
CSS:
.stick {
position: fixed;
top: 0;
}
JS:
$(document).ready(function() {
// Cache selectors for faster performance.
var $window = $(window),
$mainMenuBar = $('#mainMenuBar'),
$mainMenuBarAnchor = $('#mainMenuBarAnchor');
// Run this on scroll events.
$window.scroll(function() {
var window_top = $window.scrollTop();
var div_top = $mainMenuBarAnchor.offset().top;
if (window_top > div_top) {
// Make the div sticky.
$mainMenuBar.addClass('stick');
$mainMenuBarAnchor.height($mainMenuBar.height());
}
else {
// Unstick the div.
$mainMenuBar.removeClass('stick');
$mainMenuBarAnchor.height(0);
}
});
});
Вот еще один вариант:
JAVASCRIPT
var initTopPosition= $('#myElementToStick').offset().top;
$(window).scroll(function(){
if($(window).scrollTop() > initTopPosition)
$('#myElementToStick').css({'position':'fixed','top':'0px'});
else
$('#myElementToStick').css({'position':'absolute','top':initTopPosition+'px'});
});
Ваш #myElementToStick
должен начинаться со свойства position:absolute
CSS.
Как Джош Ли и Colin 't Hart сказал, что при желании вы можете просто использовать position: sticky; top: 0;
применительно к div, в котором вы хотите прокрутить ...
Кроме того, единственное, что вам нужно сделать, это скопировать это в верхнюю часть страницы или отформатировать так, чтобы оно соответствовало внешнему листу CSS:
<style>
#sticky_div's_name_here { position: sticky; top: 0; }
</style>
Просто замените #sticky_div's_name_here
именем вашего div, т.е. если ваш div был <div id="example">
, вы бы поместили #example { position: sticky; top: 0; }
.
Мое решение немного подробное, но оно обрабатывает переменное позиционирование от левого края для центрированных макетов.
// Ensurs that a element (usually a div) stays on the screen
// aElementToStick = The jQuery selector for the element to keep visible
global.makeSticky = function (aElementToStick) {
var $elementToStick = $(aElementToStick);
var top = $elementToStick.offset().top;
var origPosition = $elementToStick.css('position');
function positionFloater(a$Win) {
// Set the original position to allow the browser to adjust the horizontal position
$elementToStick.css('position', origPosition);
// Test how far down the page is scrolled
var scrollTop = a$Win.scrollTop();
// If the page is scrolled passed the top of the element make it stick to the top of the screen
if (top < scrollTop) {
// Get the horizontal position
var left = $elementToStick.offset().left;
// Set the positioning as fixed to hold it's position
$elementToStick.css('position', 'fixed');
// Reuse the horizontal positioning
$elementToStick.css('left', left);
// Hold the element at the top of the screen
$elementToStick.css('top', 0);
}
}
// Perform initial positioning
positionFloater($(window));
// Reposition when the window resizes
$(window).resize(function (e) {
positionFloater($(this));
});
// Reposition when the window scrolls
$(window).scroll(function (e) {
positionFloater($(this));
});
};
Вот еще одна версия для тех, у кого проблемы с другими. Он объединяет методы, описанные в этот повторяющийся вопрос и динамически генерирует необходимые вспомогательные DIV, поэтому дополнительный HTML-код не требуется.
CSS:
.sticky { position:fixed; top:0; }
JQuery:
function make_sticky(id) {
var e = $(id);
var w = $(window);
$('<div/>').insertBefore(id);
$('<div/>').hide().css('height',e.outerHeight()).insertAfter(id);
var n = e.next();
var p = e.prev();
function sticky_relocate() {
var window_top = w.scrollTop();
var div_top = p.offset().top;
if (window_top > div_top) {
e.addClass('sticky');
n.show();
} else {
e.removeClass('sticky');
n.hide();
}
}
w.scroll(sticky_relocate);
sticky_relocate();
}
Чтобы сделать элемент липким, выполните:
make_sticky('#sticky-elem-id');
Когда элемент становится липким, код управляет положением оставшегося содержимого, чтобы он не прыгнул в промежуток, оставленный липким элементом. Он также возвращает липкий элемент в исходное положение без липкости при прокрутке назад над ним.
Вот расширенная версия ответа Джоша Ли. Если вы хотите, чтобы div находился на боковой панели справа и плавал в пределах диапазона (т.е. вам нужно указать верхнюю и нижнюю позиции привязки). Он также исправляет ошибку, когда вы просматриваете это на мобильных устройствах (вам нужно проверить левую позицию прокрутки, иначе div переместится за пределы экрана).
function moveScroller() {
var move = function() {
var st = $(window).scrollTop();
var sl = $(window).scrollLeft();
var ot = $("#scroller-anchor-top").offset().top;
var ol = $("#scroller-anchor-top").offset().left;
var bt = $("#scroller-anchor-bottom").offset().top;
var s = $("#scroller");
if(st > ot) {
if (st < bt - 280) //280px is the approx. height for the sticky div
{
s.css({
position: "fixed",
top: "0px",
left: ol-sl
});
}
else
{
s.css({
position: "fixed",
top: bt-st-280,
left: ol-sl
});
}
} else {
s.css({
position: "relative",
top: "",
left: ""
});
}
};
$(window).scroll(move);
move();
}
Не точное решение, но отличная альтернатива, которую стоит рассмотреть
это ТОЛЬКО CSS полоса прокрутки в верхней части экрана. Решены все проблемы с помощью ТОЛЬКО CSS, НЕТ JavaScript, НЕТ JQuery, Нет работы мозга (lol ).
Наслаждайтесь моей скрипкой: D все коды включены туда :)
CSS
#menu {
position: fixed;
height: 60px;
width: 100%;
top: 0;
left: 0;
border-top: 5px solid #a1cb2f;
background: #fff;
-moz-box-shadow: 0 2px 3px 0px rgba(0, 0, 0, 0.16);
-webkit-box-shadow: 0 2px 3px 0px rgba(0, 0, 0, 0.16);
box-shadow: 0 2px 3px 0px rgba(0, 0, 0, 0.16);
z-index: 999999;
}
.w {
width: 900px;
margin: 0 auto;
margin-bottom: 40px;
}<br type="_moz">
Поместите контент достаточно долго, чтобы вы могли увидеть здесь эффект :) Да, и ссылка там тоже, потому что он заслуживает его кредит
ТОЛЬКО CSS Полоса прокрутки в верхней части экрана
Я столкнулся с этим, когда искал то же самое. Я знаю, что это старый вопрос, но я подумал, что предложу более свежий ответ.
В Scrollorama есть функция «закрепить», которую я как раз искал.
http://johnpolacek.github.io/scrollorama/
Информация, предоставленная для ответа на этот другой вопрос, может быть вам полезна, Эван:
Проверить, отображается ли элемент после прокрутки
В основном вы хотите изменить стиль элемента, чтобы установить его как фиксированный, только после проверки того, что значение document.body.scrollTop равно или больше, чем верхняя часть вашего элемента.
Принятый ответ работает, но не возвращается в предыдущую позицию, если вы прокрутите его вверх. После размещения он всегда приклеивается кверху.
$(window).scroll(function(e) {
$el = $('.fixedElement');
if ($(this).scrollTop() > 42 && $el.css('position') != 'fixed') {
$('.fixedElement').css( 'position': 'fixed', 'top': '0px');
} else if ($(this).scrollTop() < 42 && $el.css('position') != 'relative') {
$('.fixedElement').css( 'relative': 'fixed', 'top': '42px');
//this was just my previous position/formating
}
});
Ответ jleedev должен сработать, но мне не удалось заставить его работать. Его примерная страница также не сработала (для меня).
Вы можете добавить 3 дополнительные строки, чтобы, когда пользователь вернется наверх, div останется на своем старом месте:
Вот код:
if ($(this).scrollTop() < 200 && $el.css('position') == 'fixed'){
$('.fixedElement').css({'position': 'relative', 'top': '200px'});
}
У меня есть настройки ссылок в div, поэтому это вертикальный список букв и цифр.
#links {
float:left;
font-size:9pt;
margin-left:0.5em;
margin-right:1em;
position:fixed;
text-align:center;
width:0.8em;
}
Затем я настраиваю эту удобную функцию jQuery для сохранения загруженной позиции, а затем меняю положение на фиксированное при прокрутке за пределы этой позиции.
ПРИМЕЧАНИЕ: это работает, только если ссылки видны при загрузке страницы !!
var listposition=false;
jQuery(function(){
try{
///// stick the list links to top of page when scrolling
listposition = jQuery('#links').css({'position': 'static', 'top': '0px'}).position();
console.log(listposition);
$(window).scroll(function(e){
$top = $(this).scrollTop();
$el = jQuery('#links');
//if(typeof(console)!='undefined'){
// console.log(listposition.top,$top);
//}
if ($top > listposition.top && $el.css('position') != 'fixed'){
$el.css({'position': 'fixed', 'top': '0px'});
}
else if ($top < listposition.top && $el.css('position') == 'fixed'){
$el.css({'position': 'static'});
}
});
} catch(e) {
alert('Please vendor [email protected] (Myvendor JavaScript Issue)');
}
});
В javascript вы можете:
var element = document.getElementById("myid");
element.style.position = "fixed";
element.style.top = "0%";
Вот пример, в котором используется плагин, видимый в jquery: http://jsfiddle.net/711p4em4/.
HTML:
<div class = "wrapper">
<header>Header</header>
<main>
<nav>Stick to top</nav>
Content
</main>
<footer>Footer</footer>
</div>
CSS:
* {
margin: 0;
padding: 0;
}
body {
background-color: #e2e2e2;
}
.wrapper > header,
.wrapper > footer {
font: 20px/2 Sans-Serif;
text-align: center;
background-color: #0040FF;
color: #fff;
}
.wrapper > main {
position: relative;
height: 500px;
background-color: #5e5e5e;
font: 20px/500px Sans-Serif;
color: #fff;
text-align: center;
padding-top: 40px;
}
.wrapper > main > nav {
position: absolute;
top: 0;
left: 0;
right: 0;
font: 20px/2 Sans-Serif;
color: #fff;
text-align: center;
background-color: #FFBF00;
}
.wrapper > main > nav.fixed {
position: fixed;
top: 0;
left: 0;
right: 0;
}
JS (включая плагин jquery-visible):
(function($){
/**
* Copyright 2012, Digital Fusion
* Licensed under the MIT license.
* http://teamdf.com/jquery-plugins/license/
*
* @author Sam Sehnert
* @desc A small plugin that checks whether elements are within
* the user visible viewport of a web browser.
* only accounts for vertical position, not horizontal.
*/
var $w = $(window);
$.fn.visible = function(partial,hidden,direction){
if (this.length < 1)
return;
var $t = this.length > 1 ? this.eq(0) : this,
t = $t.get(0),
vpWidth = $w.width(),
vpHeight = $w.height(),
direction = (direction) ? direction : 'both',
clientSize = hidden === true ? t.offsetWidth * t.offsetHeight : true;
if (typeof t.getBoundingClientRect === 'function'){
// Use this native browser method, if available.
var rec = t.getBoundingClientRect(),
tViz = rec.top >= 0 && rec.top < vpHeight,
bViz = rec.bottom > 0 && rec.bottom <= vpHeight,
lViz = rec.left >= 0 && rec.left < vpWidth,
rViz = rec.right > 0 && rec.right <= vpWidth,
vVisible = partial ? tViz || bViz : tViz && bViz,
hVisible = partial ? lViz || rViz : lViz && rViz;
if(direction === 'both')
return clientSize && vVisible && hVisible;
else if(direction === 'vertical')
return clientSize && vVisible;
else if(direction === 'horizontal')
return clientSize && hVisible;
} else {
var viewTop = $w.scrollTop(),
viewBottom = viewTop + vpHeight,
viewLeft = $w.scrollLeft(),
viewRight = viewLeft + vpWidth,
offset = $t.offset(),
_top = offset.top,
_bottom = _top + $t.height(),
_left = offset.left,
_right = _left + $t.width(),
compareTop = partial === true ? _bottom : _top,
compareBottom = partial === true ? _top : _bottom,
compareLeft = partial === true ? _right : _left,
compareRight = partial === true ? _left : _right;
if(direction === 'both')
return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop)) && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
else if(direction === 'vertical')
return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop));
else if(direction === 'horizontal')
return !!clientSize && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
}
};
})(jQuery);
$(function() {
$(window).scroll(function() {
$(".wrapper > header").visible(true) ?
$(".wrapper > main > nav").removeClass("fixed") :
$(".wrapper > main > nav").addClass("fixed");
});
});
Я использовал некоторые из вышеперечисленных работ, чтобы создать эту технологию. Я немного улучшил его и подумал, что поделюсь своей работой. Надеюсь это поможет.
function scrollErrorMessageToTop() {
var flash_error = jQuery('#flash_error');
var flash_position = flash_error.position();
function lockErrorMessageToTop() {
var place_holder = jQuery("#place_holder");
if (jQuery(this).scrollTop() > flash_position.top && flash_error.attr("position") != "fixed") {
flash_error.css({
'position': 'fixed',
'top': "0px",
"width": flash_error.width(),
"z-index": "1"
});
place_holder.css("display", "");
} else {
flash_error.css('position', '');
place_holder.css("display", "none");
}
}
if (flash_error.length > 0) {
lockErrorMessageToTop();
jQuery("#flash_error").after(jQuery("<div id='place_holder'>"));
var place_holder = jQuery("#place_holder");
place_holder.css({
"height": flash_error.height(),
"display": "none"
});
jQuery(window).scroll(function(e) {
lockErrorMessageToTop();
});
}
}
scrollErrorMessageToTop();
Это немного более динамичный способ прокрутки. Это действительно требует некоторой работы, и в какой-то момент я превращу это в подключаемый модуль, но это то, что я придумал после часа работы.
липкий, пока нижний колонтитул не попадет в div:
function stickyCostSummary() {
var stickySummary = $('.sticky-cost-summary');
var scrollCostSummaryDivPosition = $(window).scrollTop();
var footerHeight = $('#footer').height();
var documentHeight = $(document).height();
var costSummaryHeight = stickySummary.height();
var headerHeight = 83;
var footerMargin = 10;
var scrollHeight = 252;
var footerPosition = $('#footer').offset().top;
if (scrollCostSummaryDivPosition > scrollHeight && scrollCostSummaryDivPosition <= (documentHeight - footerHeight - costSummaryHeight - headerHeight - footerMargin)) {
stickySummary.removeAttr('style');
stickySummary.addClass('fixed');
} else if (scrollCostSummaryDivPosition > (documentHeight - footerHeight - costSummaryHeight - headerHeight - footerMargin)) {
stickySummary.removeClass('fixed');
stickySummary.css({
"position" : "absolute",
"top" : (documentHeight - footerHeight - costSummaryHeight - headerHeight - footerMargin - scrollHeight) + "px"
});
} else {
stickySummary.removeClass('fixed');
stickySummary.css({
"position" : "absolute",
"top" : "0"
});
}
}
$window.scroll(stickyCostSummary);
position: sticky; top:0;
работает в большинстве браузеров в январе 2017 года. - person Colin 't Hart   schedule 23.01.2017position: sticky;
вещь волшебная. - person tscizzle   schedule 30.06.2017