How can we center a popup window opened via JavaScript's window.open
function on the center of screen (the exact x and y coordinates of which will depend on the current screen resolution)?
SINGLE/DUAL MONITOR FUNCTION (credit to http://www.xtf.dk - thank you!)
UPDATE: It will also work on windows that aren't maxed out to the screen's width and height now thanks to @Frost!
If you're on dual monitor, the window will center horizontally, but not vertically... use this function to account for that.
const 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 width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
const systemZoom = width / window.screen.availWidth;
const left = (width - w) / 2 / systemZoom + dualScreenLeft
const top = (height - h) / 2 / systemZoom + dualScreenTop
const newWindow = window.open(url, title,
`
scrollbars=yes,
width=${w / systemZoom},
height=${h / systemZoom},
top=${top},
left=${left}
`
)
if (window.focus) newWindow.focus();
}
Usage Example:
popupCenter({url: 'http://www.xtf.dk', title: 'xtf', w: 900, h: 500});
CREDIT GOES TO: http://www.xtf.dk/2011/08/center-new-popup-window-even-on.html (I wanted to just link out to this page but just in case this website goes down the code is here on SO.)
PopupCenter('http://www.xtf.dk','xtf','200','300');
–
Artiodactyl window.screen
instead of screen
directly to avoid the error message by linter on no-restricted-globals
( @RubenStolk , @tony-m ) –
Plosion if (window.focus)
? Shouldn't you check that the new popup window has a focus method instead? –
Pothead dualScreenTop
? In my experience dual screen only messes up the x-axis (or is this only because my screens are next to each other?)... –
Canzone document.documentElement.clientWidth
(lack of null check) and also prompts a WebStorm fix for !== undefined
instead of != undefined
to prevent coercive type checking. –
Lavernlaverna var width
and var height
declaration you're missing a window
declaration. It's throwing an ESLint error for no-restricted-globals
. This is the screen.width
and screen.height
declaration respectively. –
Lavernlaverna systemZoom
level assumes that the browser window takes up the entire screen. When this assumption is violated, the function believes that we are zoomed in (equivalent to systemZoom
< 1), and consequently puts the window in the wrong place - often way over on one edge of the screen if the parent window is small. –
Forelli 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);
}
(screen.width / 2) - (w / 2)
= (screen.width - w) / 2
=> 2 calculations instead of 3 –
Thickset 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);
window.top.inner(Height|Width)
so that if a portion of the page is taken up by something like dev-tools that pane will be ignored and the content will centered against the web page –
Preeminent 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;
}
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.
window.top
struck me as a bit odd, too. I guess the one advantage(?) of his approach is that you can spawn popups from within other popups and they'll still get positioned in the center of the parent window. If you wanted to do that, for some reason... –
Forelli 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);
Number(...)
. –
Thrombophlebitis 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;
}
My recommendation is to use top location 33% or 25% from remaining space, and not 50% as other examples posted here do, mainly due to the window header. This will make it look better and more comfortable to the user.
Complete code:
function OpenPopupCenter(pageURL, title, w, h) {
var left = (screen.width - w) / 2;
var top = (screen.height - h) / 4; /* for 25%, divide by 4. for 33%, divide by 3, etc. */
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;
}
<button onclick="OpenPopupCenter('http://www.google.com', 'TEST!?', 800, 600);">Click here</button>
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%);
}
window.open
popup windows, not about modals. There's no way CSS is in any way relevant here. –
Forelli 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();
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;
}
screen.left
property in Firefox isn't just a Firefox version of window.screenLeft
; they're the coordinates of fundamentally different things (left screen edge and left window edge, respectively). The comment hints the author believed the two equivalent, but they aren't! –
Forelli (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';
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));
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 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);
}
window.screenLeft
and window.screenTop
give the coordinates of the top-left corner of the screen (relative to the left edge of the leftmost screen and the top edge of the topmost screen) but in fact they give the coordinates of the top-left corner of the browser window (again relative to the leftmost/topmost screen). The result is that if you try this with a non-maximised browser, the popup appears in wildly different places depending upon the parent window position, and isn't in the center of anything. –
Forelli The following approach will work in multi-monitor environments and/or when the browser window that the popup is triggered from is not maximised. It also adjusts the vertical position to account for the height of the address bar.
function centeredPopup(url, width, height) {
const topBarHeight = (outerHeight - innerHeight);
const top = screen.availTop + screen.availHeight / 2 - height / 2 - topBarHeight / 2;
const left = screen.availLeft + screen.availWidth / 2 - width / 2;
window.open(url, "_blank", `popup=true, width=${width}, height=${height}, top=${top}, left=${left}`);
}
Explanation and lots of caveats
Other answers on this page fail in multi-monitor environments when the browser window from which the popup is triggered is not on the primary monitor. Browsers will only let you spawn a popup on the same screen as the monitor that the triggering window is on, but the top
and left
arguments to window.open
express the coordinates of the popup in the entire combined area of all screens, treated as a single giant 2D space. When computing the coordinates for the popup, then, we need to compute how far it should be from the top-left of the current screen and then add on to that the coordinates of the top-left of the current screen, which we approximately get with screen.availTop
and screen.availLeft
.
(Some other answers use window.screenLeft
and window.screenTop
for this, but this is wildly wrong; these properties give the coordinates of the top-left of the browser window relative to the top-left of the primary screen, but the browser window might not be maximised and therefore its top-left corner could be at any point on the current screen.)
A nuance is that availLeft
, availTop
, availWidth,
and availHeight
give the top-left corner and size of the "available" region of the current screen. This region is what remains after you exclude any OS bars that windows aren't allowed to overlap, like the taskbar (if pinned) in Windows or the dock in Ubuntu. The center of this region won't necessarily be exactly identical to the true center of the screen but should be close (and may be what your users would prefer anyway). Positioning in a window in the true center of the screen while supporting multiple monitors is hard (but see the end of the answer for possible tweaks to kinda do so).
The availTop
and availLeft
properties of screen
used above are not standardized - but will nonetheless work in all browsers according to MDN.
Another nuance not accounted for by other answers is the height of the bits of the browser window that are above (or below) the page frame, like the URL bar. The height
argument to window.open
just specifies the size of the frame within the browser window that the page will render it, and is not inclusive of the URL bar; the true height of the popup window will therefore be greater than this. Failing to account for this results in popups being rendered below the center of the screen. We attempt to account for this here by computing the height of these bars in the current window (by subtracting window.innerHeight
from window.outerHeight
) and then blindly assuming that their height will be the same in the popup. This is actually probably an overcorrection most of the time, since popup windows have a tweaked UI with a smaller address bar (at least in Chrome on my machine), but overcorrecting for the address bar size at least leads to us positioning the popup above the center of the screen instead of below, which looks nicer.
Possible tweaks
To really position in the center of the screen and not the "available" region...
If for some reason you are particular about truly wanting to put the popup in the center of the screen, I see some possible tactics you could use, but they all have horrible downsides which is why I do not recommend them above.
One way would be to call getScreenDetails
and then use the top
, left
, height
, and width
properties of the currentScreen
instead of screen.availTop
, screen.availLeft
, screen.availHeight
, screen.availWidth
. However, getScreenDetails
is not currently available in Firefox and requires the user to grant the website a scary-sounding permission to "Manage windows on all your displays" on Chrome. I imagine that for approximately 100% of developers these drawbacks make this alternative a non-option, and grossly worse than just using the screen.availXXX
properties.
If you'd like to at least get the positioning exact sometimes, you could check if screen.isExtended === false
, and if so, position the popup relative to screen origin (0, 0) (instead of (screen.availLeft
, screen.availTop
)) and height/width screen.height
and screen.width
(instead of screen.availWidth
and screen.availHeight
). If screen.isExtended
is true
or undefined
, you'd fall back to the logic at the start of my answer. screen.isExtended
isn't available in some browsers (e.g. Firefox) though, so this fix roughly only helps single-monitor Chrome and Edge users.
Finally, you could also attempt to heuristically guess where the true top and left edges of the screen are. For instance, if screen.availLeft
or screen.availTop
are less than 100, probably the actual left or top edge of the screen is at 0 and you could tweak the code above to assume this.
I don't think any of these are good ideas, but wanted to outline options in case you are fanatical about putting your popup in the center of the screen and not just the available area.
To more accurately adjust for the height of the address bar
You can spawn the popup (with e.g. const popup = window.open(...)
, then check the top bar height a while after it's spawned (popup.outerHeight - popup.innerHeight
) and adjust the positioning accordingly using popup.moveTo
. (moveTo
docs)
There are once again nasty problems with such a trick that in my view make it inadvisable, though. It takes some time for popup.outerHeight
to return anything other than 0
, so you can't do this synchronously. Also, if your popup is cross-origin, the Same Origin Policy will block you from reading its height. In my opinion it is best to simply live with the imperfections of the simple centeredPopup
function at the start of my answer rather than try to fix them with hacks like this, but that's your call.
availTop
property of the ScreenDetailed
interface is not available in Firefox, but that's not what we're using when we access window.screen.availTop
. Instead we're accessing the property described in the "Note" on the linked page: "A non-standard implementation of the availTop property is available on the Screen
interface in all browsers." –
Forelli 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();
}
}
menubar
in the windowFeatures
string but fixing that doesn't fix the brokenness I observe above.) –
Forelli 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>
Image For Popup Code. updated on 2023 javascript for dual screen
const fucntionPop =()=>{
const popupWidth = 600;
const popupHeight = 700;
const dualScreenLeft = window.screenLeft || window.screenX || 0;
const dualScreenTop = window.screenTop || window.screenY || 0;
const screenWidth = window.screen.width;
const screenHeight = window.screen.height;
const left = (screenWidth - popupWidth) / 2 + dualScreenLeft;
const top = (screenHeight - popupHeight) / 2 + dualScreenTop;
const popupFeatures = `width=${popupWidth},height=${popupHeight},left=${left},top=${top}`;
return window.open(
`http://localhost:3001/?token=${getToken()}&apiKey=${getApiKey()}`, // replace with your URL
'_blank',
popupFeatures
);
}
window.screenLeft
and window.screenTop
give the coordinates for the top-left corner of the screen, but actually they (perhaps perversely, given their names) give the coordinates for the top-left corner of the browser window; all the logic using them is nonsensical with this in mind. It just happens to kinda work when the parent window is maximised, but you can't rely on that. –
Forelli .center{
left: 50%;
max-width: 350px;
padding: 15px;
text-align:center;
position: relative;
transform: translateX(-50%);
-moz-transform: translateX(-50%);
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
-o-transform: translateX(-50%);
}
© 2022 - 2024 — McMap. All rights reserved.