Cómo arreglar un encabezado en scroll

Estoy creando un encabezado que una vez que se desplazó a una cierta cantidad de píxeles lo arregla y se mantiene en su lugar.

¿Puedo hacer esto usando solo css y html o también necesito jquery?

He creado una demostración para que puedas entender. ¡Cualquier ayuda sería genial!

http://jsfiddle.net/gxRC9/4/

body{ margin:0px; padding:0px; } .clear{ clear:both; } .container{ height:2000px; } .cover-photo-container{ width:700px; height: 348px; margin-bottom: 20px; background-color:red; } .small-box{ width:163px; height:100px; border:1px solid blue; float:left; } .sticky-header{ width:700px; height:50px; background:orange; postion:fixed; } 

Necesitas algunos JS para hacer eventos de desplazamiento. La mejor manera de hacerlo es establecer una nueva clase de CSS para la posición fija que se asignará a la div relevante cuando el desplazamiento va más allá de cierto punto.

HTML

 

CSS

 .fixed { position: fixed; top:0; left:0; width: 100%; } 

jQuery

 $(window).scroll(function(){ var sticky = $('.sticky'), scroll = $(window).scrollTop(); if (scroll >= 100) sticky.addClass('fixed'); else sticky.removeClass('fixed'); }); 

Ejemplo de violín: http://jsfiddle.net/gxRC9/501/


EDITAR: Ejemplo extendido

Si se desconoce el punto de activación, pero debe serlo siempre que el elemento adhesivo llegue a la parte superior de la pantalla, se puede usar la función offset().top .

 var stickyOffset = $('.sticky').offset().top; $(window).scroll(function(){ var sticky = $('.sticky'), scroll = $(window).scrollTop(); if (scroll >= stickyOffset) sticky.addClass('fixed'); else sticky.removeClass('fixed'); }); 

Ejemplo ampliado de violín: http://jsfiddle.net/gxRC9/502/

He modificado la respuesta de Coop. Por favor, consulte el ejemplo FIDDLE Aquí están mis ediciones:

 $(window).scroll(function(){ if ($(window).scrollTop() >= 330) { $('.sticky-header').addClass('fixed'); } else { $('.sticky-header').removeClass('fixed'); } }); 

Sé que Coop ya respondió esta pregunta, pero aquí hay una versión que también rastrea en qué parte del documento está el div, en lugar de basarse en un valor estático:

http://jsfiddle.net/gxRC9/16/

Javascript

 var offset = $( ".sticky-header" ).offset(); var sticky = document.getElementById("sticky-header") $(window).scroll(function() { if ( $('body').scrollTop() > offset.top){ $('.sticky-header').addClass('fixed'); } else { $('.sticky-header').removeClass('fixed'); } }); 

CSS

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

La respuesta de Coop es excelente.
Sin embargo, depende de jQuery, aquí hay una versión que no tiene dependencias:

HTML

 

CSS

 .sticky { width: 100% } .fixed { position: fixed; top:0; } 

