New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possilbe to change sticky top position when viewport changes? #211

Open
eSilverStrike opened this Issue May 9, 2016 · 3 comments

Comments

Projects
None yet
3 participants
@eSilverStrike

eSilverStrike commented May 9, 2016

I have 2 sticky items, the top navigation menu bar, and a module on the left side bar.

Everything works great expect when the top navigation menu bar gets changed to a slide out left menu for mobile devices with small viewports.

Is it possible to change the module to a new top position when the view port has changed? This way I am not left with a white space at the top.

Thanks for a great plugin.

@heathdutton

This comment has been minimized.

Show comment
Hide comment
@heathdutton

heathdutton May 10, 2016

There are a few ways to accomplish this.

For us, we use a css/sass workaround:

body:before {
  display: none !important;
  @include breakpoint(xs) {
    content: 'xs' !important;
  }
  @include breakpoint(sm) {
    content: 'sm' !important;
  }
  @include breakpoint(md) {
    content: 'md' !important;
  }
  @include breakpoint(lg) {
    content: 'lg' !important;
  }
}

Basically, we're exploiting the :before pseudo-element to ensure that our stylesheet breakpoints are always retrievable by javascript by effectively modifying the DOM, regardless of how those breakpoints may change in our sass. You can do this with standard CSS as well, of course.

Next in JS, we do something like:

$(window).resize(function () {
      var breakpoint = window
          .getComputedStyle( document.querySelector('body'), ':before' )
          .getPropertyValue( 'content' )
          .replace(/['"]+/g, '');
    // Do the thing based on the breakpoint.
});

heathdutton commented May 10, 2016

There are a few ways to accomplish this.

For us, we use a css/sass workaround:

body:before {
  display: none !important;
  @include breakpoint(xs) {
    content: 'xs' !important;
  }
  @include breakpoint(sm) {
    content: 'sm' !important;
  }
  @include breakpoint(md) {
    content: 'md' !important;
  }
  @include breakpoint(lg) {
    content: 'lg' !important;
  }
}

Basically, we're exploiting the :before pseudo-element to ensure that our stylesheet breakpoints are always retrievable by javascript by effectively modifying the DOM, regardless of how those breakpoints may change in our sass. You can do this with standard CSS as well, of course.

Next in JS, we do something like:

$(window).resize(function () {
      var breakpoint = window
          .getComputedStyle( document.querySelector('body'), ':before' )
          .getPropertyValue( 'content' )
          .replace(/['"]+/g, '');
    // Do the thing based on the breakpoint.
});
@eSilverStrike

This comment has been minimized.

Show comment
Hide comment
@eSilverStrike

eSilverStrike May 11, 2016

Thanks for your solution. I will give this a try. I haven't used SASS yet so I will go about this using standard css.

eSilverStrike commented May 11, 2016

Thanks for your solution. I will give this a try. I haven't used SASS yet so I will go about this using standard css.

@mhulse

This comment has been minimized.

Show comment
Hide comment
@mhulse

mhulse Jun 27, 2017

Another approach that works well with Bootstrap 3 breakpoints (you'd have to replicate the classes/breakpoints to work in a non-Bootstrap environment):

Put this anywhere in your document:

<span id="mq-detector">
    <span class="visible-xs" data-id="0"></span>
    <span class="visible-sm" data-id="1"></span>
    <span class="visible-md" data-id="2"></span>
    <span class="visible-lg" data-id="3"></span>
</span>

Then this JS:

$(function() {

    // https://stackoverflow.com/a/28373319/922323
    // https://github.com/garand/sticky/issues/211
    // https://github.com/JoshBarr/on-media-query

    var $sticky = $('.sticky');
    var options = {
        topSpacing: 10,
        responsiveWidth: true
    };

    $sticky.sticky(options);

    $('body').on('BREAKPOINT', function(event, size) {
        if (size <= 1) {
            $sticky.unstick();
        } else {
            $sticky.sticky(options);
        }
    });

});

//----------------------------------------------------------------------
// THIS SHOULD COME LAST!
//----------------------------------------------------------------------

$(function() {

    var mqDetector = $('#mq-detector');
    var mqSelectors = [
        mqDetector.find('.visible-xs'),
        mqDetector.find('.visible-sm'),
        mqDetector.find('.visible-md'),
        mqDetector.find('.visible-lg')
    ];

    var checkForResize = function() {
        for (var i = 0; i <= mqSelectors.length; i++) {
            if (mqSelectors[i].is(':visible')) {
                if (window.BREAKPOINT != i) {
                    window.BREAKPOINT = i;
                    console.log(mqSelectors[i].attr('class'));
                    $('body').trigger('BREAKPOINT', mqSelectors[i].data('id'));
                }
                break;
            }
        }
    };

    window.BREAKPOINT = undefined;

    $(window).on('resize', checkForResize);

    checkForResize();

});

Links:

mhulse commented Jun 27, 2017

Another approach that works well with Bootstrap 3 breakpoints (you'd have to replicate the classes/breakpoints to work in a non-Bootstrap environment):

Put this anywhere in your document:

<span id="mq-detector">
    <span class="visible-xs" data-id="0"></span>
    <span class="visible-sm" data-id="1"></span>
    <span class="visible-md" data-id="2"></span>
    <span class="visible-lg" data-id="3"></span>
</span>

Then this JS:

$(function() {

    // https://stackoverflow.com/a/28373319/922323
    // https://github.com/garand/sticky/issues/211
    // https://github.com/JoshBarr/on-media-query

    var $sticky = $('.sticky');
    var options = {
        topSpacing: 10,
        responsiveWidth: true
    };

    $sticky.sticky(options);

    $('body').on('BREAKPOINT', function(event, size) {
        if (size <= 1) {
            $sticky.unstick();
        } else {
            $sticky.sticky(options);
        }
    });

});

//----------------------------------------------------------------------
// THIS SHOULD COME LAST!
//----------------------------------------------------------------------

$(function() {

    var mqDetector = $('#mq-detector');
    var mqSelectors = [
        mqDetector.find('.visible-xs'),
        mqDetector.find('.visible-sm'),
        mqDetector.find('.visible-md'),
        mqDetector.find('.visible-lg')
    ];

    var checkForResize = function() {
        for (var i = 0; i <= mqSelectors.length; i++) {
            if (mqSelectors[i].is(':visible')) {
                if (window.BREAKPOINT != i) {
                    window.BREAKPOINT = i;
                    console.log(mqSelectors[i].attr('class'));
                    $('body').trigger('BREAKPOINT', mqSelectors[i].data('id'));
                }
                break;
            }
        }
    };

    window.BREAKPOINT = undefined;

    $(window).on('resize', checkForResize);

    checkForResize();

});

Links:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment