[javascript] Center a popup window on screen?

How can we center a popup window opened via javascript window.open function on the center of screen variable to the currently selected screen resolution ?

This question is related to javascript

The answer is


function fnPopUpWindow(pageId) {
     popupwindow("hellowWorld.php?id="+pageId, "printViewer", "500", "300");
}

function popupwindow(url, title, w, h) {
    var left = Math.round((screen.width/2)-(w/2));
    var top = Math.round((screen.height/2)-(h/2));
    return window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, '
            + 'menubar=no, scrollbars=yes, resizable=no, copyhistory=no, width=' + w 
            + ', height=' + h + ', top=' + top + ', left=' + left);
}
<a href="javascript:void(0);" onclick="fnPopUpWindow('10');">Print Me</a>

Note: you have to use Math.round for getting the exact integer of width and height.


This would work out based on your screen size

<html>
<body>
<button onclick="openfunc()">Click here to open window at center</button>
<script>
function openfunc() {
windowWidth = 800;
windowHeight = 720;
 var left = (screen.width - windowWidth) / 2;
            var top = (screen.height - windowHeight) / 4;
            var myWindow = window.open("https://www.google.com",'_blank','width=' + windowWidth + ', height=' + windowHeight + ', top=' + top + ', left=' + left);
}
</script>
</body>
</html>

You can use css to do it, just give the following properties to the element to be placed in the center of the popup

element{

position:fixed;
left: 50%;
top: 50%;
-ms-transform: translate(-50%,-50%);
-moz-transform:translate(-50%,-50%);
-webkit-transform: translate(-50%,-50%);
 transform: translate(-50%,-50%);

}

This hybrid solution worked for me, both on single and dual screen setup

function popupCenter (url, title, w, h) {
    // Fixes dual-screen position                              Most browsers      Firefox
    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : window.screenX;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : window.screenY;
    const left = (window.screen.width/2)-(w/2) + dualScreenLeft;
    const top = (window.screen.height/2)-(h/2) + dualScreenTop;
    return window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+top+', left='+left);
}

My version with ES6 JavaScript.
Works well on Chrome and Chromium with dual screen setup.

function openCenteredWindow({url, width, height}) {
    const pos = {
        x: (screen.width / 2) - (width / 2),
        y: (screen.height/2) - (height / 2)
    };

    const features = `width=${width} height=${height} left=${pos.x} top=${pos.y}`;

    return window.open(url, '_blank', features);
}

Example

openCenteredWindow({
    url: 'https://stackoverflow.com/', 
    width: 500, 
    height: 600
}).focus();

_x000D_
_x000D_
.center{_x000D_
    left: 50%;_x000D_
    max-width: 350px;_x000D_
    padding: 15px;_x000D_
    text-align:center;_x000D_
    position: relative;_x000D_
    transform: translateX(-50%);_x000D_
    -moz-transform: translateX(-50%);_x000D_
    -webkit-transform: translateX(-50%);_x000D_
    -ms-transform: translateX(-50%);_x000D_
    -o-transform: translateX(-50%);   _x000D_
}
_x000D_
_x000D_
_x000D_


Source: http://www.nigraphic.com/blog/java-script/how-open-new-window-popup-center-screen

function PopupCenter(pageURL, title,w,h) {
  var left = (screen.width/2)-(w/2);
  var top = (screen.height/2)-(h/2);
  var targetWin = window.open (pageURL, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+top+', left='+left);
  return targetWin;
} 

try it like this:

function popupwindow(url, title, w, h) {
  var left = (screen.width/2)-(w/2);
  var top = (screen.height/2)-(h/2);
  return window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+top+', left='+left);
} 

Facebook use the following algorithm to position their login popup window:

function PopupCenter(url, title, w, h) {
  var userAgent = navigator.userAgent,
      mobile = function() {
        return /\b(iPhone|iP[ao]d)/.test(userAgent) ||
          /\b(iP[ao]d)/.test(userAgent) ||
          /Android/i.test(userAgent) ||
          /Mobile/i.test(userAgent);
      },
      screenX = typeof window.screenX != 'undefined' ? window.screenX : window.screenLeft,
      screenY = typeof window.screenY != 'undefined' ? window.screenY : window.screenTop,
      outerWidth = typeof window.outerWidth != 'undefined' ? window.outerWidth : document.documentElement.clientWidth,
      outerHeight = typeof window.outerHeight != 'undefined' ? window.outerHeight : document.documentElement.clientHeight - 22,
      targetWidth = mobile() ? null : w,
      targetHeight = mobile() ? null : h,
      V = screenX < 0 ? window.screen.width + screenX : screenX,
      left = parseInt(V + (outerWidth - targetWidth) / 2, 10),
      right = parseInt(screenY + (outerHeight - targetHeight) / 2.5, 10),
      features = [];
  if (targetWidth !== null) {
    features.push('width=' + targetWidth);
  }
  if (targetHeight !== null) {
    features.push('height=' + targetHeight);
  }
  features.push('left=' + left);
  features.push('top=' + right);
  features.push('scrollbars=1');

  var newWindow = window.open(url, title, features.join(','));

  if (window.focus) {
    newWindow.focus();
  }

  return newWindow;
}

(this was posted in 2020)

An extension to CrazyTim's answer

You can also set the width to a percentage (or a ratio) for a dynamic size. Absolute size is still accepted.

function popupWindow(url, title, w='75%', h='16:9', opts){
    // sort options
    let options = [];
    if(typeof opts === 'object'){
        Object.keys(opts).forEach(function(value, key){
            if(value === true){value = 'yes';}else if(value === false){value = 'no';}
            options.push(`${key}=${value}`);
        });
        if(options.length){options = ','+options.join(',');}
        else{options = '';}
    }else if(Array.isArray(opts)){
        options = ','+opts.join(',');
    }else if(typeof opts === 'string'){
        options = ','+opts;
    }else{options = '';}

    // add most vars to local object (to shorten names)
    let size = {w: w, h: h};
    let win = {w: {i: window.top.innerWidth, o: window.top.outerWidth}, h: {i: window.top.innerHeight, o: window.top.outerHeight}, x: window.top.screenX || window.top.screenLeft, y: window.top.screenY || window.top.screenTop}

    // set window size if percent
    if(typeof size.w === 'string' && size.w.endsWith('%')){size.w = Number(size.w.replace(/%$/, ''))*win.w.o/100;}
    if(typeof size.h === 'string' && size.h.endsWith('%')){size.h = Number(size.h.replace(/%$/, ''))*win.h.o/100;}

    // set window size if ratio
    if(typeof size.w === 'string' && size.w.includes(':')){
        size.w = size.w.split(':', 2);
        if(win.w.o < win.h.o){
            // if height is bigger than width, reverse ratio
            size.w = Number(size.h)*Number(size.w[1])/Number(size.w[0]);
        }else{size.w = Number(size.h)*Number(size.w[0])/Number(size.w[1]);}
    }
    if(typeof size.h === 'string' && size.h.includes(':')){
        size.h = size.h.split(':', 2);
        if(win.w.o < win.h.o){
            // if height is bigger than width, reverse ratio
            size.h = Number(size.w)*Number(size.h[0])/Number(size.h[1]);
        }else{size.h = Number(size.w)*Number(size.h[1])/Number(size.h[0]);}
    }

    // force window size to type number
    if(typeof size.w === 'string'){size.w = Number(size.w);}
    if(typeof size.h === 'string'){size.h = Number(size.h);}

    // keep popup window within padding of window size
    if(size.w > win.w.i-50){size.w = win.w.i-50;}
    if(size.h > win.h.i-50){size.h = win.h.i-50;}

    // do math
    const x = win.w.o / 2 + win.x - (size.w / 2);
    const y = win.h.o / 2 + win.y - (size.h / 2);
    return window.open(url, title, `width=${size.w},height=${size.h},left=${x},top=${y}${options}`);
}

usage:

// width and height are optional (defaults: width = '75%' height = '16:9')
popupWindow('https://www.google.com', 'Title', '75%', '16:9', {/* options (optional) */});

// options can be an object, array, or string

// example: object (only in object, true/false get replaced with 'yes'/'no')
const options = {scrollbars: false, resizable: true};

// example: array
const options = ['scrollbars=no', 'resizable=yes'];

// example: string (same as window.open() string)
const options = 'scrollbars=no,resizable=yes';

It works very well in Firefox.
Just change the top variable to any other name and try again

        var w = 200;
        var h = 200;
        var left = Number((screen.width/2)-(w/2));
        var tops = Number((screen.height/2)-(h/2));

window.open("templates/sales/index.php?go=new_sale", '', 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+tops+', left='+left);

The accepted solution does not work unless the browser takes up the full screen,

This seems to always work

  const popupCenterScreen = (url, title, w, h, focus) => {
    const top = (screen.height - h) / 4, left = (screen.width - w) / 2;
    const popup = window.open(url, title, `scrollbars=yes,width=${w},height=${h},top=${top},left=${left}`);
    if (focus === true && window.focus) popup.focus();
    return popup;
  }

Impl:

some.function.call({data: ''})
    .then(result =>
     popupCenterScreen(
         result.data.url,
         result.data.title, 
         result.data.width, 
         result.data.height, 
         true));

My recommendation is to use top location 33% or 25% from remaining space,
and not 50% as other examples posted here,
mainly because of the window header,
which look better and more comfort to the user,

