1

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!

Brendan
  • 125
  • 2
  • 14
  • I updated my answer with some additional hints that might help you. If you need further help, I might have to ask you to clarify what you mean by the "snapping" action you're describing. – Neely Sep 10 '18 at 18:30

3 Answers3

1

Here are some errors / corrections.

GetBoundingClientRect() is a JS function, not jQuery, so it must be used on a javascript element, not a jquery selector. Using the [0] accessor on the jquery selector (if that's how you want to get it) will give you the JS element.

Also noticed that you were trying to select the "html" tag by id, but it doesn't have any Id. Changed it to getElementsByTagName.

var offsetYOrig = $('.box-1')[0].getBoundingClientRect().bottom;
// or, without jQuery:
// var offsetYOrig = document.getElementsByClassName('box-1')[0].getBoundingClientRect().bottom;

var html = document.getElementsByTagName("html")[0];
var style = window.getComputedStyle(html);
var remValue = style.getPropertyValue('font-size');

Edit: Regarding your edit, if you need to call the javascript to recompute on window resize, you may want to try something like this. I'm not sure if it achieves what you want fully (I don't completely understand your 'snapping' requirements, but this will at least call the code again. You may still have to edit the code in the snapFunction if it doesn't suit your needs.

I added some console logs that might help you check your math as it seemed a bit problematic to me, though I was unsure how to fix it because I don't understand your goal.

function snapFunction ()
{
    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;

    // open your browser console and check the value of these to check your math and what values you're getting
    console.log("bottomOrig: " + bottomOrig )
    console.log("remValue: " + remValue)
    console.log("bottomNew: " + bottomNew )

    // note: no quotes around your variable name fix here
    $('.container-2').css("margin-bottom", fix + "px");
};

// call on load
(function() {
    snapFunction();
})();

// call on resize
$( window ).resize(function() {
    snapFunction();
});

I did notice that the value of your bottomNew variable was logging as "NaN" (Not a Number) so I think something is going wrong there.

I think you're getting a font-size like "36px" instead of just "36". Maybe you could try

var remValue = parseInt(style.getPropertyValue('font-size'), 10);

The 10 in that parseInt function is just specifying we want to use base 10 numbers.

Neely
  • 111
  • 2
  • 4
1

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);
});
Brendan
  • 125
  • 2
  • 14
0

I hope this will help you

Here's the edited fiddle

jsfiddle.net/ztf64mwg/82/

I just edited some variables and fixed some of the errors

Eyad
  • 37
  • 7
  • I've made changes to the fiddle and code above with the edits you proposed, but I'm still not having success in creating the desired CSS style change for `.container-2`. I've also tried removing the second part of the code with the event listener and changed to On Load for the Fiddle Load Type, but no success. Still would love some help! This will be a bit of a breakthrough for me if it's accomplished. – Brendan Aug 29 '18 at 01:06