使用CSS Flexbox 构建可靠实用的网站 Header

做者:Shadeed
译者:前端小智
来源:ishadeed
点赞再看,微信搜索 【大迁世界】关注这个没有大厂背景,但有着一股向上积极心态人。本文 GitHub https://github.com/qq44924588... 上已经收录,文章的已分类,也整理了不少个人文档,和教程资料。**

最近开源了一个 Vue 组件,还不够完善,欢迎你们来一块儿完善它,也但愿你们能给个 star 支持一下,谢谢各位了。css

github 地址:https://github.com/qq44924588...html

在 CSS3 没有普及的时候,建立一个网站 header 是一项既可怕又困难的任务 ?。那时,Flexbox 仍是个新东西,咱们不得不使用老方法,好比 floatclearfix技术。今天,状况彻底不一样了,Flexbox 获得了普遍的支持,大大的减小了咱们的开发工做,同时也为咱们提供了更多的可能性。前端

有人可能会说,如今 CSS3 这么普及,制做一个网站 header 不是很容易么 ?? 并不是如此,由于有一些有趣的挑战须要解决,在本文中咱们会介绍其中的几种。vue

简介

首先,这里所说的网站 Header 是用户访问网站时首先看到的内容之一。 一般,它包含logo或网站名称以及导航连接,以下所示:git

clipboard.png

无论 Header 的视觉设计如何,关键元素都是logo导航github

Flexbox

当 flexbox 应用于 Header 元素时,它将使全部子项目在同一行中。而后,你所须要作的就是应用justify-content来分配它们之间的间距。web

html面试

<header class="site-header">
  <a href="#" class="brand">Brand</a>
  <nav class="nav"></nav>
</header>

css微信

.site-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

很简单,对吧?对于这样的用例,是的,可能会比这更复杂。app

Header Wrapper

在上面的 lagonav 外没有包含一层 wrapper,这在大屏幕可能会出现问题。

clipboard.png

从上能够看到第一个Header太宽了,由于它没有内部 wrapper 相比第一个,第二个看起来好多了。因此,咱们能够对 HTML 进行以下调整。

<header class="site-header">
  <div class="wrapper site-header__wrapper">
    <a href="#" class="brand"><img src="logo.svg" alt="brand" /></a>
    <nav class="nav"></nav>
  </div>
</header>

flexbox应该移动到.site-header__wrapper元素中。

