---
# System prepended metadata

title: 挑戰-金魚都能懂的網頁切版： 導覽列

---

# 挑戰-金魚都能懂的網頁切版： 導覽列

網址：
https://judyyutong.github.io/my-projects/TopNav.html

### 學習重點
- 圖片容器與父子層置中
- 導圓角的四個角分2次指定border-radius
- 消除滑鼠點擊搜尋列時的框線``:focus``＋``outline: none;``
- 使用``display: flex``讓``input``和``button``緊密排列
- 多重偽元素的使用＋transition+上下左右位置偏移

### 1. 圖片容器與父子層置中
**圖片多包一層容器去控制**
先建立一個超連結``<a>``容器，把圖片``<img>``放在``<a>``裡面，讓圖片可以被點擊。

```htmlembedded=
<header class="main-header">
    <div class="container">
      <a href="#" class="logo">
        <img src="img/cat.png" alt="CSS Cat | CSS 貓">
      </a>
```
--
父層設定具體寬度：``.logo{width: 100px}``；
子層則設定「百分比」去撐滿容器：``.logo img{width: 100%``}，用這種方式間接控制圖片大小。

```css=
.main-header .container{
    display: flex;
    align-items: center;
    padding: 20px;
    max-width: 1200px;
    margin: auto;
        }
        
.main-header .logo{
    width: 100px;
        }
        
.main-header .logo img{
    width: 100%;
    vertical-align: middle;
        }
```

> **疑惑murmur區**
不懂為什麼``img``必須設定``vertical-align:middle``

> 既然``.container``已經設定``display:flex;``＋``align-items: center
``(主軸流向預設row由左往右水平+次軸相對主軸由上往下垂直對齊=垂直置中)，那麼包含其中的``.logo``裡面的``img``難道不會也一起垂直中？為何``img``還得再設定``vertical-align:middle``？

> 自己推斷：可能是先讓``img``先相對垂直置中於自己父層的``.logo``，再讓``.logo``去被``.container``的``flex``影響而垂直置中。
> 也就是兩個層次的置中。

> 也許就像是Adobe Illustrator裡面有時也要置中兩次，內群組會先置中一次，外群組再置中一次，確保內外層的置中做在同一高度。