JS
(Esto usa la respuesta de la falta de blanco para encontrar compensaciones en Vanilla JS.)

 function findOffset(element) { var top = 0, left = 0; do { top += element.offsetTop || 0; left += element.offsetLeft || 0; element = element.offsetParent; } while(element); return { top: top, left: left }; } window.onload = function () { var stickyHeader = document.getElementById('sticky'); var headerOffset = findOffset(stickyHeader); window.onscroll = function() { // body.scrollTop is deprecated and no longer available on Firefox var bodyScrollTop = document.documentElement.scrollTop || document.body.scrollTop; if (bodyScrollTop > headerOffset.top) { stickyHeader.classList.add('fixed'); } else { stickyHeader.classList.remove('fixed'); } }; }; 

Ejemplo

https://jsbin.com/walabebita/edit?html,css,js,output

Solo basándome en la respuesta de Rich , que usa el desplazamiento.

Modifiqué esto de la siguiente manera:

  • No era necesario el var $sticky en el ejemplo de Rich, no estaba haciendo nada
  • Moví la verificación de desplazamiento a una función separada y la llamé en el documento listo y también en el desplazamiento, por lo que si la página se actualiza con el desplazamiento hasta la mitad de la página, cambia el tamaño directamente sin tener que esperar un desplazamiento. desencadenar

     jQuery(document).ready(function($){ var offset = $( "#header" ).offset(); checkOffset(); $(window).scroll(function() { checkOffset(); }); function checkOffset() { if ( $('body').scrollTop() > offset.top){ $('#header').addClass('fixed'); } else { $('#header').removeClass('fixed'); } } }); 

La respuesta de Coops es una solución buena y simple, sin embargo, una vez que aplica la clase fija, la página se vuelve mucho más corta y el contenido “saltará”, y si la página es de una longitud donde la distancia de desplazamiento es menor que la altura del encabezado elemento, parecerá que salta y no le permite ver la parte inferior de la página.

La respuesta que encontré fue agregar un divisor espaciador por encima del elemento que se fijará (elemento nav en mi caso), configurarlo a la misma altura que el elemento nav y configurarlo para que no muestre ninguno.

Al agregar la clase .fixed al navegador, muestre el div .nav-spacer y, cuando lo elimine, escóndalo. Como el alto de la página cambia instantáneamente, he establecido la duración en 0.

HTML

 
the element above the element that will become fixed

CSS

 nav { position: relative; height: 100px; } .nav-spacer{ position: relative; height: 100px; display: none; } .fixed { position: fixed; top:0; left:0; width: 100%; /* I like to add a shadow on to the fixed element */ -webkit-box-shadow: 0px 5px 10px 1px rgba(0,0,0,0.25); -moz-box-shadow: 0px 5px 10px 1px rgba(0,0,0,0.25); box-shadow: 0px 5px 10px 1px rgba(0,0,0,0.25); } 

JavaScript

 var stickyOffset = $('nav').offset().top; $(window).scroll(function(){ if ($(window).scrollTop() >= stickyOffset){ $('nav').addClass('fixed'); //this makes the page length equal to what it was before fixing nav $('.nav-spacer').show(0); } else { $('nav').removeClass('fixed'); $('.nav-spacer').hide(0); } }); 
  $(document).ready(function(){ var div=$('#header'); var start=$(div).offset().top; $.event.add(window,'scroll',function(){ var p=$(window).scrollTop(); $(div).css('position',(p>start)?'fixed':'static'); $(div).css('top',(p>start)?'0px':''); }); }); 

Funciona perfectamente

La solución elegida no encajaba bien en mi página. Entonces esta es una versión más avanzada que funciona con bootstrap.

El javascript

 var stickyOffset = $('.sticky-header').offset().top; $(window).scroll(function () { var sticky = $('.sticky-header'), scroll = $(window).scrollTop(), header = $('.fixed-header-background'); sticky.each(function() { var left = $(this).offset().left; $(this).data('left', left);//I store the left offset }); if (scroll >= stickyOffset) { sticky.addClass('fixed'); header.css('display', 'block'); sticky.each(function() { $(this).css('left', $(this).data('left'));//I set the left offset }); } else { sticky.removeClass('fixed'); header.css('display', 'none'); sticky.each(function () { $(this).css('left', '');//I remove the left offset }); } }); 

El CSS

 .fixed-header-background { display: none; position: fixed; top: 50px; width: 100%; height: 30px; background-color: #fff; z-index: 5; border-bottom-style: solid; border-bottom-color: #dedede; border-bottom-width: 2px; } .fixed{ position: fixed; top: 52px; z-index: 6; } 

Y el HTML

  
[....]
My header 1 My header 2

O simplemente agregue una etiqueta span con la altura del conjunto de encabezado fijo como su altura y luego insértelo junto al encabezado fijo:

 $(function() { var $span_height = $('.fixed-header').height; var $span_tag = ''; $('.fixed-header').after($span_tag); }); 

Espero que esta solución alternativa sea tan valiosa para otra persona como lo fue para mí.

Situación :
En una página HTML5, tenía un menú que era un elemento de navegación dentro de un encabezado (no el encabezado, sino un encabezado en otro elemento).
Quería que la navegación se adhiriera a la parte superior una vez que el usuario se desplazaba hacia ella, pero antes de esto, el encabezado estaba en una posición absoluta (por lo que podría superponer algo más).
Las soluciones anteriores nunca activaron un cambio porque .offsetTop no iba a cambiar ya que este era un elemento de posición absoluta. Además, la propiedad .scrollTop era simplemente la parte superior del elemento más superior … es decir 0 y siempre sería 0.
Las pruebas que realicé utilizando estos dos (y lo mismo con los resultados de getBoundingClientRect) no me dirían si la parte superior de la barra de navegación alguna vez se desplazó a la parte superior de la página visible (de nuevo, como se informó en la consola, simplemente mantuvieron los mismos números mientras se desplazaban ocurrió).

Solución
La solución para mí fue utilizar

 window.visualViewport.pageTop 

El valor de la propiedad pageTop refleja la sección visible de la pantalla, lo que me permite rastrear dónde se encuentra un elemento en referencia a los límites del área visible.
Esto permitió una función simple asignada al evento de desplazamiento de la ventana para detectar cuando la parte superior de la barra de navegación se cruzaba con la parte superior del área visible y aplicar el estilo para que se quede en la parte superior.

Probablemente sea innecesario decir que, cada vez que me ocupo de desplazarme, espero usar esta solución para responder programáticamente al movimiento de los elementos que se desplazan.
Espero que ayude a alguien más.