Como posso fazer um div ficar no topo da canvas depois de ter sido rolado para?

Eu gostaria de criar um div, que está situado abaixo de um bloco de conteúdo, mas que, uma vez que a página tenha sido rolada o suficiente para entrar em contato com seu limite superior, será fixada no lugar e rolará com a página. Eu sei que já vi pelo menos um exemplo disso on-line, mas não consigo me lembrar da vida de mim.

Alguma ideia?

Você poderia usar simplesmente css, posicionando seu elemento como fixo :

 .fixedElement { background-color: #c0c0c0; position:fixed; top:0; width:100%; z-index:100; } 

Edit: Você deve ter o elemento com posição absoluta, uma vez que o deslocamento de rolagem tenha atingido o elemento, ele deve ser alterado para fixo e a posição superior deve ser definida como zero.

Você pode detectar o deslocamento de rolagem superior do documento com a function scrollTop :

 $(window).scroll(function(e){ var $el = $('.fixedElement'); var isPositionFixed = ($el.css('position') == 'fixed'); if ($(this).scrollTop() > 200 && !isPositionFixed){ $('.fixedElement').css({'position': 'fixed', 'top': '0px'}); } if ($(this).scrollTop() < 200 && isPositionFixed) { $('.fixedElement').css({'position': 'static', 'top': '0px'}); } }); 

Quando o deslocamento de deslocamento atingir 200, o elemento ficará no topo da janela do navegador, porque é colocado como fixo.

Você viu esse exemplo na página de problemas do Google Code e (apenas recentemente) na página de edição do Stack Overflow.

A resposta do CMS não reverte o posicionamento quando você rola para cima. Aqui está o código descaradamente roubado do 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(); } 
   

E uma simples demonstração ao vivo .

Uma alternativa nascente, livre de scripts é a position: sticky , que é suportada no Chrome, Firefox e Safari. Veja o artigo sobre HTML5Rocks e demo e os documentos do Mozilla .

Eu tive o mesmo problema que você e acabei fazendo um plugin jQuery para cuidar disso. Na verdade, resolve todos os problemas listados aqui, além de adicionar alguns resources opcionais também.

Opções

 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

demonstração: http://htmlpreview.github.io/?https://github.com/donnyv/sticky-panel/blob/master/jquery.stickyPanel/Main.htm

A partir de janeiro de 2017 e com o lançamento do Chrome 56, a maioria dos navegadores em uso comum suporta a position: sticky property in CSS.

 #thing_to_stick { position: sticky; top: 0px; } 

faz o truque para mim no Firefox e no Chrome.

No Safari, você ainda precisa usar a position: -webkit-sticky .

Polyfills estão disponíveis para o Internet Explorer e Edge; https://github.com/wilddeer/stickyfill parece ser bom.

E aqui está como sem jquery (UPDATE: veja outras respostas onde você pode fazer isso apenas com 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; } 
 
This is a Header
Hello World!
This is a Footer

É assim que eu fiz com jquery. Tudo isso foi compilado a partir de várias respostas no estouro de pilha. Essa solução armazena em cache os seletores para um desempenho mais rápido e também resolve o problema de “saltar” quando o div pegajoso se torna pegajoso.

Confira no 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); } }); }); 

Aqui está outra opção:

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'}); }); 

Seu #myElementToStick deve começar com position:absolute CSS property.

Minha solução é um pouco detalhada, mas lida com posicionamento variável a partir da borda esquerda para layouts centralizados.

 // 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)); }); }; 

Aqui está mais uma versão para tentar aqueles com problemas com os outros. Ele reúne as técnicas discutidas nesta questão duplicada e gera as DIVs auxiliares necessárias dinamicamente, portanto, nenhum HTML extra é necessário.

CSS:

 .sticky { position:fixed; top:0; } 

