Центрировать всплывающее окно на экране?


281

Как мы можем центрировать всплывающее окно, открытое с помощью window.openфункции javascript, по центру экранной переменной в соответствии с текущим выбранным разрешением экрана?

Ответы:


459

ЕДИНАЯ / ДВОЙНАЯ ФУНКЦИЯ МОНИТОРА (благодарность http://www.xtf.dk - спасибо!)

ОБНОВЛЕНИЕ: Это также будет работать на окнах, которые не были увеличены до ширины и высоты экрана теперь благодаря @Frost!

Если вы используете двойной монитор, окно будет располагаться по центру по горизонтали, но не по вертикали ... используйте эту функцию, чтобы учесть это.

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

Пример использования:

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

КРЕДИТ ПРОДОЛЖАЕТСЯ: http://www.xtf.dk/2011/08/center-new-popup-window-even-on.html (я хотел просто указать ссылку на эту страницу, но на всякий случай код здесь на ТАК, ура!)


7
После некоторой игры это работает не так хорошо, как я думал. Более простой, исключенный ответ работает намного лучше. Это работает, только если стартовая страница развернута.
Барт

8
Спасибо за кредит, мой пример теперь работает с свернутыми окнами: xtf.dk/2011/08/center-new-popup-window-even-on.html
Frost

10
Использует глобальные переменные (ширина / высота), ой!
Рубен Столк

13
Оригинальный вопрос, опубликованный в 2010 году, оригинальное решение, опубликованное в 2010 году. Мой комментарий о первоначальном решении о неработающем двойном мониторе, опубликованный в 2013 году, мой ответ о двойном мониторе, опубликованном в 2013 году. Ваш комментарий о тройном мониторе в 2015 году. Теперь вам нужно ответить на решение с тремя мониторами в 2015 году. Таким образом, у нас будет ответ для 5 мониторов в 2020 году, 6 мониторов в 2025 году, 7 мониторов в 2030 году ... давайте продолжим этот цикл!
Тони М

2
@TonyM Я обновил ответ. Да, цикл должен продолжаться!
Зо имеет

329

попробуйте это так:

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

17
Эта функция не работает на установке с двумя мониторами. Я разместил решение для одного и двух мониторов ниже.
Тони М

1
Я хотел бы подтвердить это: var left = (screen.width / 2) - (w / 2); var top = (screen.height / 2) - (h / 2); Разве это не вернет left = 0 и top = 0 ??? Предполагая, что w равно screen.width, а h равно screen.height ... Я прав или нет?
Мутанец

1
@mutanic w / h указывает на размер всплывающего окна, а не на экран.
Mahn

2
Не центрируется на моем втором мониторе (который находится вверх от основного). Отвечать за двойной экран тоже не получается.
vsync

2
Это не будет работать, если вы хотите центрировать окно по центру браузера, а не по центру экрана (если, например, у пользователя размер браузера уменьшен до половины). Для центрирования в браузере замените screen.width & screen.height на window.innerWidth & window.innerHeight
Джонатон Блок

71

Из-за сложности определения центра текущего экрана в настройке с несколькими мониторами, более простым вариантом является центрирование всплывающего окна над родительским окном. Просто передайте родительское окно в качестве другого параметра:

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

Реализация:

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

Похоже, это техника, используемая Facebook для всплывающего окна с кнопкой «Поделиться».
Тим Тисдалл

3
Это отлично сработало для меня на двойном экране. Даже при перемещении или изменении размера окна, он говорит, что центральным является окно, из которого он открыт. Это должен быть принятый ответ. Спасибо.
Оли Б

2
Я согласен с @OliB - это прекрасно работает и решает недавнюю проблему с разработкой, которая у нас была! Должен быть принят ответ на 2019 год.
MrLewk

Сделано изменение, чтобы расширить возможности этой функции здесь . Он включает в себя возможность установить ширину и высоту в процентах или соотношении. Вы также можете изменить параметры объекта (легче управлять, чем строка)
SwiftNinjaPro


15

Если вы хотите расположить его по центру в текущем кадре, я бы порекомендовал эту функцию:

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

Похоже на ответ Безумного Тима, но не использует window.top. Таким образом, это будет работать, даже если окно встроено в iframe из другого домена.


13

Это очень хорошо работает в Firefox.
Просто измените верхнюю переменную на любое другое имя и попробуйте снова

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

6
Это совершенно не нужно делать Number(...).
густавогенке

6

Я рекомендую использовать верхнее расположение 33% или 25% от оставшегося пространства,
а не 50%, как другие примеры, размещенные здесь, в
основном из-за заголовка окна ,
который выглядит лучше и удобнее для пользователя,

полный код:

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



проверьте эту строку:
var top = (screen.height - h) / 4; // на 25% - делим на 4 | на 33% - делим на 3


6

Facebook использует следующий алгоритм для размещения своего всплывающего окна входа в систему:

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

4

Вы можете использовать css для этого, просто присвойте следующие свойства элементу, который будет размещен в центре всплывающего окна.

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

}

3

Вот альтернативная версия вышеупомянутого решения ...

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

3

Моя версия с ES6 JavaScript.
Хорошо работает на Chrome и Chromium с настройкой двойного экрана.

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

пример

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

2

(это было опубликовано в 2020 году)

Расширение до ответа CrazyTim

Вы также можете установить ширину в процентах (или пропорции) для динамического размера. Абсолютный размер все еще принят.

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

использование:

// 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';

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>

Примечание: вы должны использовать Math.roundдля получения точного целого числа ширины и высоты.


0

Основывается на Facebook, но использует медиа-запрос, а не регулярное выражение пользовательского агента, чтобы вычислить, достаточно ли места (с небольшим пространством) для всплывающего окна, в противном случае переходит на полный экран. Все равно всплывающие окна на мобильном телефоне открываются как новые вкладки.

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

0

Это гибридное решение работало для меня как на одном, так и на двух экранах.

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

0

У меня была проблема с центрированием всплывающего окна на внешнем мониторе, а window.screenX и window.screenY имели отрицательные значения (-1920, -1200) соответственно. Я испробовал все вышеперечисленное из предложенных решений, и они хорошо работали в основных мониторах. Я хотел уйти

  • 200 px поля для левой и правой
  • Поля 150 px для верха и низа

Вот что сработало для меня:

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.