Bootstrap 3模态框垂直居中位置

290

这是一个双重问题:

  1. 当您不知道模态框的确切高度时,如何使其垂直居中?

  2. 如果模态框超出屏幕高度,是否可以将模态框居中并在模态框主体中使用overflow:auto属性?

我尝试过使用以下内容:

.modal-dialog {
  height: 80% !important;
  padding-top:10%;
}

.modal-content {
  height: 100% !important;
  overflow:visible;
}

.modal-body {
  height: 80%;
  overflow: auto;
}

当内容远大于竖屏幕尺寸时,这为我提供了所需的结果,但对于小型模态框内容来说,它几乎无法使用。


1
@Heiken,由于某种原因,这让我在屏幕上跳下来了,我正在使用Chrome。 - Sven van den Boogaart
34个回答

396
.modal {
  text-align: center;
}

@media screen and (min-width: 768px) { 
  .modal:before {
    display: inline-block;
    vertical-align: middle;
    content: " ";
    height: 100%;
  }
}

.modal-dialog {
  display: inline-block;
  text-align: left;
  vertical-align: middle;
}

稍微调整一下 .fade 类,以确保它出现在窗口的顶部边界而不是中心位置


我错过了这一点,实际上是错误覆盖了它。谢谢你指出了它在幕后实际起作用。 - Dorian
4
我说明一下,在移动设备上这个并不太好用。因为定义":after"的高度为100%,会自动将模态框移到页面下方。我刚刚解决了这个问题,声明.modal {display: flex! Important;} .modal-dialog {margin: auto}。92.97%的人已经支持使用这个CSS属性,但是对于一般支持可以使用JavaScript来设置边距。 - Walter Chapilliquen - wZVanG
23
非常好,但我建议仅在宽度大于768像素时使用它,并在移动设备上保留默认设置。当屏幕高度较小时,顶部位置是模态框的最佳位置。我还调整了动画效果,使其从中心出现。如果有人需要,下面是一个工作示例链接:http://codepen.io/anon/pen/zGBpNq - bwitkowicz
这个解决方案将模态窗口向右移动2像素,原因是:before元素。但是可以通过为:after添加相同的代码来解决这个问题。 - Cypher
它运行得非常好。但是,您能否更详细地解释一下为什么这个设置有效,因为我对CSS和布局还很陌生。特别是为什么需要 display: inline-block - macemers
显示剩余2条评论

155

1. 当你不知道模态框的确切高度时,如何使模态框在垂直方向上居中?

要实现在不声明高度的情况下绝对居中 Bootstrap 3 模态框,你需要通过将以下代码添加到你的样式表中来覆盖 Bootstrap CSS:

.modal-dialog-center { /* Edited classname 10/03/2014 */
    margin: 0;
    position: absolute;
    top: 50%;
    left: 50%;
}

这将使模态对话框的左上角位于窗口中心。

我们必须添加此媒体查询,否则在小型设备上,模态边距会出现错误:

@media (max-width: 767px) {
  .modal-dialog-center { /* Edited classname 10/03/2014 */
    width: 100%;
  }
} 
现在我们需要使用JavaScript来调整它的位置。为此,我们给元素设置负的上边距和左边距,值应该等于其高度和宽度的一半。在这个例子中,我们将使用jQuery,因为它与Bootstrap一起使用。
$('.modal').on('shown.bs.modal', function() {
    $(this).find('.modal-dialog').css({
        'margin-top': function () {
            return -($(this).outerHeight() / 2);
        },
        'margin-left': function () {
            return -($(this).outerWidth() / 2);
        }
    });
});

更新(2015年01月10日):

Finik的答案上添加。感谢在未知情况下居中提供的帮助。

.modal {
  text-align: center;
  padding: 0!important;
}

.modal:before {
  content: '';
  display: inline-block;
  height: 100%;
  vertical-align: middle;
  margin-right: -4px; /* Adjusts for spacing */
}

.modal-dialog {
  display: inline-block;
  text-align: left;
  vertical-align: middle;
}

注意负的右外边距吗?这将消除inline-block添加的空间。那个空间会导致模态框在@media width < 768px下跳到页面底部。

2. 如果模态框超出屏幕高度,是否可能使其居中并在modal-body中使用overflow:auto?

可以通过为modal-body设置overflow-y:auto和max-height来实现此目的。这需要更多的工作才能使其正常工作。首先,在样式表中添加以下内容:

.modal-body {
    overflow-y: auto;
}
.modal-footer {
    margin-top: 0;
}

我们将再次使用jQuery来获取窗口高度,并首先设置modal-content的最大高度。然后我们必须通过将modal-header和modal-footer从modal-content中减去来设置modal-body的最大高度:

$('.modal').on('shown.bs.modal', function() {
    var contentHeight = $(window).height() - 60;
    var headerHeight = $(this).find('.modal-header').outerHeight() || 2;
    var footerHeight = $(this).find('.modal-footer').outerHeight() || 2;

    $(this).find('.modal-content').css({
        'max-height': function () {
            return contentHeight;
        }
    });

    $(this).find('.modal-body').css({
        'max-height': function () {
            return (contentHeight - (headerHeight + footerHeight));
        }
    });

    $(this).find('.modal-dialog').css({
        'margin-top': function () {
            return -($(this).outerHeight() / 2);
        },
        'margin-left': function () {
            return -($(this).outerWidth() / 2);
        }
    });
});

