几个月前我收藏了 一条推文,因为它是一个货真价实的 CSS 技巧,而这正是我们在这里所热爱的。
问题是:**当我们在一个有限宽度的父元素内部时,如何创建一个全浏览器宽度的容器?**
起点

我们希望将其拉伸到与浏览器窗口完全一样宽。
以下是一些最小的假设标记
<!-- parent -->
<main>
<p>Stuff.</p>
<!-- container we want to be full width -->
<figure class="full-width">
<!-- could be whatever content -->
<img src="dog.jpg" alt="">
</figure>
</main>
注意事项
如果我们可以使用绝对定位,我们可以将容器设置为 left: 0;
和 width: 100%;
- 但我们不能,因为我们希望容器保持在正常的文档流中。
我们不能只是在每一侧应用一些负边距并将其向外拉吗?在某些情况下,我们可以!
已知百分比宽度
假设父容器宽度为 60% 且居中。这意味着在其两侧各留有 20% 的宽度。但是边距是根据父元素计算的,因此要将其向左拉到浏览器窗口的 20%,您需要父元素宽度的 1/3,所以…
main {
width: 60%;
margin: 0 auto;
/* creates 20% margins on either side */
}
.full-width {
/* 1/3 of 60% = the 20% margin on either side */
margin-left: -33.33%;
margin-right: -33.33%;
}
已知非百分比宽度
在大多数其他情况下,我们没有足够的信息来准确知道要使用负边距将全宽容器向外拉多远。
好吧,除非…
我们可以在 CSS 计算中使用浏览器窗口的宽度。**我们想要向左和向右“拉”的量是浏览器窗口宽度的一半加上父元素宽度的一半。**(假设父元素居中。)
所以,我们的父元素宽度为 500px
.full-width {
margin-left: calc(-100vw / 2 + 500px / 2);
margin-right: calc(-100vw / 2 + 500px / 2);
}
这样的固定宽度感觉有点危险信号(即在较窄的屏幕上会发生什么?),所有这些都可能包装在一个媒体查询中,使其仅在较大的屏幕上应用。
@media (min-width: 500px) {
main {
width: 500px;
margin: 0 auto;
}
.full-width {
margin-left: calc(-100vw / 2 + 500px / 2);
margin-right: calc(-100vw / 2 + 500px / 2);
}
}
由于我们的演示是一个图像,您也可以执行类似 .full-width img { width: 100%; }
的操作,以获得全覆盖。
如果它不太费脑筋,您可能会在 减少到
@media (min-width: $max-width) {
.full-width {
margin-left: calc(50% - 50vw);
margin-right: calc(50% - 50vw);
}
}
转换
由于这里可能不涉及动画,所以可能没有必要,但您可以使用变换将容器拉回到边缘。
@media (min-width: 40em) {
.full-width {
width: 100vw;
transform: translateX(calc((40em - 100vw)/2));
}
}
@supports()
以上想法来自 Brandon Mathis 的一个笔,他在其中将此想法与将其全部包装在 @supports
中结合起来。
/* See warning below */
@supports (width: 100vw) {
.full-width {
width: 100vw;
}
@media all and (min-width: 40rem) {
.full-width {
transform: translateX(calc((40rem - 100vw)/2));
}
}
}
这里的想法是,如果浏览器不支持视口单位,则所有这些都不会应用。这样,您可以在 CSS 中的此内容之上提取回退行为,如果可以,则让它覆盖它。
看起来是个好主意,但在我的测试中,只有 Firefox 做到了这一点。Chrome 有时会错误地应用媒体查询(即使不应该应用)(截图)。(我说“有时”,因为它似乎重绘会“修复”它,只是不会向另一个方向应用媒体查询。)Edge 似乎根本没有应用媒体查询规则(截图)。也许嵌套的 @ 规则有点 buggy。
无需 calc()
Sven Wolfermann 继续 Jon Neal 的想法,并提出了一个巧妙的变体,不需要 calc()
.full-width {
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}
这里的想法是:使用 left: 50%;
将容器**推**到浏览器窗口的正中间,然后使用负 -50vw
边距将其**拉**回左边缘。

