Center HTML Vertically via Angular Directive

One of common tasks that come up when you write an HTML app is a requirement to center some component inside a screen.  Centering horizontally is very easy with Twitter Bootstrap.  However, center vertically is not supported by Bootstrap, at least they do not have a style for that.  Since in an Angular application you do want to use manipulate DOM outside of directives, I decided to write an center vertically directive.  I am emotionally attached to TypeScript now, but you can easily translate the code I am sharing to JavaScript.  I know, I know, but there are worse additions than TypeScript.

The idea behind the directive is simple, I just need to dynamically add top margin based on window size and HTML element size.  As a result, there are only a few lines of code required.  Also, I have to remember that the user can resize the browser window, so I have to listen to window resize events and react to those as well.

    export class CenterVerticallyDirective extends app.directives.BaseDirective {
        private owner: ng.IAugmentedJQuery;
        constructor(private $window: ng.IWindowService) {
            super();
            var that = this;
            this.restrict = 'A';
            this.link = function (scope: ng.IScope, element: ng.IAugmentedJQuery) {
                that.owner = element;
                resize();
            };
            
            var resize = function () {
                that.owner.css('margin-top', (angular.element(that.$window).height() - that.owner.height()) / 2);
            };
            angular.element($window).on('resize', resize);
        }
    }

As you can see I am using $window service that in Angular abstracts developers from the actual window object in JavaScript.  I am injecting window into directive inside my module / directive declaration:

    angular.module('app.directives.Common', [])
        .directive('centerVertically', ['$window', function ($window: ng.IWindowService) {
            return new app.directives.CenterVerticallyDirective($window);
        }]);

Easy, right.  Final step is to add an attribute my HTML element, using of course normalized version of the directive.

<div class="col-md-4 col-md-offset-4 col-sm-10 col-sm-offset-1" data-center-vertically>

Enjoy.

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *