使用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和完善,你們面試能夠參照考點複習,另外關注公衆號,後臺回覆福利,便可看到福利,你懂的。

本文同步分享在 博客「前端小智」(SegmentFault)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索