JQuery:

 function make_sticky(id) { var e = $(id); var w = $(window); $('
').insertBefore(id); $('
').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(); }

Para tornar um elemento pegajoso, faça:

 make_sticky('#sticky-elem-id'); 

Quando o elemento fica pegajoso, o código gerencia a posição do conteúdo restante para impedir que ele salte na lacuna deixada pelo elemento adesivo. Ele também retorna o elemento adesivo à sua posição original não aderente ao rolar de volta acima dele.

Aqui está uma versão estendida para a resposta de Josh Lee. Se você quiser que o div esteja na barra lateral à direita e flutue dentro de um intervalo (ou seja, é necessário especificar as posições de âncora superior e inferior). Ele também corrige um bug quando você vê isso em dispositivos móveis (você precisa verificar a posição de rolagem para a esquerda, caso contrário, a div sairá da canvas).

 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(); } 

Eu me deparei com isso quando procurava a mesma coisa. Eu sei que é uma pergunta antiga, mas pensei em oferecer uma resposta mais recente.

O Scrollorama tem um recurso ‘pin it’ que é exatamente o que eu estava procurando.

http://johnpolacek.github.io/scrollorama/

Como Josh Lee e Colin ‘t Hart disseram, você poderia usar apenas position: sticky; top: 0; position: sticky; top: 0; aplicando para o div que você quer a rolagem em …

Além disso, a única coisa que você terá que fazer é copiar isso no topo da sua página ou formatá-lo para caber em uma folha CSS externa:

  

Apenas substitua #sticky_div's_name_here pelo nome da sua div, ou seja, se o seu div for

, coloque #example { position: sticky; top: 0; } #example { position: sticky; top: 0; } #example { position: sticky; top: 0; } .

As informações fornecidas para responder a esta outra pergunta podem ajudá-lo, Evan:

Verifique se o elemento é visível após a rolagem

Você basicamente quer modificar o estilo do elemento para defini-lo como fixo somente depois de ter verificado que o valor document.body.scrollTop é igual ou maior que o topo de seu elemento.

A resposta aceita funciona, mas não volta para a posição anterior se você rolar por cima dela. É sempre preso ao topo depois de ser colocado lá.

  $(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 } }); 

A resposta de Jleedev deveria funcionar, mas eu não consegui fazê-lo funcionar. Sua página de exemplo também não funcionou (para mim).

Você pode adicionar 3 linhas extras para que, quando o usuário rolar de volta ao topo, o div fique no lugar antigo:

Aqui está o código:

 if ($(this).scrollTop() < 200 && $el.css('position') == 'fixed'){ $('.fixedElement').css({'position': 'relative', 'top': '200px'}); } 

Eu tenho links de configuração em um div por isso é uma lista vertical de links de letras e números.

 #links { float:left; font-size:9pt; margin-left:0.5em; margin-right:1em; position:fixed; text-align:center; width:0.8em; } 

Em seguida, configuro essa function útil do jQuery para salvar a posição carregada e, em seguida, alterar a posição para fixa ao rolar para além dessa posição.

NOTA: isso só funciona se os links estiverem visíveis no carregamento da página !!

 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 admin@mydomain.com (Myvendor JavaScript Issue)'); } }); 

Eu usei alguns dos trabalhos acima para criar essa tecnologia. Eu melhorei um pouco e pensei em compartilhar meu trabalho. Espero que isto ajude.

Código jsfuddle

 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("
")); var place_holder = jQuery("#place_holder"); place_holder.css({ "height": flash_error.height(), "display": "none" }); jQuery(window).scroll(function(e) { lockErrorMessageToTop(); }); } } scrollErrorMessageToTop();​

Isso é um pouco mais dynamic de uma maneira de fazer o pergaminho. Ele precisa de algum trabalho e eu vou em algum momento transformar isso em um plug mas, mas é isso que eu fiz depois de horas de trabalho.

Em javascript você pode fazer:

 var element = document.getElementById("myid"); element.style.position = "fixed"; element.style.top = "0%"; 

Não é uma solução exata, mas uma ótima alternativa a considerar

este CSS SOMENTE Barra de rolagem na parte superior da canvas . Resolvido todo o problema com apenas CSS , sem JavaScript, sem JQuery, sem trabalho do cérebro ( lol ).

Aproveite o meu violino : D todos os códigos estão incluídos lá 🙂

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; }

Coloque o conteúdo por tempo suficiente para que você possa ver o efeito aqui 🙂 Ah, e a referência está lá também, pois ele merece crédito

CSS SOMENTE Barra de rolagem na parte superior da canvas

Aqui está um exemplo que usa o plugin jquery-visible: http://jsfiddle.net/711p4em4/ .

HTML:

 
Header
Content
Footer

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 (inclui o plugin 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"); }); }); 

pegajoso até o rodapé atingir a 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);