使用 Flexbox 创建包含固定宽度、可变宽度和剩余空间元素的导航栏

Avatar of Chris Coyier
Chris Coyier 发布

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

Izak Filmalter 写信给我

在我正在开发的网站上,有一个导航栏包含几个元素:一个搜索输入框、用户的全名和一些图标。 图标的宽度是固定的,用户名是可变的,而搜索栏应该占据可用空间的剩余部分。

无论我尝试什么,当用户名长度动态变化时,我都无法让搜索栏使用所有可用空间且不多不少。

我已经回复了 Izak,但我也将在此处分享该解决方案。 **Flexbox!** 我相信,Flexbox 是一款出色的布局工具,这一点并不奇怪。 我 有一篇关于 Flexbox 的指南,可以作为很好的参考。

好消息是,使用 Flexbox 布局可以轻松实现这一点。 我们将详细说明,但以下几行代码基本上就可以完成任务。

.bar {
  display: flex;
}
.search {
  flex: 1;
} 

分步指南

让我们假设使用以下标记。 这里没有什么意外。 我只是将搜索输入框包裹在一个 <div> 中,主要是因为我不习惯将输入框作为 Flex 项目,但您可能无论如何都需要一个包装元素(如 <form>),因为您可能会有一个 <label> 等等。

<div class="bar">
  <div class="icon icon-1"></div>
  <div class="icon icon-2"></div>
  <div class="icon icon-3"></div>
  <div class="username">
    Emily Blunt
  </div>
  <div class="search">
    <input type="search" placeholder="search..." />
  </div>
</div>
没有任何 CSS

使它们水平对齐并居中

.bar {
  display: flex;
  align-items: center;
}

让我们确保该栏与浏览器窗口一样宽。 我们可以轻松地设置 100% 的宽度。 但每当我这样做时,就会提醒我应该 使用 box-sizing: border-box; ——否则,该容器上的任何填充或边框都会使其宽度超过 100%,这是最糟糕的情况。

*, *:before, *:after {
  box-sizing: inherit;
}
html {
  box-sizing: border-box;
}
.bar {
  display: flex;
  align-items: center;
  width: 100%;
  background: #eee;
  padding: 20px;
}

对于最终技巧

.search {
  /* take up the rest of the remaining space */
  flex: 1;
}
.search input {
  width: 100%;
}

它将按以下方式工作

现在我们进入了 Flexbox 世界,我们可以随意更改事物的顺序并获得相同的良好间距效果。 order 属性默认为 0,因此任何正值都会将该 Flex 项目置于末尾,负值则置于开头。 然后按顺序排列,就像 z-index 一样。

.bar-2 .username {
  order: 2;
}
.bar-2 .icon-3 {
  order: 3;
}

.bar-3 .search {
  order: -1;
}
.bar-3 .username {
  order: 1;
}

响应式设计 (RWD) 奖励!

Flexbox 对响应式设计非常友好,因为我们可以非常轻松地交换顺序和大小,甚至可以换行。 让我们使我们的演示换行,并使搜索和用户名宽度充满整个容器。

@media (max-width: 650px) {
  .bar {
    flex-wrap: wrap;
  }
  .icon {
    order: 0 !important;
  }
  .username {
    order: 1 !important;
    width: 100%;
    margin: 15px;
  }
  .search {
    order: 2 !important;
    width: 100%;
  }
}

演示

开始吧

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的笔 Flexbox 重新排序

浏览器支持

如今,提到 Flexbox 就不得不提浏览器支持问题。 与往常一样,您可以查阅 Can I Use。 IE 9 是剩下的最大限制因素。 如果您需要支持它,则必须找到其他方法。 否则,在 旧/新/过渡 语法之间,您 会没事的。 我们在这里没有使用任何奇怪的东西。

诀窍只是 使用 Autoprefixer,它可以很好地处理 Flexbox。 使用它时,此演示中的 Flexbox 属性/值变为

.bar {
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-align-items: center;
  -ms-flex-align: center;
  align-items: center;
}

.search {
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
}
.bar-2 .username {
  -webkit-order: 2;
  -ms-flex-order: 2;
  order: 2;
}

但我需要更好的回退方案!

一种可能性是使用 Modernizr 检测 Flexbox 支持。 它将在 html 元素上放置一个类名,例如

<html class="no-flexbox">

您可以使用它来使用不同的布局技术。

.no-flexbox .bar {
  display: table;
  border-spacing: 15px;
  padding: 0;
}
.no-flexbox .bar > * {
  display: table-cell;
  vertical-align: middle;
  white-space: nowrap;
}
.no-flexbox .username {
  width: 1px;
}

效果很好。

这不是唯一可能的方法。 您可以使用内联块或浮动以及使用 JavaScript 测量内容。 或者您可以使用一个真正的表格。 网页,兄弟,总有办法。