跨越整个浏览器宽度的横条

Avatar of Chris Coyier
Chris Coyier 发布

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

更新于 2014年12月17日,作者 Parker Bennett

随着文本内容的行长变长,阅读起来可能会更困难。因此,当视口变宽时,限制内容宽度是一种常见的做法。通常,这是通过为内容设置一个max-width并将其居中来实现的,无论是包装在一个包装元素中,还是逐节进行。

但是,如果我们希望某个元素在视觉上扩展到覆盖视口的整个宽度,例如标题或单个标题的背景颜色,该怎么办呢?

一种方法是为我们想要宽度受限的内容使用内部包装器,但将外部元素保持在100%宽度。但是,这会增加额外的标记,并且(可以说,令人惊讶的是)非语义化

<header>
  <div class="wrap">
    <h2>Header</h2>
  </div>
</header>

<h3 class="full-width">
  <div class="wrap">Heading</div>
</h3>
<div class="wrap">
  <p>... text ... </p>
</div>
header, .full-width {
  width: 100%;
  background: #ccc;
}
.wrap {
  width: 80%;
  max-width: 24em;
  margin: 0 auto;
  padding: 0.25em 0.625em;
}

最好用语义方式(例如,main或section)包装内容,并根据需要在视觉上分割标题。以下是一些我们可以使用的方法

使用负边距

一种简单的方法(来自Timothy Mackey)使用负边距和填充来向两个方向扩展背景。为了避免触发水平滚动,我们需要在htmlbody元素上都设置overflow-x:hidden

html, body {
  overflow-x: hidden;
}
.full-width-bar {
  margin: 0 -9999rem;
  /* add back negative margin value */
  padding: 0.25rem 9999rem;
  background: rgba(0, 0, 0, 0.5);
}

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的示例 使用负边距创建全宽横条

想要使全宽横条的颜色不同于标题背景颜色?一种方法是使用左右边框。但事实证明,超宽的边框存在一些问题。对于超过960px的边框,您需要将其精确设置为9600px或10240px(或等效的em),以避免Chrome中的错误。此外,您需要使用纯色,因为RGBa值在Safari中会显示一个小缝隙。这是因为包含元素居中时出现的舍入误差。

html, body {
  overflow-x: hidden;
}

.full-width-borders {
  /* also subtract section padding (1.5rem) */
  margin: 0 -601.5rem;
  /* add back section padding (1.5rem) */
  padding: 0.25rem 1.5rem;
  background: red;
  /* border has to be solid, not RGBa */
  /* 9600px or equiv (600rem = 9600/16) */
  border-left: 600rem solid maroon;
  border-right: 600rem solid maroon;
}

查看 CodePen 上 Parker Bennett (@parkerbennett) 编写的示例 使用边框创建全宽横条

鉴于使用边框的繁琐性,让我们看看另一种方法

使用伪元素

通过向标题添加一个:before伪元素,您可以使用绝对定位和负z-index使标题后面的背景与全宽横条区分开来。这还允许我们为全宽横条使用RGBa。

.full-width-tinted {
  position: relative; /* for child pseudo-element */
  z-index: 0;
  margin: 0 -600rem;
  /* add back negative margin value */
  padding: 0.25rem 600rem;
  background: #666;
  background: rgba(0, 0, 0, 0.25);
}

.full-width-tinted:before {
  content: "";
  position: absolute;
  z-index: -1; /* behind parent */
  top: 0;
  bottom: 0;
  /* subtract h2 padding (1.5rem) */
  left: 598.5rem;
  right: 598.5rem;
  background: green;
}

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的示例 使用负边距创建全宽横条

在使用负z-index时需要稍微注意一下,因为它往往只在没有太多嵌套元素及其自身背景的简单情况下才能工作。

如果您需要更大的灵活性,您可以使用两个伪元素,:before:after,来分别向左和向右扩展标题背景。这样,背景可以包含不同的颜色、宽度或高度,仅向一个方向扩展,使用渐变淡出等等。

.full-width {
  position: relative; /* for the child pseudo-elements */
  /* negative offset = section padding */
  margin: 0 -30px;
  /* add back section padding value */
  padding: 0.25rem 30px;
  background: #333;
}
.full-width:before, .full-width:after {
  content: "";
  position: absolute;
  /* fill vertically */
  top: 0;
  bottom: 0;
  width: 9600px;
  right: 100%;
  background: green;
}
.full-width:after { 
  width: 320px;
  left: 100%;
  /* you're free to do something totally different here */
  background: green;
}

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的示例 使用伪元素创建全宽横条

使用盒子阴影

一种巧妙的方法来避免触发水平滚动是使用box-shadow生成背景扩展(至少在右侧)。Andreas 创建了一个此方法的演示

查看 CodePen 上 Andreas (@receter) 编写的示例 使用盒子阴影创建全宽浏览器横条

不幸的是,这方面存在一些问题。Charles Stuart 指出 Internet Explorer 11(v11.0.9600.17501)中存在一个错误,使得使用盒子阴影变得不可靠。似乎即使将模糊设置为0,IE 也会在盒子阴影上使用亚像素抗锯齿。

使用视口单位

Lisa 建议了一种方法,可以通过结合使用vwcalc()来避免触发水平滚动,这些方法现在已经拥有了相当可靠的浏览器支持。在合适的环境下它可能很有用(但尚未考虑诸如paddingmin-width之类的因素)。

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的示例 全宽横条