![](https://i.imgur.com/5L8xVo6.jpg =80%x)
![](https://i.imgur.com/PGJUBxG.jpg =80%x)
<圖說>
桃色方框好比``.container``
黃色方塊好比``.logo``
藍色方塊好比``img``

藍色尚未與父層的黃色彼此置中時，即使黃色的確已置中於桃色，藍色卻是在中線以下，沒有真的置中於畫面，所以要先讓藍色置中於黃色，再讓藍色與黃色一起置中於桃色，大家才真的在同一個置中水平上。


![](https://i.imgur.com/mlLcJzA.gif)

▲ 上面GIF可看出，實際上修改語法觀察，``vertical-align: middle``存在與否，確實有造成版面細微的差異。 

### 2. 導圓角的四個角分2次指定border-radius
form搜尋表單``.header-search``是由左邊的input和右邊的button組成，所以要讓完整表單四個角落要導圓角的話，得由input負責左上和左下，button負責右上和右下。

![](https://i.imgur.com/Kh5ha3F.jpg =80%x)
![](https://i.imgur.com/At7NaUR.jpg =80%x)
![](https://i.imgur.com/GXnEQOP.jpg =80%x)


```css=
border-radius: 左上 右上 右下 左下;
```
四個角要指定四個值時，是順時針指定。

```css=
input{border-radius: 200px 0 0 200px;} 

.main-header .header-search button{
border-radius: 0 200px 200px 0;}
```
input負責左上和左下，button負責右上和右下。




> 疑惑murmur區
> 不知道為什麼CSS選擇器這邊，同樣都是在``<form class="header-search">``裡面的``input``和``button``，``input``可以直接寫``input``來選取，但是``button``前面卻必須寫出``.main-header .header-search``這兩層來選取？


### 3. 消除滑鼠點擊搜尋列時的框線``:focus``＋``outline: none;``

在CSS選擇器中使用逗點``,``聯合指定當``input`` 和``button``任何一方被滑鼠點擊時(``:focus``)不要出現預設的藍色框線，將框線樣式指定為``none``。

![](https://i.imgur.com/Kqqn7Oh.jpg)

![](https://i.imgur.com/M43VU1p.jpg)

![](https://i.imgur.com/aMRRU4s.jpg)


### 4. 使用``display: flex``讓``input``和``button``緊密排列
搜尋表單由左側的「輸入框」與右側「按鈕」組成。

父層的``<form class="header-search">``指定``display: flex``，則其所包裹的``input``和``button``兩者就會因為預設是row水平緊密，消除兩者之間空隙，而緊密排列。

![](https://i.imgur.com/Kq8EhEK.jpg)

![](https://i.imgur.com/eSkileX.jpg)


### 5. 多重偽元素的使用＋transition+上下左右位置偏移
#### 希望游標滑過導覽列``.main-nav``裡面的超連結文字``a``時，底下會由「中央」展開白線。
![](https://i.imgur.com/v50Am9L.gif)

▲ 像這面這樣


```css=

.main-header .main-nav a{
    text-decoration: none;
    color: #fff;
    padding: 5px 1em;
    position: relative;
        }
/*先消除超連結原生的底線，設定超連結文字本身是#fff白色，
指定上下內距5px，左右內距1em，並指定「相對定位」。*/   

.main-header .main-nav a:after{
    content: '';
    position: absolute;
    left: 50%;
    right: 50%;
    height: 0;
    bottom: -5px;
    border-bottom: 1px solid #fff;
    transition: .3s;
        }
/*設定「絕對定位」。
由於受父層`display:flex影響成為區塊排列，
所以超連結a:after從「之後」變成「之下」，
並在下方距離5px的位置，產生一條1px的白實心線段。
但是距離左邊位移一半，距離右邊也位移一半，
等於左右都退到中間退無可退，所以白線此時是看不到的。
而且還有設定延遲0.3秒才開始生成這條白線。
*/

.main-header .main-nav a:hover:after{
    left:0;
    right:0;
        }
/* 當游標滑過超連結a時，
原本a:after設定的那條白線，
此時會距離左邊和距離右邊為0，
也就是說白線會完整的長出100%與文字同寬。
也就是說上面的0.3秒代表游標滑上去後延遲0.3秒，
白線會從「無」延伸到「全長」。
*/
```

【左右各往中間退一半】
本來``a:after``的線段，因為左右各退一半往中間縮，所以看不到，

但是，當游標滑上超連結，超連結之後的線段就因為距離左右變為0，等於線段撐滿超連結容器，變成完全看得到，且設定0.3秒的延遲，得到的結果就是—
線段帶著微妙延遲從「正中間」從0~100長出來。

--

![](https://i.imgur.com/dRvUGIH.jpg)
![](https://i.imgur.com/FKBb6pg.jpg)

▲ 如果距離左邊和距離右邊都各50%，則交會在正中間無路可退，左邊減一半＋右邊減一半=看不見。

--
![](https://i.imgur.com/v50Am9L.gif)

▲ 可以看到線段是由中間往兩側長出來，又從兩側往中間縮減直到消失。

##### 為什麼要這樣設定？
比起利用``opacity``讓白線從完全看不見>>到完全被看見，屬於整條off/on；

這邊運用``left``、``right``位移屬性各往中間退一半，指定白線由「中央」長出來，從看不見的「起點」長到「終點」被完全看見，並且加上延遲。

這樣做，可以讓白線的出現更有視覺動態層次感。


### 【一些CSS屬性測試】

#### ``position``的測試
![](https://i.imgur.com/3ql78bX.jpg)

▲ 如果拿掉``.main-header .main-nav a``的``position: relative;``和``bottom: 0;``，那麼``border-bottom``變成一整條在``a``上面的線，

我猜是因為這樣導致``.main-header .main-nav a:after``的``position:absolute``沒有「上一層？」對象讓他抓定位，所以找不到``a``超連結文字的位置，而且也沒有指定bottom，所以線條走位。

> **疑惑murmur區**
position子層absolute與父層relative的關係，也適用在偽元素情況下?

--

![](https://i.imgur.com/8kKxP9n.jpg)
▲ 如果只加上``position: relative;``，``position:absolute``因為抓到位置了，所以``border-bottom``的線段有找到超連結``a``的位置，變成每個超連結自已一個小線段，但因為沒有指定``bottom``，所以線段長在上方。

--
![](https://i.imgur.com/5h3J26c.jpg)
▲ ``position: relative;``和``bottom: 0;``都加上去的話，線段既找得到每個超連結文字``a``的位置，而且還會在超連結下面。

--
#### ``height``的測試
![](https://i.imgur.com/1rlt3iI.jpg)


▲ 若改成``right:30%``和``height:1000``會發現線段距離右邊偏移30%，但是``height``看不出影響，我猜可能是因為已經是``border-bottom``所以高度沒有意義？不懂的是為什麼要特別設置？因為測試即使把``height``整個取下不寫，畫面也看不出影響。

**［要記得加上單位］**
right和left的偏移，如果直接打數字沒有加上單位，例如``right:30``線段會看不見，顯示失效，必須打成``right:30%``，或者``right:30px``，線段才會真的距離右邊發生偏移。

--
![](https://i.imgur.com/Nm2ST4w.jpg)

▲ 若改成``right:30%``與``bottom: 50%;``，並且把線段加粗變藍使容易辨識，會看到線段距離右邊偏移30%以及距離底下偏移50%。

--
![](https://i.imgur.com/ujjdswU.jpg)

▲ 若改為``right:0%``留下``bottom: 50%;``就會看到線段在超連結區塊撐滿，但是距離底下偏移50%，看起來變得像是刪除線。

--
![](https://i.imgur.com/sMxzu8Y.jpg)
![](https://i.imgur.com/kM5lyOx.jpg)

▲ 可以利用負值讓線段再沿著y軸往下偏移，例如``bottom:-5px``


> **疑惑murmur區
> 為什麼left和right設定要用百分比0%
> 但是height和bottom卻是直接設定0？
> 兩者有什麼差別嗎？