Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Centering HTML Content

5.00/5 (1 vote)
27 May 2014CPOL6 min read 7.5K   13  
Resusable utility to easily center one HTML element over another.

Introduction

I have been developing websites since 2010. One reoccurring problem I faced on almost every project was centering some HTML element, either relative to the window or to some other element. This is not such a difficult concept so for each website I managed to implement an effective solution. Nonetheless, I realized that each time I am faced with this problem, I waste time re-coding the solution. I never spent time making a solution I could reuse throughout my websites. So today, I have decided to make a solution that can be reused.

The Problem

The first step in making a reusable solution is to properly define the problem and to outline all the requirements. Now the problem may seem relatively simple at first: we must center one HTML element inside or over another, but it is not. For example, suppose we implement a solution that centers an HTML element over another. Then something happens - either the window is resized or the later element is repositioned. Then our HTML element will no longer be centered and our solution has accomplished nothing.

Centered Element

So what is our real problem? First of all, we must position any visible HTML element (from now on called elm2) inside or over another (from now on called elm1) so that the following conditions are met:

  1. elm2 appears to be inside or over elm1, but in markup elm2 is not necessarily a child of elm1.
  2. elm2 is positioned so that the space inside elm1 and outside elm2 is equally spaced horizontally and vertically.

Furthermore, we must maintain this position throughout the lifetime of the page. Lastly, we should be able to center more than one HTML element on any one page.

Requirements

From this more substantial problem definition, I developed the following requirements:

  1. The solution should take two given elements (called elm1 and elm2) and position elm2 so that:

    1. The space between the left borders of elm1 and elm2 is equal to the space between the right borders of elm1 and elm2,
    2. and so that the space between the top borders of elm1 and elm2 is equal to the space between the bottom borders of elm1 and elm2.

    When conditions a and b are true for any element, it will be referred to as “centered”.

  2. Handle the onresize event of the window, and reposition any elements that must be centered so that conditions a and b are true for such an element.
  3. The solution should provide an interface so that users can specify which elements they want to be centered and over which elements.
  4. The solution should provide an interface so that users can re-center any elements if they resized or repositioned an element that would cause a centered element to no longer be centered.
  5. The solution should be able to center up to 20 elements and maintain centering for all of them.
  6. The solution should consider the window to also be an element so that other HTML elements can be centered inside it.

Implementation

Now it is possible to code a solution using only HTML and CSS. In such a case, the solution will be very efficient in terms of loading time of the webpage. Nonetheless, such a solution is not reusable. That is because a solution using only CSS requires that elm1 and elm2 have statically defined dimensions. So when you move the solution to a new page to center a different elm2 with different dimensions, you will have to change the CSS rules. A true reusable solution must be defined so that it does not have to be changed when implemented on a different web page.

The only solution that offers such reusability is one that uses JavaScript. However, such a solution does have a slight performance drawback because the code will have to be executed after the page loads; thus, extending the loading time of the page (but only by milliseconds).

The solution should keep track of up to twenty elements. It should know which elements must be centered over which elements so that it can re-center them when the window is resized. This requires the use of an array. But rather than placing the array in the global scope along with all the functions needed for the solution, I decided to create an object that will contain the array as a private member. This object will then have only two public members to implement the interfaces defined in points 3 and 4 of the requirements.

JavaScript
(function () {
    function Utility() {
        code elements = new Array(0);
    }               
    util = new Utility();
}());    

As can be seen from the code, util (short for utility) is a onetime only object because it is not necessary to have more than one instance.

The next step is to define the function that will do all the hard work.

JavaScript
function centerElements(index) {
                    
    for (code l_1 = index?index:0; l_1 < elements.length; l_1++) {
        code anchor;

        if (elements[l_1].elm1.offsetLeft) {
            elements[l_1].elm2.style.position = "absolute";
            anchor = { left: elements[l_1].elm1.offsetLeft, top: elements[l_1].elm1.offsetTop };
        }
        else {
            elements[l_1].elm2.style.position = "fixed";
            anchor = { left: 0, top: 0 };
        }

        elements[l_1].elm2.style.marginTop = "0px";
        elements[l_1].elm2.style.marginLeft = "0px";

        code elm1Size = getSize(elements[l_1].elm1), elm2Size = getSize(elements[l_1].elm2);

        anchor.left += (elm1Size.width - elm2Size.width) / 2;
        anchor.top += (elm1Size.height - elm2Size.height) / 2;

       elements[l_1].elm2.style.left = anchor.left + "px";
       elements[l_1].elm2.style.top = anchor.top + "px";
       
        if (index) { break;}
    }
}

First of all, notice that the function takes an argument index. It uses this index to center only the specified element in the array. But if the index is not specified, then it loops through the array of elements and centers all of them.

The first step to center an element is to specify its position. This is the first required step otherwise inline elements like the anchor does not have width or height. Notice that when elm1 is the window object then elm2 will be positioned “fixed” and if elm1 is an element then elm2 will be positioned “absolute”. This is so that when the user scrolls, elm2 will remain centered inside the window.

At this point, it is important to note that the code uses the top and left style rules of elm2 to position it. The first step in calculating the pixel values for the top and left style rule of elm2 is to find the top and left position of elm1. This is given by the offsetTop and offsetLeft properties of elm1, or in the case of the window object, they are both zero. The two values are combined into an object and assigned to the anchor variable.

The next step is to obtain the widths and heights of elm1 and elm2, these are assigned to elm1Size and elm2Size respectively. The widths and heights are obtained by calling getSize. This function is useful in more than just the util object so it is defined in the global scope.

Finally, after the sizes have been acquired, it is time for some math. To calculate the top position of elm2, the height of elm2 is subtracted from that of elm1 and divided into two. The result is then added to the top position of elm1. The same steps are taken to calculate the left position but this time using the widths instead of the heights.

After all that, the top and left style rules of elm2 are finally assigned.

Once the backbone of the solution has been implemented, the interface methods can be defined.

JavaScript
this.center = function (elm1, elm2) {
    code index = elements.length;
    elements[index] = { elm1: elm1, elm2: elm2 };
    centerElements(index);
    return index;
}
this.reCenter = function (index) { centerElements(index); }

The center method takes references for elm1 and elm2, and adds them to the array. It then calls the centerElements method and returns the index of the elements in the array. The reason it returns the index is so that the user can later on call reCenter and specify which element should be re-centered.

The last thing needed is to handle the onresize event of the window.

JavaScript
window.addEventListener("resize", function () { centerElements(); }, false);

Note that when the event is raised, no index is passed to centerElements so it will re-center all elements.

Use

To center an element now is very easy.

JavaScript
var elm1 = document.getElementById("elm1");
var elm2 = document.getElementById("elm2");

util.center(elm1,elm2);

//if size or position change 
util.reCenter();

First get references to both elements, then call the center method of the util object. If any changes are made in the size or position of either element, simply call reCenter to maintain the centeredness of the elements.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)