complete code:

    <script language="javascript" type="text/javascript">
        function OpenPopupCenter(pageURL, title, w, h) {
            var left = (screen.width - w) / 2;
            var top = (screen.height - h) / 4;  // for 25% - devide by 4  |  for 33% - devide by 3
            var targetWin = window.open(pageURL, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
        } 
    </script>
</head>
<body>
    <button onclick="OpenPopupCenter('http://www.google.com', 'TEST!?', 800, 600);">click on me</button>
</body>
</html>



check out this line:
var top = (screen.height - h) / 4; // for 25% - devide by 4 | for 33% - devide by 3


Due to the complexity of determining the center of the current screen in a multi-monitor setup, an easier option is to center the pop-up over the parent window. Simply pass the parent window as another parameter:

function popupWindow(url, windowName, win, w, h) {
    const y = win.top.outerHeight / 2 + win.top.screenY - ( h / 2);
    const x = win.top.outerWidth / 2 + win.top.screenX - ( w / 2);
    return win.open(url, windowName, `toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=${w}, height=${h}, top=${y}, left=${x}`);
}

Implementation:

popupWindow('google.com', 'test', window, 200, 100);

I had an issue with centering a popup window in the external monitor and window.screenX and window.screenY were negative values (-1920, -1200) respectively. I have tried all the above of the suggested solutions and they worked well in primary monitors. I wanted to leave

  • 200 px margin for left and right
  • 150 px margin for top and bottom

Here is what worked for me:

 function createPopupWindow(url) {
    var height = screen.height;
    var width = screen.width;
    var left, top, win;

    if (width > 1050) {
        width = width - 200;
    } else {
        width = 850;
    }

    if (height > 850) {
        height = height - 150;
    } else {
        height = 700;
    }

    if (window.screenX < 0) {
        left = (window.screenX - width) / 2;
    } else {
        left = (screen.width - width) / 2;
    }

    if (window.screenY < 0) {
        top = (window.screenY + height) / 4;
    } else {
        top = (screen.height - height) / 4;
    }

    win=window.open( url,"myTarget", "width="+width+", height="+height+",left="+left+",top="+top+"menubar=no, status=no, location=no, resizable=yes, scrollbars=yes");
    if (win.focus) {
        win.focus();
    }
}

Based on Facebook's but uses a media query rather than user agent regex to calc if there is enough room (with some space) for the popup, otherwise goes full screen. Tbh popups on mobile open as new tabs anyway.

function popupCenter(url, title, w, h) {
  const hasSpace = window.matchMedia(`(min-width: ${w + 20}px) and (min-height: ${h + 20}px)`).matches;
  const isDef = v => typeof v !== 'undefined';
  const screenX = isDef(window.screenX) ? window.screenX : window.screenLeft;
  const screenY = isDef(window.screenY) ? window.screenY : window.screenTop;
  const outerWidth = isDef(window.outerWidth) ? window.outerWidth : document.documentElement.clientWidth;
  const outerHeight = isDef(window.outerHeight) ? window.outerHeight : document.documentElement.clientHeight - 22;
  const targetWidth = hasSpace ? w : null;
  const targetHeight = hasSpace ? h : null;
  const V = screenX < 0 ? window.screen.width + screenX : screenX;
  const left = parseInt(V + (outerWidth - targetWidth) / 2, 10);
  const right = parseInt(screenY + (outerHeight - targetHeight) / 2.5, 10);
  const features = [];

  if (targetWidth !== null) {
    features.push(`width=${targetWidth}`);
  }

  if (targetHeight !== null) {
    features.push(`height=${targetHeight}`);
  }

  features.push(`left=${left}`);
  features.push(`top=${right}`);
  features.push('scrollbars=1');

  const newWindow = window.open(url, title, features.join(','));

  if (window.focus) {
    newWindow.focus();
  }

  return newWindow;
}

If you want to center it on the frame you are currently in, I would recommend this function:

function popupwindow(url, title, w, h) {
    var y = window.outerHeight / 2 + window.screenY - ( h / 2)
    var x = window.outerWidth / 2 + window.screenX - ( w / 2)
    return window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=' + w + ', height=' + h + ', top=' + y + ', left=' + x);
} 

Similar to Crazy Tim's answer, but doesn't use window.top. This way, it will work even if the window is embedded in an iframe from a different domain.


Here is an alternate version of the aforementioned solution...

const openPopupCenter = (url, title, w, h) => {
  const getSpecs = (w, h, top, left) => {
    return `scrollbars=yes, width=${w}, height=${h}, top=${top}, left=${left}`;
  };

  const getFirstNumber = (potentialNumbers) => {
    for(let i = 0; i < potentialNumbers.length; i++) {
      const value = potentialNumbers[i];

      if (typeof value === 'number') {
        return value;
      }
    }
  };

  // Fixes dual-screen position
  // Most browsers use window.screenLeft
  // Firefox uses screen.left
  const dualScreenLeft = getFirstNumber([window.screenLeft, screen.left]);
  const dualScreenTop = getFirstNumber([window.screenTop, screen.top]);
  const width = getFirstNumber([window.innerWidth, document.documentElement.clientWidth, screen.width]);
  const height = getFirstNumber([window.innerHeight, document.documentElement.clientHeight, screen.height]);
  const left = ((width / 2) - (w / 2)) + dualScreenLeft;
  const top = ((height / 2) - (h / 2)) + dualScreenTop;
  const newWindow = window.open(url, title, getSpecs(w, h, top, left));

  // Puts focus on the newWindow
  if (window.focus) {
    newWindow.focus();
  }

  return newWindow;
}