javascript - vertically - jquery ui position




Using jQuery to center a DIV on the screen (18)

How do I go about setting a <div> in the center of the screen using jQuery?


Edit:

If the question taught me anything, it's this: don't change something that already works :)

I'm providing an (almost) verbatim copy of how this was handled on http://www.jakpsatweb.cz/css/css-vertical-center-solution.html - it's heavily hacked for IE but provides a pure CSS way of answering the question:

.container {display:table; height:100%; position:absolute; overflow:hidden; width:100%;}
.helper    {#position:absolute; #top:50%;
            display:table-cell; vertical-align:middle;}
.content   {#position:relative; #top:-50%;
            margin:0 auto; width:200px; border:1px solid orange;}

Fiddle: http://jsfiddle.net/S9upd/4/

I've run this through browsershots and it seems fine; if for nothing else, I'll keep the original below so that margin percentage handling as dictated by CSS spec sees the light of day.

Original:

Looks like I'm late to the party!

There are some comments above that suggest this is a CSS question - separation of concerns and all. Let me preface this by saying that CSS really shot itself in the foot on this one. I mean, how easy would it be to do this:

.container {
    position:absolute;
    left: 50%;
    top: 50%;
    overflow:visible;
}
.content {
    position:relative;
    margin:-50% 50% 50% -50%;
}

Right? Container's top left corner would be in the center of the screen, and with negative margins the content will magically reappear in the absolute center of the page! http://jsfiddle.net/rJPPc/

Wrong! Horizontal positioning is OK, but vertically... Oh, I see. Apparently in css, when setting top margins in %, the value is calculated as a percentage always relative to the width of the containing block. Like apples and oranges! If you don't trust me or Mozilla doco, have a play with the fiddle above by adjusting content width and be amazed.

...

Now, with CSS being my bread and butter, I was not about to give up. At the same time, I prefer things easy, so I've borrowed the findings of a Czech CSS guru and made it into a working fiddle. Long story short, we create a table in which vertical-align is set to middle:

<table class="super-centered"><tr><td>
    <div class="content">
        <p>I am centered like a boss!</p>
    </div>
</td></tr></table>

And than the content's position is fine-tuned with good old margin:0 auto;:

.super-centered {position:absolute; width:100%;height:100%;vertical-align:middle;}
.content {margin:0 auto;width:200px;}​

Working fiddle as promised: http://jsfiddle.net/teDQ2/


CSS solution In two lines only

It centralize your inner div horizontally and vertically.

#outer{
  display: flex;
}
#inner{
margin: auto;

}

for only horizontal align, change

margin: 0 auto;

and for vertical, change

margin: auto 0;

Here is my version. I may change it after I look at these examples.

$.fn.pixels = function(property){
    return parseInt(this.css(property));
};

$.fn.center = function(){
    var w = $($w);
    return this.each(function(){
        $(this).css("position","absolute");
        $(this).css("top",((w.height() - $(this).height()) / 2) - (($(this).pixels('padding-top') + $(this).pixels('padding-bottom')) / 2) + w.scrollTop() + "px");
        $(this).css("left",((w.width() - $(this).width()) / 2) - (($(this).pixels('padding-left') + $(this).pixels('padding-right')) / 2) + w.scrollLeft() + "px");
    });
};

Here's my go at it. I ended up using it for my Lightbox clone. The main advantage of this solution is that the element will stay centered automatically even if the window is resized making it ideal for this sort of usage.

$.fn.center = function() {
    this.css({
        'position': 'fixed',
        'left': '50%',
        'top': '50%'
    });
    this.css({
        'margin-left': -this.outerWidth() / 2 + 'px',
        'margin-top': -this.outerHeight() / 2 + 'px'
    });

    return this;
}

I like adding functions to jQuery so this function would help:

jQuery.fn.center = function () {
    this.css("position","absolute");
    this.css("top", Math.max(0, (($(window).height() - $(this).outerHeight()) / 2) + 
                                                $(window).scrollTop()) + "px");
    this.css("left", Math.max(0, (($(window).width() - $(this).outerWidth()) / 2) + 
                                                $(window).scrollLeft()) + "px");
    return this;
}

Now we can just write:

$(element).center();

Demo: Fiddle (with added parameter)


I put a jquery plugin here

VERY SHORT VERSION