.site-header__wrapper {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

使用 flex-wrap

当屏幕很小的时候,能够水平滚动。见下图

clipboard.png

若是没有设置flex-wrap: wrap,当屏幕太小的时候就会出现水平滚动,若是不想这样,能够加上 flex-wrap: wrap` ?。

Header 的多种形式

我喜欢使用flexbox的缘由是它能够很容易地处理 header 设计的多种变化。基于前面的 header 设计,我扩展了 header 元素的一些选项,如添加按钮、搜索输入和更改子项目的顺序。

Header 变化 1

clipboard.png

假设我想要在导航连接旁边添加了一个按钮。这应该如何处理?咱们应该把它做为连接添加到导航栏中吗?仍是应该和导航分开?我更喜欢这样作。

<header class="site-header">
  <div class="wrapper site-header__wrapper">
    <a href="#" class="brand"><img src="logo.svg" alt="brand" /></a>
    <nav class="nav"></nav>
    <a href="/track-shipment" class="button">Track</a>
  </div>
</header>

这种状况下,咱们不能在用 justify-content: space-between来处理间隙,相反,我会在 nav 元素上使用 margin-left: auto

这样,它就会自动向右靠齐。

clipboard.png

将导航和 track 按钮分开对于移动设备很是有用,由于咱们须要保留该按钮并在其旁边显示一个移动切换按钮。

clipboard.png

Header 变化 2

clipboard.png

与第一个变化相似,这个变化增长了一个搜索输入,占用了剩余的可用空间。对于flexbox,这能够经过使用flex属性来实现。

html

<header class="site-header">
  <div class="wrapper site-header__wrapper">
    <a href="#" class="brand"><img src="logo.svg" alt="brand" /></a>
    <div class="search"></div>
    <nav class="nav"></nav>
    <a href="/track-shipment" class="button">Track</a>
  </div>
</header>

css

.search {
  flex: 1;
}

如今,搜索输入将填充 brandnav 之间的可用空间。 可是,这有一些限制。 在较小的视口上,header 将以下所示:

clipboard.png

搜索输入宽度不该小于此宽度,由于这样很难输入和查看全文。 下面有两种解决方案:

clipboard.png

我更喜欢第二种解决方案,由于它不会过早隐藏导航。 通常来讲,若是元素不影响布局,我会尽可能避免隐藏它。

Header 变化 3

clipboard.png

对于这个示例,HTML标记是相同的,可是 header 里的元素顺序是不一样的。咱们如何才能作到这一点? 你可能想到用 order 属性来解决这个问题 ?

html

<header class="site-header">
  <div class="wrapper site-header__wrapper">
    <a href="#" class="brand"><img src="logo.svg" alt="brand" /></a>
    <nav class="nav"></nav>
    <a href="/track-shipment" class="button">Track</a>
  </div>
</header>

css

.site-header {
  display: flex;
  justify-content: space-between;
}

.nav {
  order: -1;
}

clipboard.png

这样有个问题,间隔空间不会使 logo 居中,它只是分散项目之间的空间。

解决方案是给每一个子项一个flex: 1,这将在它们之间分配可用空间。

.brand,
.nav,
.button {
  flex: 1;
}

clipboard.png

这样,因为flex: 1,按钮元素变宽了, 解决此问题的惟一方法是将其包裹到另外一个元素中。

HTML

<header class="site-header">
  <div class="wrapper site-header__wrapper">
    <a href="#" class="brand"><img src="logo.svg" alt="brand" /></a>
    <nav class="nav"></nav>
    <div class="button-wrapper">
      <a href="/track-shipment" class="button">Track</a>
    </div>
  </div>
</header>

这样,咱们就能够将下面的logo和按钮居中。

.logo {
  text-align: center;
}

/* 不要介意这里的命名,这只是出于演示*/
.button-wrapper {
  text-align: end; /* end 等同于LTR语言中的right */
}

clipboard.png

可是,若是添加了更多导航连接,这种方法很容易失败。咱们须要确保导航连接的数量不会超过特定的限制。下面一个logo偏离中心的例子 ?:

clipboard.png

正如在上图中看到的,logo没有居中。因此要记住这一点,以免这种意想不到的问题 ?。

使用 Flexbox 构建 Header 的有用技巧

flex-basis

若是某个元素须要在移动设备上占据整个宽度(不能隐藏的重要导航),我会使用flex-basis: 100% ?。

clipboard.png

从上面的模型看,作起来可能很简单。 实际上不是。 一般,header 可能有一个内部间距(padding),当咱们强制某项占据所有宽度时,除非清除padding ,不然它不会生效。 可是,删除padding不切实际,由于它将影响设计中的其余元素 ?。

下面解决此问题的一种解决方法 ?:

  1. flex: 1 0 100%添加到导航元素。
  2. 若有须要,请更改其order。 有时,可能还有其余元素,咱们想确保导航是最后一个。
  3. 加上一个等于宽度等于 padding 的负 margin,这也会让导航占据整个宽度。
  4. 在导航中添加 padding,这会增长一些适当的空间。
  5. 最后,使用了justify-content: center将导航项居中(不重要)
.nav {
  flex: 1 0 100%; /* [1] */
  order: 2; /* [2] */
  margin: 1rem -1rem -1rem -1rem; /* [3] */
  padding: 1rem; /* [4] */
  display: flex; /* [5] */
  justify-content: center; /* [5] */
}

clipboard.png

间距

着 Chrome 和 Firefox 支持flex gap属性,如今在flex项目之间添加间距比以往任什么时候候都容易。考虑如下标题

clipboard.png

要作到上图的高亮间距,只需将gap: 1rem添加到flex父节点。没有了gap,咱们仍是须要用旧的方式来间隔 ?。

/* 老的方式 */
.brand {
  margin-right: 1rem;
}

.sign-in {
  margin-right: 1rem;
}

/* 新的方式 */
.site-header {
  /* Other flexbox styles */
  gap: 1rem;
}

代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug

原文:https://ishadeed.com/article/...

交流

文章每周持续更新,能够微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了不少个人文档,欢迎Star和完善,你们面试能够参照考点复习,另外关注公众号,后台回复福利,便可看到福利,你懂的。

相关文章
相关标签/搜索