Search code examples
jqueryscrollmedia-queriesoffset

Add media queries to offset scroll jQuery


I'm building a website with a navigation that jumps to anchors on a different page of the website. To compensate for the sticky header that's blocking the top part of the content I found this code snippet.

It works, but only on desktop. I would need to adjust the value for tablets and smartphones but since I have no idea of jQuery I'm completely clueless.

I would need one for min-width: 1025px, max-width: 1024px and max-width: 767px to adjust the height of the different header sizes.

How do I add those media queries into the snippet?

 jQuery(document).ready(function() {
    var target = window.location.hash;

   // only try to scroll to offset if target has been set in location hash
       if (target != '') {
   var $target = jQuery(target);
jQuery('html, body').stop().animate({
  'scrollTop': $target.offset().top - 155
}, 900, 'swing', function() {
  window.location.hash = target - 40;
});
} 
});

Solution

  • You can dynamically read the height of your header.

    Just replace your 155 with parseInt($('.header').css('height'), 10). Obviously the .header is the selector in my example, if your header has an ID use #YouIDName if it has a class like in my example, use .YourClassName.

    To see this example in action repeatedly click on Run code snippet.

    jQuery(document).ready(function() {
      var target = window.location.hash;
      
      
      // Only for test on Stack Overflow:
      target = '#myTarget'; // Force target for test
      $('.header').css('height', (Math.floor(Math.random() * 81) + 20) + 'px'); // Random height of header from 20 to 100
      $('.header').text('Current header height is ' + $('.header').css('height')); // Print header height
      // End rows for test //
      
      
      
      // only try to scroll to offset if target has been set in location hash
      if (target != '') {
        var $target = jQuery(target);
        jQuery('html, body').stop().animate({
          'scrollTop': $target.offset().top - parseInt($('.header').css('height'), 10) // Read the height of your header
        }, 900, 'swing', function() {
          window.location.hash = target - 40;
        });
      }
    });
    .header {
      position: sticky;
      top:0;
      background-color:red;
      width:100%;
      height: 155px;
    }
    
    .content {
      display: inline-block;
      background-color:blue;
      width:100%;
      height: 600px;
    }
    
    a {
      display: inline-block;
      background-color:yellow;
      width:100%;
      height: 20px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="header">My header</div>
    <div class="content">Random content</div>
    <a id="myTarget" href="#myTarget">Target</a>
    <div class="content">Random content</div>

    EDIT

    Anyway, not knowing the exact functioning of your layout, I add the solution with media queries via javascript.

    The relevant part:

    let headerHeight = 155;
    
    if (window.matchMedia("(max-width: 767px)")) {
      // Less then 767
      headerHeight = 50;
      console.log('header: 50 // max-width: 767px');
    } else if (window.matchMedia("(max-width: 1024px)")) {
      // From 768 and 1024
      headerHeight = 100;
      console.log('header: 100 // max-width: 1024px');
    } else {
      // Greater than 1024 (headerHeight = 155).
      //    You can remove this else.
      console.log('header: 155');
    }
    

    jQuery(document).ready(function() {
      var target = window.location.hash;
    
    
      // Only for test on Stack Overflow:
      target = '#myTarget'; // Force target for test
      
      // Force header height based on media query
      if (window.matchMedia("(max-width: 767px)")) {
        $('.header').css('height', '50px');
      } else if (window.matchMedia("(max-width: 1024px)")) {
        $('.header').css('height', '100px');
      }
      // End rows for test //
    
    
    
      // only try to scroll to offset if target has been set in location hash
      if (target != '') {
    
        let headerHeight = 155;
    
        if (window.matchMedia("(max-width: 767px)")) {
          // Less then 767
          headerHeight = 50;
          console.log('header: 50 // max-width: 767px');
        } else if (window.matchMedia("(max-width: 1024px)")) {
          // From 768 and 1024
          headerHeight = 100;
          console.log('header: 100 // max-width: 1024px');
        } else {
          // Greater than 1024 (headerHeight = 155).
          //    You can remove this else.
          console.log('header: 155');
        }
    
    
        var $target = jQuery(target);
        jQuery('html, body').stop().animate({
          'scrollTop': $target.offset().top - headerHeight
        }, 900, 'swing', function() {
          window.location.hash = target - 40;
        });
      }
    });
    .header {
      position: sticky;
      top: 0;
      background-color: red;
      width: 100%;
      height: 155px;
    }
    
    .content {
      display: inline-block;
      background-color: blue;
      width: 100%;
      height: 600px;
    }
    
    a {
      display: inline-block;
      background-color: yellow;
      width: 100%;
      height: 20px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="header">My header</div>
    <div class="content">Random content</div>
    <a id="myTarget" href="#myTarget">Target</a>
    <div class="content">Random content</div>