$('#myDiv').css({top:'50%',left:'50%',margin:'-'+($('#myDiv').height() / 2)+'px 0 0 -'+($('#myDiv').width() / 2)+'px'});

SHORT VERSION

(function($){
    $.fn.extend({
        center: function () {
            return this.each(function() {
                var top = ($(window).height() - $(this).outerHeight()) / 2;
                var left = ($(window).width() - $(this).outerWidth()) / 2;
                $(this).css({position:'absolute', margin:0, top: (top > 0 ? top : 0)+'px', left: (left > 0 ? left : 0)+'px'});
            });
        }
    }); 
})(jQuery);

Activated by this code :

$('#mainDiv').center();

PLUGIN VERSION

(function($){
     $.fn.extend({
          center: function (options) {
               var options =  $.extend({ // Default values
                    inside:window, // element, center into window
                    transition: 0, // millisecond, transition time
                    minX:0, // pixel, minimum left element value
                    minY:0, // pixel, minimum top element value
                    withScrolling:true, // booleen, take care of the scrollbar (scrollTop)
                    vertical:true, // booleen, center vertical
                    horizontal:true // booleen, center horizontal
               }, options);
               return this.each(function() {
                    var props = {position:'absolute'};
                    if (options.vertical) {
                         var top = ($(options.inside).height() - $(this).outerHeight()) / 2;
                         if (options.withScrolling) top += $(options.inside).scrollTop() || 0;
                         top = (top > options.minY ? top : options.minY);
                         $.extend(props, {top: top+'px'});
                    }
                    if (options.horizontal) {
                          var left = ($(options.inside).width() - $(this).outerWidth()) / 2;
                          if (options.withScrolling) left += $(options.inside).scrollLeft() || 0;
                          left = (left > options.minX ? left : options.minX);
                          $.extend(props, {left: left+'px'});
                    }
                    if (options.transition > 0) $(this).animate(props, options.transition);
                    else $(this).css(props);
                    return $(this);
               });
          }
     });
})(jQuery);

Activated by this code :

$(document).ready(function(){
    $('#mainDiv').center();
    $(window).bind('resize', function() {
        $('#mainDiv').center({transition:300});
    });
);

is that right ?

UPDATE :

From CSS-Tricks

.center {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%); /* Yep! */
  width: 48%;
  height: 59%;
}

I would recommend jQueryUI Position utility

$('your-selector').position({
    of: $(window)
});

which gives you much more possibilities than only centering ...


I would use the jQuery UI position function.

See working demo.

<div id="test" style="position:absolute;background-color:blue;color:white">
    test div to center in window
</div>

If i have a div with id "test" to center then the following script would center the div in the window on document ready. (the default values for "my" and "at" in the position options are "center")