非常聪明!这样,您根本不需要任何有关父元素宽度的信息。请注意,**此方法和 calc()
版本都需要父元素在浏览器中完全居中。**
您甚至可能会想:为什么要费心使用 right
和 margin-right
?确实,在从左到右的网站上您并不真正需要它,但如果存在任何机会发生 direction: rtl;
,则您将需要右侧属性,因此同时拥有两者更可靠。
我将在此处放置此方法的一个分支,因为它似乎最有用。
查看 Chris Coyier 在 CodePen 上的笔 文章内部的全视口宽度图像(容器)(@chriscoyier)。
这真是太棒了,谢谢!
Chrome 的错误可能是由于在文档的
overflow
设置为auto
以外的其他值时无法正确测量视口单位。我也遇到了 使用此技术的问题(向下滚动到“哦,不,一个水平滚动条”),并且看起来他们从那时起就没有修复它。我刚刚在阅读 这里 的文本时发现了原因
“在某些时候,项目将溢出视口。在 Windows 上,将出现一个滚动条,稍微缩小视口。在 OS X 上,一个智能滚动条将显示在内容之上,并自动显示和隐藏,因此不会影响视口。这与什么相关?以下是规范的一部分:”
同样地,这里有一个代码笔,可以使用 bootstrap3 将图像大小调整为视口的一半..也许这对某些人有用
http://codepen.io/Colir/pen/GJWYEy
非常酷,但如果可以的话,请不要这样做
可能需要解释一下为什么不这样做。
很棒的总结,Chris!我写了 一篇关于这个主题的文章,尽管我完全错过了 Jonathan Neal 的推文!伟大的思想,等等。
就我个人而言,我更喜欢
calc
版本。允许我自夸一下 解释一下原因这可以用于电子邮件吗?
考虑到你通常甚至不能在电子邮件中安全地使用浮动元素,所以我不建议使用这种方法。在不支持的情况下,它可能会回退到典型的标准定位,但一些客户端会对电子邮件做出很奇怪的操作。
也许可以简单地添加一个回退方案?
不行。100% 和 50% 会参考父元素的宽度,从而抵消任何效果。
如果浏览器不支持 vw,就不要使用任何东西。
不幸的是,问题在于“全宽”图像始终会被垂直浏览器滚动条(约 25px)截断。有没有人有解决方案?
目前,每个人都只是使用 JS 或修改父容器的布局(以便仅对图像应用 width:100%)。
我也很好奇这一点。使用 calc() 是可能的。
.full-width {
width: calc(100vw – 25px);
position: relative;
left: 50%;
right: 50%;
margin-left: calc(-50vw + 12.5px);
margin-right: calc(-50vw + 12.5px);
}
@Vince
那么在操作系统和/或设置默认情况下将滚动条覆盖内容的设备上,右侧会出现 12.5px 的间隙,即每台没有插入标准鼠标的 Mac 和每台移动设备。
事实是,虽然这种技术在理想世界中肯定很完美,但视口单位的当前规范非常愚蠢,它阻止我们使用它,以及基于 vw 的网格。
请参阅 Gabriel Tadeu 的评论以了解有关规范的详细信息。
天才!你又一次做到了,Chris。
昨天我还在绞尽脑汁,思考如何在
.container
内部获得全宽彩色背景。你对这样的决定怎么看?
http://codepen.io/theexplay/pen/ZORvBE
附注:抱歉我的英语不好。
选择除图像之外的所有内容的不太酷的方法。
查看 David Bullock(@serkai)在 CodePen 上的 Pen 文章内全视口宽度图像(容器)——简单版本。
太棒了!谢谢!
我仍然想知道这个技巧在哪些地方有用……
假设你是一家出版物,你有一些很棒的照片,并且想要以 100% 的比例显示其中一些照片,那么撰写内容的人只需将图像放在文本的中间,然后“砰!”,就可以显示全宽图像了。
真的吗?你写过博客,想要一个出血边缘的图像吗?
非常棒的技巧,谢谢。顺便问一下,我想知道你是如何想到在许多语言中用培根和类似的词语填充的这种惊人的类似 Lorem ipsum 的文本的。:D
http://baconipsum.com/
谢谢,wefegererg!
这个解决方案怎么样?
http://codepen.io/anon/pen/VjdjVK
甚至还有 Zombie 和 skateipsum :)
是的——我发现 Chrome 中存在与该特定情况相关的错误——事实证明,
@supports
内部的@media
块在调整大小时没有重新评估。我发送了一个错误报告(并在博客中写了关于这个错误的文章),Chromium 的团队很快就修复了它——所以这种情况很快就会得到解决。:-)非常酷!不过我不得不说我更喜欢这种方法。
.full-width {
width: 100vw;
position: relative;
left: 50%;
transform: translateX(-50%);
}
太棒了!这太赞了!
太棒了!我甚至都没有想过这样做……将来会考虑使用它……=D
太棒了!
我去年创建了一个 CodePen 就是为了做到这一点。我使用 margin-left 和 translateX 做到了这一点。
http://codepen.io/ahmadawais/pen/avBwBz
太棒了!
很棒的文章!
提醒一下,CodePen 中缺少图像。
虽然这是一个很棒且简单的解决方案,但它也感觉有点“hacky”,以这种方式打破了常规。如果你可以控制你的标记,我想让段落等内容有一个容器,并让你的图像宽度为 100% 始终是最棒的。
感谢“无需 calc”的解决方案!
以下是一个额外的提示:如果你想在任何全宽元素内包含内容,你可以将你的主包装器属性应用于任何 .full-width 元素的所有子元素,如下所示。