javascriptwindow-resizegridlinesgetboundingclientrectsnapping

Using Javascript getBoundingClientRect to Snap Items to Grid


EDIT: I've simplified the code (below and in fiddle) down to the major problem needed to be solved in hope of creating more readability.

I've implemented Bader's solution for correctly using getBoundingClientRect value and using document.querySelector for getting both the class name and the html tag needed for the function. I'd now like to move on to the last five lines of the code beginning with var = style.

I've now corrected the math for the final two variables.

→ I'm trying to achieve creating a snapping function for use alongside Plumber, a baseline-grid Sass plugin.

Basically, I have a vertically centered flex item that needs to -- instead of being perfectly centered -- snap in an upward direction to the closest grid line. This will allow me to have a consistent vertical rhythm between slides in a custom mobile-based experience.

I'm using getBoundingClientRect to calculate the distance between the bottom of an object, and the top of the window.

Then I use Math.floor to round down to the nearest multiple of my rem value.

Then I use this new value to create a CSS bottom margin on the flex-centered container for the alignment fix.

(Then to finish, I'd like to have this function load on $(document).ready and on window resize.)

function() {

  var box = document.querySelector('.box-1');
  var rect = box.getBoundingClientRect();
  var bottomOrig = rect.bottom;

  var htmlRoot = document.querySelector('html');
  var style = getComputedStyle(htmlRoot);
  var remValue = style.getPropertyValue('font-size');

  var bottomNew = Math.floor(bottomOrig / remValue) * remValue;
  var fix = bottomOrig - bottomNew;

  $('.container-2').css("margin-bottom", "fix + 'px'");

}

Here's the fiddle.

I most likely have a syntax problem here, and would greatly appreciate help.

Thanks!


Solution

  • I ended up jumping on HackHands and, with help, came up with a great working solution.

    This will snap any vertically flex-centered object to a grid with its size set as 1rem.

    All you need to do is give the object that is being measured for distance the id attribute "measure", making sure that this object is aligned correctly with a 1rem grid from the top of its own container.

    Then give the parent container (or any container higher in the DOM tree) that you'd like to snap to the grid the class of "snap".

    If anyone ever finds a use for this and needs further explanation, just let me know.

    function snap(object){  
    
        var rect = object.getBoundingClientRect();
        var bottomOrig = rect.bottom;
    
        var htmlRoot = document.querySelector('html');
        var style = getComputedStyle(htmlRoot);
        var remValue = parseInt(style.getPropertyValue('font-size'));
    
        var bottomNew = Math.floor(bottomOrig / remValue) * remValue;
    
        var topFixPositive = bottomNew - bottomOrig;
        var topFixNegative = -Math.abs(topFixPositive);
    
        $(object).closest('.snap').css("margin-top", topFixNegative);
    
    }
    
    
    function snapClear(object){  
    
        $(object).closest('.snap').css("margin-top", "0");
    
    }
    
    
    var measureHome = document.querySelector('#measure');
    
    snap(measureHome);
    
    $(window).on('resize', function() {
        snapClear(measureHome);
        snap(measureHome);
    });