在有限宽度父元素中使用全宽容器

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

几个月前我收藏了 一条推文,因为它是一个货真价实的 CSS 技巧,而这正是我们在这里所热爱的。

问题是:**当我们在一个有限宽度的父元素内部时,如何创建一个全浏览器宽度的容器?**

起点

此图像宽度为 100%,因为它受限于父元素的宽度。

我们希望将其拉伸到与浏览器窗口完全一样宽。

以下是一些最小的假设标记

<!-- 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() 版本都需要父元素在浏览器中完全居中。**

您甚至可能会想:为什么要费心使用 rightmargin-right?确实,在从左到右的网站上您并不真正需要它,但如果存在任何机会发生 direction: rtl;,则您将需要右侧属性,因此同时拥有两者更可靠。

我将在此处放置此方法的一个分支,因为它似乎最有用。

查看 Chris Coyier 在 CodePen 上的笔 文章内部的全视口宽度图像(容器)@chriscoyier)。