<script type="text/javascript">
$(function(){
  $("#test").position({
     of: $(window)
  });
};
</script>

Lot's of ways to do this. My object is kept hidden with display:none just inside the BODY tag so that positioning is relative to the BODY. After using $("#object_id").show(), I call $("#object_id").center()

I use position:absolute because it is possible, especially on a small mobile device, that the modal window is larger than the device window, in which case some of the modal content could be inaccessible if positioning was fixed.

Here's my flavor based on other's answers and my specific needs:

$.fn.center = function () {
        this.css("position","absolute");

        //use % so that modal window will adjust with browser resizing
        this.css("top","50%");
        this.css("left","50%");

        //use negative margin to center
        this.css("margin-left",(-1*this.outerWidth()/2)+($(window).scrollLeft())+"px");
        this.css("margin-top",(-1*this.outerHeight()/2)+($(window).scrollTop())+"px");

        //catch cases where object would be offscreen
        if(this.offset().top<0)this.css({"top":"5px","margin-top":"0"});
        if(this.offset().left<0)this.css({"left":"5px","margin-left":"0"});

        return this;
    };

No need jquery for this

I used this to center Div element. Css Style,

.black_overlay{
    display: none;
    position: absolute;
    top: 0%;
    left: 0%;
    width: 100%;
    height: 100%;
    background-color: black;
    z-index:1001;
    -moz-opacity: 0.8;
    opacity:.80;
    filter: alpha(opacity=80);
}

.white_content {
    display: none;
    position: absolute;
    top: 25%;
    left: 25%;
    width: 50%;
    height: 50%;
    padding: 16px;
    border: 16px solid orange;
    background-color: white;
    z-index:1002;
    overflow: auto;
}

Open element

$(document).ready(function(){
    $(".open").click(function(e){
      $(".black_overlay").fadeIn(200);
    });

});

Please use this:

$(window).resize(function(){
    $('.className').css({
        position:'absolute',
        left: ($(window).width() - $('.className').outerWidth())/2,
        top: ($(window).height() - $('.className').outerHeight())/2
    });
});

// To initially run the function:
$(window).resize();

The transition component of this function worked really poorly for me in Chrome (didn't test elsewhere). I would resize the window a bunch and my element would sort of scoot around slowly, trying to catch up.

So the following function comments that part out. In addition, I added parameters for passing in optional x & y booleans, if you want to center vertically but not horizontally, for example:

// Center an element on the screen
(function($){
  $.fn.extend({
    center: function (x,y) {
      // var options =  $.extend({transition:300, minX:0, minY:0}, options);
      return this.each(function() {
                if (x == undefined) {
                    x = true;
                }
                if (y == undefined) {
                    y = true;
                }
                var $this = $(this);
                var $window = $(window);
                $this.css({
                    position: "absolute",
                });
                if (x) {
                    var left = ($window.width() - $this.outerWidth())/2+$window.scrollLeft();
                    $this.css('left',left)
                }
                if (!y == false) {
            var top = ($window.height() - $this.outerHeight())/2+$window.scrollTop();   
                    $this.css('top',top);
                }
        // $(this).animate({
        //   top: (top > options.minY ? top : options.minY)+'px',
        //   left: (left > options.minX ? left : options.minX)+'px'
        // }, options.transition);
        return $(this);
      });
    }
  });
})(jQuery);

This is untested, but something like this should work.

var myElement = $('#myElement');
myElement.css({
    position: 'absolute',
    left: '50%',
    'margin-left': 0 - (myElement.width() / 2)
});

To center the element relative to the browser viewport (window), don't use position: absolute, the correct position value should be fixed (absolute means: "The element is positioned relative to its first positioned (not static) ancestor element").

This alternative version of the proposed center plugin uses "%" instead of "px" so when you resize the window the content is keep centered:

$.fn.center = function () {
    var heightRatio = ($(window).height() != 0) 
            ? this.outerHeight() / $(window).height() : 1;
    var widthRatio = ($(window).width() != 0) 
            ? this.outerWidth() / $(window).width() : 1;

    this.css({
        position: 'fixed',
        margin: 0,
        top: (50*(1-heightRatio)) + "%",
        left: (50*(1-widthRatio))  + "%"
    });

    return this;
}

You need to put margin: 0 to exclude the content margins from the width/height (since we are using position fixed, having margins makes no sense). According to the jQuery doc using .outerWidth(true) should include margins, but it didn't work as expected when I tried in Chrome.

The 50*(1-ratio) comes from:

Window Width: W = 100%

Element Width (in %): w = 100 * elementWidthInPixels/windowWidthInPixels

Them to calcule the centered left:

 left = W/2 - w/2 = 50 - 50 * elementWidthInPixels/windowWidthInPixels =
 = 50 * (1-elementWidthInPixels/windowWidthInPixels)

Why you don't use CSS for centering a div?

#timer_wrap{  
  position: fixed;
  left: 50%;
  top: 50%;
} 

You can use CSS alone to center like so:

Working Example

.center{
    position: absolute;
    height: 50px;
    width: 50px;
    background:red;
    top:calc(50% - 50px/2); /* height divided by 2*/
    left:calc(50% - 50px/2); /* width divided by 2*/
}
<div class="center"></div>

calc() allows you to do basic calculations in css.

MDN Documentation for calc()
Browser support table


i use this:

$(function() {
   $('#divId').css({
    'left' : '50%',
    'top' : '50%',
    'position' : 'absolute',
    'margin-left' : -$('#divId').outerWidth()/2,
    'margin-top' : -$('#divId').outerHeight()/2
  });
});

you're getting that poor transition because you're adjusting the position of the element every time the document is scrolled. What you want is to use fixed positioning. I tried that fixed center plugin listed above and that seems to do solve the problem nicely. Fixed positioning allows you to center an element once, and the CSS property will take care of maintaining that position for you every time you scroll.







layout