Using .outerWidth() & .outerHeight() with the 'resize' event to center a child element in parent

2.2k views Asked by At

I am attempting to write some JavaScript code that will allow me to center a child element within it's parent using padding. Then using the same function to recalculate the spacing using the 'resize' event. Before you start asking me why i am not doing this with CSS, this code is only a small part of a larger project. I have simplified the code as the rest of the code works and would only serve to confuse the subject.

Calculating the space - This is the function that caculates the amount of space to be used on either side of the child element.

($outer.outerWidth() - $inner.outerWidth()) / 2;
($outer.outerHeight() - $inner.outerHeight()) / 2;

The problem

Although i have successfully managed to get the desired results with margin. Padding is causing me problems.

  1. It appears to be increasing the width on the outer element when resized
  2. It does not center the child element perfectly (there appears to be an offset)
  3. The inner element collapses on resize and becomes invisible.

I realize that there may be some fundamentals regarding padding that are causing my problems however after numerous console logs and observing the data returned i still can't put my finger on the problem. Any suggestion would be very welcome. It may turn out that this is not feasible at all.

HTML

 <div id="demo" class="outer">
  <div class="inner">

  </div>
</div>

CSS

html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}

.outer {
  width:97%;
  height:400px;
  border:1px solid black;
  margin:20px;
}

.inner {
  width:40%;
  height:100px;
  background-color:grey;
}

JAVASCRIPT

var $outer = $(".outer");
var $inner = $(".inner");

var getSpace = function(axis)  {

  if (axis.toLowerCase() == "x") {

    return ($outer.outerWidth() - $inner.outerWidth()) / 2;

  } else if (axis.toLowerCase() == "y") {

    return ($outer.outerHeight() - $inner.outerHeight()) / 2;

  }  

}

var renderStyle = function(spacingType) {

  var lateralSpace = getSpace("x");  
  var verticalSpace = getSpace("y");

  var $element;

  if (spacingType == "padding") {
      $element = $outer;
  } else if (spacingType == "margin") {
      $element = $inner;
    }

  $.each(["top", "right", "bottom", "left"], function(index, direction) {
    if (direction == "top" || direction == "bottom") {
      $element.css(spacingType + "-" + direction, verticalSpace);
    }
    else if (direction == "right" || direction == "left") {
      $element.css(spacingType + "-" + direction, lateralSpace);
    }                                     
  });                
}; 

var renderInit = function() {

  $(document).ready(function() {

    renderStyle("padding");

  });

  $(window).on("resize", function() {

    renderStyle("padding");

  });

}

renderInit();

EXAMPLE - link

2

There are 2 answers

1
rorymorris89 On BEST ANSWER

Although I completely disagree with this approach to horizontally centring an element, hopefully this will help you on your way.

Fiddle: https://jsfiddle.net/0uxx2ujg/

JavaScript:

var outer = $('.outer'), inner = $('.inner');
function centreThatDiv(){ 
    var requiredPadding = outer.outerWidth() / 2 - (inner.outerWidth() / 2);
    console.log(requiredPadding);
    outer.css('padding', '0 ' + requiredPadding + 'px').css('width','auto');
}

$(document).ready(function(){
    // fire on page load
    centreThatDiv();
});

$(window).resize(function(){
    // fire on window resize
    centreThatDiv();
});

HTML:

<div class="outer">
    <div class="inner">Centre me!</div>
</div>

CSS:

.outer{ width:80%; height:300px; margin:10%; background: tomato; }
.inner{ width:60px; height:60px; background:white; }

Furthered on from why I disagree with this approach - JavaScript shouldn't be used to lay things out. Sure - it can be, if it really needs to be used; but for something as simple as centring an element, it's not necessary at all. Browsers handle resizing CSS elements themselves, so by using JS you introduce more headaches for yourself further down the line.

Here's a couple of examples of how you can achieve this in CSS only:

text-align:center & display:inline-block https://jsfiddle.net/0uxx2ujg/1/

position:absolute & left:50% https://jsfiddle.net/0uxx2ujg/2/ (this can be used for vertically centring too which is trickier than horizontal)

4
Ranjeet KRISHNA Bhargava On

You can create the new CSS class to adjust for elements size on $window.onresize = function () { //add your code };