javascript - Hvordan kan jeg få en div til å sitte fast øverst på skjermen når den har blitt scrollet til?


Jeg vil gjerne lage en div som er plassert under et innholdsblokk, men som, når siden har blitt scrolla nok til å treffe dens øvre grense, blir fast på plass og scroller med siden.

Svar #1

Du kan enkelt bruke CSS, og plassere elementet ditt som fast:

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

Rediger: Du bør ha elementet med posisjon absolutt, når rulleforskyvningen har nådd elementet, bør det endres til fast, og topposisjonen bør settes til null.

Du kan oppdage toppens rulleforskyvning i dokumentet med scrollTop-funksjonen:

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

Når rulleoffset nådde 200, vil elementet feste seg til toppen av nettleservinduet, fordi det er plassert som fast.

Svar #2

Du har sett dette eksempelet på Googles Codes issues-side og (først nylig) på Stack Overflows redigeringsside.

CMS sitt svar reverserer ikke posisjoneringen når du scroller tilbake opp. Her er den skamløst stjålne koden fra 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> 

Og en enkel direktesendt demo.

Et nyfødt, skript-fritt alternativ er position: sticky, som støttes i Chrome, Firefox og Safari. Se artikkelen på HTML5Rocks og demoen, samt Mozilla-dokumentasjonen.

Svar #3

Fra januar 2017 og utgivelsen av Chrome 56, støtter de fleste nettlesere i vanlig bruk position: sticky-egenskapen i CSS.

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

gjør susen for meg i Firefox og Chrome.

I Safari må du fortsatt bruke position: -webkit-sticky.

Polyfills er tilgjengelige for Internet Explorer og Edge; https://github.com/wilddeer/stickyfill ser ut til å være en god en.

Svar #4

Og her er hvordan uten jquery (OPPDATERING: se andre svar hvor du nå kan gjøre dette kun med 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>

Svar #5

Jeg hadde det samme problemet som deg og endte opp med å lage en jQuery-plugin for å ta seg av det. Den løser faktisk alle problemene folk har listet opp her, pluss at den legger til noen valgfri funksjoner også.

Alternativer

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

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

Svar #6

Den enkleste løsningen (uten js): demo

.container {
  position: relative;
}
.sticky-div {
    position: sticky;
    top: 0;
}
<div class="container">
  <h1>
    relative container & sticky div
  </h1>
  <div class="sticky-div"> this row is sticky</div>
  <div>
    content
  </div>
</div>

Svar #7

Slik gjorde jeg det med jQuery. Dette var alt satt sammen fra ulike svar på Stack Overflow. Denne løsningen cacher selektorene for raskere ytelse og løser også «hopping»-problemet når den sticky div blir sticky.

Sjekk det ut på 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);
        }
    });
});

Svar #8

Som Josh Lee og Colin 't Hart har sagt, kan du eventuelt bare bruke position: sticky; top: 0; som gjelder for div-en du ønsker skal ha scrolling...

I tillegg er det eneste du må gjøre å kopiere dette til toppen av siden din eller formatere det slik at det passer inn i et eksternt CSS-ark:

<style>
#sticky_div's_name_here { position: sticky; top: 0; }
</style>

Bare erstatt #sticky_div's_name_here med navnet på din div, altså hvis din div var <div id="example"> ville du skrive #example { position: sticky; top: 0; }.

Relaterte artikler