¿Centrar una ventana emergente en la pantalla?

281

¿Cómo podemos centrar una ventana emergente abierta mediante la window.openfunción de JavaScript en el centro de la variable de pantalla a la resolución de pantalla seleccionada actualmente?

Zo Has
fuente

Respuestas:

459

FUNCIÓN DE MONITOR ÚNICO / DUAL (crédito a http://www.xtf.dk - ¡gracias!)

ACTUALIZACIÓN: ¡También funcionará en ventanas que no están maximizadas al ancho y la altura de la pantalla ahora gracias a @Frost!

Si tiene un monitor dual, la ventana se centrará horizontalmente, pero no verticalmente ... use esta función para dar cuenta de eso.

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();
}

Ejemplo de uso:

popupCenter({url: 'http://www.xtf.dk', title: 'xtf', w: 900, h: 500});  

EL CRÉDITO VA A: http://www.xtf.dk/2011/08/center-new-popup-window-even-on.html (solo quería vincular a esta página, pero en caso de que este sitio web caiga el código está aquí en SO, ¡salud!)

Tony M
fuente
77
Después de jugar un poco, esto no funciona tan bien como pensaba. La respuesta más simple y exceptuada funciona mucho mejor. Esto solo funciona si la página de inicio está maximizada.
Bart
8
Gracias por el crédito, he hecho que mi ejemplo funcione en ventanas minimizadas ahora: xtf.dk/2011/08/center-new-popup-window-even-on.html
Frost
10
Utiliza variables globales (ancho / alto), ¡ay!
Ruben Stolk
13
Pregunta original publicada en 2010, solución original publicada en 2010. Mi comentario sobre la solución original sobre no funcionar en el monitor dual publicado en 2013, mi respuesta para el monitor dual publicado en 2013. Su comentario sobre el monitor triple en 2015. Ahora debe responder por una solución de triple monitor en 2015. A este ritmo, tendremos una respuesta para 5 monitores en 2020, 6 monitores en 2025, 7 monitores en 2030 ... ¡sigamos este ciclo!
Tony M
2
@TonyM He actualizado la respuesta. ¡Sí, el ciclo debe continuar!
Zo Has
329

pruébalo así:

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);
} 
oezi
fuente
17
Esta función no funciona en una configuración de monitor dual. He publicado una solución de monitor único y doble a continuación.
Tony M
1
Me gustaría confirmar esto: var left = (screen.width / 2) - (w / 2); var top = (screen.height / 2) - (h / 2); ¿No volverá left = 0 y top = 0 ??? Suponiendo que w es igual a screen.width y h es igual a screen.height ... ¿Estoy en lo correcto o incorrecto aquí?
mutanic
1
@mutanic w / h se refiere al tamaño de la ventana emergente, no a la pantalla.
Mahn
2
No se centra en mi segundo monitor (que está ARRIBA del principal). La respuesta para la pantalla dual también falla.
vsync
2
Esto no funcionará si desea centrar la ventana en el medio del navegador, en lugar de en el medio de la pantalla (si, por ejemplo, el usuario ha cambiado el tamaño de su navegador a la mitad). Para centrarse dentro del navegador, reemplace screen.width & screen.height con window.innerWidth & window.innerHeight
Jonathon Blok
71

Debido a la complejidad de determinar el centro de la pantalla actual en una configuración de varios monitores, una opción más fácil es centrar la ventana emergente sobre la ventana principal. Simplemente pase la ventana principal como otro parámetro:

function popupWindow(url, title, 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, 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}`);
}

Implementación:

popupWindow('google.com', 'test', window, 200, 100);
CrazyTim
fuente
Esta parece ser la técnica utilizada por Facebook para la ventana emergente en un botón para compartir.
Tim Tisdall
3
Esto funcionó perfectamente para mí en doble pantalla. Incluso al mover o cambiar el tamaño de la ventana, dice que es central para la ventana desde la que se abre. Esta debería ser la respuesta aceptada. Gracias.
Oli B
2
Estoy de acuerdo con @OliB: ¡esto funciona perfectamente y resolvió un problema de desarrollo reciente que teníamos! Debería ser la respuesta aceptada para 2019.
MrLewk
Hizo una modificación para ampliar las capacidades de esta función aquí . Incluye la opción de establecer el ancho y la altura en porcentaje o relación. También puede cambiar las opciones con un objeto (más fácil de administrar que una cadena)
SwiftNinjaPro
21

Fuente: 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;
} 
Entidad omnipotente
fuente
15

Si desea centrarlo en el marco en el que se encuentra actualmente, recomendaría esta función:

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 a la respuesta de Crazy Tim, pero no usa window.top. De esta manera, funcionará incluso si la ventana está incrustada en un iframe de un dominio diferente.

Taugenichts
fuente
13

Funciona muy bien en Firefox.
Simplemente cambie la variable superior a cualquier otro nombre e intente nuevamente

        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);
usuario1862764
fuente
66
Es totalmente innecesario hacerlo Number(...).
gustavohenke
6

Mi recomendación es usar la ubicación superior 33% o 25% del espacio restante,
y no 50% como otros ejemplos publicados aquí,
principalmente debido al encabezado de la ventana ,
que se ve mejor y más cómodo para el usuario,

código completo:

    <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>



mira esta línea:
var top = (screen.height - h) / 4; // para 25% - dividido por 4 | por 33% - dividido por 3

mr.baby123
fuente
6

Facebook utiliza el siguiente algoritmo para colocar su ventana emergente de inicio de sesión:

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;
}
Roland Soós
fuente
4

Puede usar css para hacerlo, solo asigne las siguientes propiedades al elemento que se colocará en el centro de la ventana emergente

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%);

}
Nikhil Mathew
fuente
3

Aquí hay una versión alternativa de la solución antes mencionada ...

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

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

  return newWindow;

  function getSpecs() {
    return 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left;
  }

  function getFirstNumber() {
    for(var i = 0, len = arguments.length; i < len; i++) {
      var value = arguments[i];

      if (typeof value === 'number') {
        return value;
      }
    }
  }
}
Mike T
fuente
3

Mi versión con ES6 JavaScript.
Funciona bien en Chrome y Chromium con configuración de pantalla dual.

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);
}

Ejemplo

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

(esto fue publicado en 2020)

Una extensión a la respuesta de CrazyTim

También puede establecer el ancho en un porcentaje (o una relación) para un tamaño dinámico. El tamaño absoluto aún se acepta.

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}`);
}

uso:

// 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';
SwiftNinjaPro
fuente
1
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>

Nota: debe usar Math.roundpara obtener el número entero exacto de ancho y alto.

Praveen Kumar
fuente
0

Basado en Facebook pero usa una consulta de medios en lugar de la expresión regular del agente de usuario para calcular si hay suficiente espacio (con algo de espacio) para la ventana emergente, de lo contrario pasa a pantalla completa. Las ventanas emergentes de Tbh en el móvil se abren como nuevas pestañas de todos modos

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;
}
Dominic
fuente
0

Esta solución híbrida funcionó para mí, tanto en configuración de pantalla única como dual

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);
}
Giuseppe Siragusa
fuente
0

Tuve un problema al centrar una ventana emergente en el monitor externo y window.screenX y window.screenY eran valores negativos (-1920, -1200) respectivamente. He intentado todo lo anterior de las soluciones sugeridas y funcionaron bien en monitores primarios. Me quería ir

  • Margen de 200 px para izquierda y derecha
  • Margen de 150 px para la parte superior e inferior

Esto es lo que funcionó para mí:

 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();
    }
}
Boston
fuente
-4

.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%);   
}

Alok Mishra
fuente