您可以在这里找到使用Bootstrap 3.0.3的演示版本:http://cdpn.io/GwvrJ

编辑:我建议使用更新版本以获得更好的响应式解决方案:http://cdpn.io/mKfCc

更新(2015年11月30日):

function setModalMaxHeight(element) {
  this.$element     = $(element);  
  this.$content     = this.$element.find('.modal-content');
  var borderWidth   = this.$content.outerHeight() - this.$content.innerHeight();
  var dialogMargin  = $(window).width() < 768 ? 20 : 60;
  var contentHeight = $(window).height() - (dialogMargin + borderWidth);
  var headerHeight  = this.$element.find('.modal-header').outerHeight() || 0;
  var footerHeight  = this.$element.find('.modal-footer').outerHeight() || 0;
  var maxHeight     = contentHeight - (headerHeight + footerHeight);

  this.$content.css({
      'overflow': 'hidden'
  });

  this.$element
    .find('.modal-body').css({
      'max-height': maxHeight,
      'overflow-y': 'auto'
  });
}

$('.modal').on('show.bs.modal', function() {
  $(this).show();
  setModalMaxHeight(this);
});

$(window).resize(function() {
  if ($('.modal.in').length != 0) {
    setModalMaxHeight($('.modal.in'));
  }
});

(更新于2015年11月30日 http://cdpn.io/mKfCc,以上编辑已生效)


1
非常好的回答和帖子!不过,这个能不能也做成动画呢?当它只是弹出时效果很棒,但是如果做成动画呢?我现在正在工作,无法立即测试,但我很想看到结果。 - scooterlord
1
你好!注意到了以下问题。当第一个弹窗首次打开时,右边距有误,直到调整大小后才正常。这个问题有什么想法吗? - scooterlord
我的错,我在 .modal 上使用了 overflow:hidden,导致滚动条宽度不同。 - scooterlord
遗憾的是,如果您将屏幕缩小并在窗口内滚动,则此方法无效。截图:http://take.ms/4m69x - Public Profile
1
@bernie 我在Browserstack上使用我的Codepen分支制作了屏幕截图,其中短模态框在文档准备就绪时打开:https://www.browserstack.com/screenshots/6011a6b37b406484bf676490cb53764106b16461 Browserstack目前不支持v9.3.x的屏幕截图,但我认为类似于您描述的情况可能会发生在iOS 6.0上(请参见iPad 3rd(6.0)(Portrait)的屏幕截图)。也许这是一个旧的错误,在v9.3.2中已经重新出现。如果您愿意,可以在https://forums.developer.apple.com/community/safari-and-web/ios-web-apps上提交错误报告。 - dimbslmh
显示剩余16条评论

42

我的解决方案

.modal-dialog-center {
    margin-top: 25%;
}

    <div id="waitForm" class="modal">
        <div class="modal-dialog modal-dialog-center">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
                    <h4 id="headerBlock" class="modal-title"></h4>
                </div>
                <div class="modal-body">
                    <span id="bodyBlock"></span>
                    <br/>
                    <p style="text-align: center">
                        <img src="@Url.Content("~/Content/images/progress-loader.gif")" alt="progress"/>
                    </p>   
                </div>
            </div>
        </div>
    </div>

你应该使用 padding-top。当你在遮罩层中点击时,margin 会破坏关闭操作。 - anvd
3
设置上边距为25%需要模态框的高度为50%。 - rebellion

34

只需使用display: flex即可轻松解决。

.modal-dialog {
  margin-top: 0;
  margin-bottom: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.modal.fade .modal-dialog {
  transform: translate(0, -100%);
}

.modal.in .modal-dialog {
  transform: translate(0, 0);
}

带前缀

.modal-dialog {
  margin-top: 0;
  margin-bottom: 0;
  height: 100vh;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -webkit-flex-direction: column;
      -ms-flex-direction: column;
          flex-direction: column;
  -webkit-box-pack: center;
  -webkit-justify-content: center;
      -ms-flex-pack: center;
          justify-content: center;
}

.modal.fade .modal-dialog {
  -webkit-transform: translate(0, -100%);
          transform: translate(0, -100%);
}
.modal.in .modal-dialog {
  -webkit-transform: translate(0, 0);
          transform: translate(0, 0);
}

2
这可以防止因为100vh高度而点击背景。对于“backdrop:'static'”设置是可以的。 - counterflow
这会导致淡出动画问题。 - Viswanath Lekshmanan

28

如果您愿意使用 flexbox,那么这将有助于解决它。

.modal-dialog {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
}

.modal-content {
  margin: 0 auto;
}

8
我发现这个答案对我非常有效。但是,如果你想让用户通过点击模态框背景关闭它,请确保将 pointer-events: none 添加到 .modal-dialog 并将 pointer-events: auto 添加到 .modal-content。因为 .modal-dialog {height: 100%} 覆盖了模态框上下的整个列,并且禁止用户在该区域内点击背景。 - wuct
结合@ChingTingWu的建议,最有效的方法是: - strider
那么 @ChingTingWu 的建议在哪里呢? - giovannipds
1
ChingTingWu 似乎已经改成了 @wuct。 - xiao
1
@giovannipds 抱歉,我已经更改了我的用户名,因为它更短更容易被标记。对于造成的困惑,我感到抱歉 :) - wuct
显示剩余2条评论

25

我的解决方案:

.modal.in .modal-dialog 
{
    -webkit-transform: translate(0, calc(50vh - 50%));
    -ms-transform: translate(0, 50vh) translate(0, -50%);
    -o-transform: translate(0, calc(50vh - 50%));
    transform: translate(0, 50vh) translate(0, -50%);
}

这似乎在Bootstrap 3中完美运作。为什么这不是被接受的答案?它比其他答案简单得多(4个CSS指令)。 - danielricecodes
@danielricecodes 我猜测可能是因为视口单位存在的问题。scooterlord提出的答案建议兼容IE9和iOS,这表明这可能是一个问题。如果您查看canIuse的问题页面,您会发现iOS和IE10及更早版本存在问题。我不是在赞同或反对这是否是正确答案,我只是指出为什么可能没有选择它作为答案。 - Malavos
1
这种方法存在一个问题,即当模态框具有可滚动内容(内容超出窗口大小)时。 - Steven Pribilinskiy
这应该是被接受的答案。到目前为止,这是唯一对我有效的解决方案。感谢您提供这个。 - shifu
如果您的模态内容超过屏幕高度(如果您的模态框需要滚动),那么这种方法将不起作用。 - Brett Gregson

25

我想出了一个纯CSS的解决方案!不过这是CSS3,也就是说不支持IE8或更低版本,但除此之外,它已在iOS、Android、IE9+、Chrome、Firefox和桌面版Safari上进行了测试并且可以正常工作。

我正在使用以下CSS:

.modal-dialog {
  position:absolute;
  top:50% !important;
  transform: translate(0, -50%) !important;
  -ms-transform: translate(0, -50%) !important;
  -webkit-transform: translate(0, -50%) !important;
  margin:auto 5%;
  width:90%;
  height:80%;
}
.modal-content {
  min-height:100%;
  position:absolute;
  top:0;
  bottom:0;
  left:0;
  right:0; 
}
.modal-body {
  position:absolute;
  top:45px; /** height of header **/
  bottom:45px;  /** height of footer **/
  left:0;
  right:0;
  overflow-y:auto;
}
.modal-footer {
  position:absolute;
  bottom:0;
  left:0;
  right:0;
}

这里有一个代码片段。 http://codepen.io/anon/pen/Hiskj

..选择这个作为正确答案,因为没有额外的重型Javascript,在有多个模态框的情况下也不会导致浏览器崩溃。


9
使用JavaScript的整个目的是获取模态框的未知高度。您的解决方案具有固定的80%高度,这并没有回答您自己的问题:“当您不知道模态框的确切高度时,如何将模态框在垂直居中位置?” - dimbslmh
1
高度维度被设置为限制模态框的最大高度与屏幕高度相比。然而,翻译的百分比是根据内容高度设置的。 - scooterlord
3
如果您想获得一个不改变模态框大小的解决方案,请尝试以下 CSS 解决方案:http://tweaks.klickagent.ch/#30.05.2014_TwitterBootstrapCenterModal。 - klickagent.ch
非常好!不过,它的方法与我所描述的不同。在你的情况下,整个模态框会上下移动,而在我的情况下,会创建一个溢出元素。不过还是非常棒的!我喜欢它! - scooterlord
这需要设置高度。这并不完全符合用户的要求。 - rebellion
显示剩余2条评论

22

添加这个简单的CSS也可以起作用。

.modal-dialog {
  height: 100vh !important;
  display: flex;
}

.modal-content {
  margin: auto !important;
  height: fit-content !important;
}

什么是fit-content? - Marc Roussel

20

在我的情况下,我所做的就是在我的CSS中设置模态框的高度,并将其设为顶部。

<div id="myModal" class="modal fade"> ... </div>

在我的CSS中我设置了:

#myModal{
    height: 400px;
    top: calc(50% - 200px) !important;
}

1
作为 CSS 的新手,这个答案似乎是最不可怕的,并且完成了工作。 - Oded Ben Dov
2
这并没有回答问题的第一部分:“..当您不知道模态框的确切高度时?” - natec

12

可以使用 CSS 来实现这个最简单的方法:

.modal-dialog {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    width:500px;
    height:300px;
}

就是这样。请注意,它只需要应用于.modal-dialog容器div。

演示:https://jsfiddle.net/darioferrer/0ueu4dmy/


7
由于固定的宽度和高度,移动设备上无法响应。 - counterflow
你的回答假设每个设备都有相同的屏幕分辨率。 - Patricio Rossi
不用客气。我假设你已经理解了这个例子,并且能够将其适应到每种情况中。 - Dario Ferrer
在Bootstrap v3.3.0中运行成功,谢谢。 - Amin Ghaderi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接