---
# System prepended metadata

title: Google 教你 CSS 000~009
tags: ['HTML, CSS']

---

# Google 教你 CSS 000~009

###### tags: `HTML, CSS`

網頁資源：https://web.dev/learn/css/

# 001 Box Model

> 所有 CSS 的呈現都像是使用在一個箱子裡一樣，所以了解 box model 是 CSS 的基礎


```html=
<style>
p {
  width: 100px;
  height: 50px;
  padding: 20px;
  border: 1px solid;
}
</style>

<p>I am a paragraph of text that has a few words in it.</p>
```

會得到下面的結果

它的 width 為 142px 而不是 100px ，了解 Box model 就可以知道其中的運作摟！

![](https://i.imgur.com/7SnOrtw.png)

## Content and sizing 

* extrinsic sizing

使用者來做決定

* intrinsic sizing

瀏覽器幫你做決定

### Extrinsic sizing vs intrinsic sizing

Extrinsic sizing

使用 Extrinsic sizing 代表 width 是固定的寫死的，因此可以看到如果內容物大於寫死的 width 則會超出去外框
![](https://i.imgur.com/FPu8mxn.png)

使用 Extrinsic sizin 則可以用兩種方式

1. 不設定 width 讓瀏覽器決定外框的 width 它就會做到自適應內容大小的框框摟
2. 對 width 設定 min-content 代表外框會適應內容物的的最小寬度


![](https://i.imgur.com/4PWHpgW.png)


### 更複雜的例子

#### extrinsic sizing

```css=
.box-demo {
  width: 400px;
  height: 400px;
}
```

可以從下圖中看出

框框使用 400 px 的高度都是使用者設定好的，不會因為內容物的大小而去做調整

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


#### intrinsic sizing

```css=
.box-demo[data-sizing="intrinsic"] {
  width: max-content;
  height: max-content;
}
```

使用了 intrinsic sizing 交給瀏覽器做決定，針對填入內容的大小去自適應容器大小

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

#### 這邊出現關鍵字 overflow 關鍵字

 overflow 是一個屬性可以用來操作 overflow 內容

overflow: auto;　//預設會自動使用捲軸
overflow:visible;　 //顯示的文字或圖片會直接超出範圍，不使用捲軸。
overflow:hidden;　//自動隱藏超出的文字或圖片。
overflow:scroll;　//自動產生捲軸。
overflow:inherit;　//繼承自父元素的可見性

### 結論

> Though extrinsic sizing gives more control on the surface, intrinsic sizing provides the most flexibility, most of the time.
> 
雖然 extrinsic sizing 提供了針對畫面更多的控制，但是大多數時候 intrinsic sizing 會有更多的彈性做處理


## The areas of the box model 

![](https://i.imgur.com/oUJ0DEC.png)


* content box 會控制父母層的大小，通常也是變化最多的地方

* padding box 則是環繞 content box 是使用 padding 屬性創造出來的，然而因為它是使用在 box 之中，所以其創造出來的空間是可視的喔！此外，像是 overflow:auto, scroll ，出現的 scrollbar 是會佔據到它的空間的喔！

* border box 則環繞 padding box 使用 border 屬性，主要使用來處理 html 元素的邊框視覺效果

* margin box 則是 box 外面的空間會使用 margin 屬性來定義，然而屬性 outline,box-shadow 則會佔據這個區域的空間 


## A useful analogy 

來複習一下本篇所學吧

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


藝術品本身就是 content box
藝術品外層的白色墊子就是 padding box
藝術品的藍色外框就是 border box
藝術品與其他藝術品的間距就是 margin box
而藝術品的陰影  box-shadow 會包含在 margin box 

## Debugging the box model 

使用瀏覽器的開發者工具就可以直接觀察網頁的 box model 狀態

一般使用 google 瀏覽器

![](https://i.imgur.com/o2QXwri.png)


![](https://i.imgur.com/ZGBtcFe.png)

## Controlling the box model 

這邊可以了解一些瀏覽器的對於 html tag 的一些預設屬性

* div 預設是 display: block
* li 預設是 display:list-item
* span 預設是 display:inline

### inline, inline-block, block

* inline 是有 margin 的但是其他的元素不會理他所以，必須轉變成使用 inline-block 才能正確展示出 margin 來，並且可以保有 inline 的各種特性 

* block 屬性則是預設填滿 inline 的全部空間會把 width  全部吃滿，而 inline 或是 inline-block 則只會跟他們的 content 一樣大而已

* box-sizing 會告訴瀏覽器我們如何計算 box 大小，它的預設是 box-sizing:content-box; 意味著你必須計算 width, height, padding, margin, border 的大小去加總

以下方程式碼為例 他的 width 最後呈現在頁面上面就會是 260px 
```css=
.my-box {
  width: 200px;
  border: 10px solid;
  padding: 20px;
}
```

* 可以使用 border-box 來避免麻煩的計算

代表目前的 border, padding 會被往內推進去，並且最後容器的大小就會是 200px 讓其結果更好被預期（因為你設定多少 width 就是多少不需要額外計算）

```css=
.my-box {
  box-sizing: border-box;
	width: 200px;
	border: 10px solid;
	padding: 20px;
}
```


## 通用在所有的頁面以及容器上

因為好預測的結果加上方便不需要多加計算的特性，一般使用上面會直接針對所有的容器加上去這段屬性

```css=
*,
*::before,
*::after {
  box-sizing: border-box;
}
```

# 002 Selectors

> 為了應用 CSS 到 html 元素上面必須使用選擇器

如果想要針對第一行的文字變大且顏色變紅該怎麼處理 css ?

```css=
<article>
  <p>I want to be red and larger than the other text.</p>
  <p>I want to be normal sized and the default color.</p>
</article>
```

可以直接使用 

去選取 article 內的 p 的第一個 對他做修飾

```css=
article p:first-of-type {
  color: red;
  font-size: 1.5em;
}
```

即可的達到效果

![](https://i.imgur.com/y4FIlCf.png)


不過選擇要修飾的 html tag 有很多種方式從簡單到複雜都有

## The parts of a CSS rule 

CSS 檔案內我們通常會這樣寫：

* .my-class-rule 的部分就是 Selector 選擇器，會尋找 html 頁面中符合的元素
* 整個 color:beige; 是宣告，他會是一種 key value pair 會把 style 配對給 selector 選擇的元素
* coloe 是 property
* beige 則是 value

![](https://i.imgur.com/oGR9JrK.png)


## Simple selectors 

這邊會介紹比較直接簡單的 seletors 像是可以直接加上 html tag 上面的 class, ID

### Universal selector 

萬用匹配符基本上應用到頁面上所有的元素中

```css=
* {
  color: hotpink;
}
```

### Type selector 

使用 type selector 則會選取所有被選取 html tag 並且對他們做修飾

範例處的就是所以的 section 元素都會吃到裡面的 padding 

```css=
section {
  padding: 2em;
}
```

### Class selector 

一個 html 元素可以有多個 class ，並且 class selector 會符合所有使用其選擇器的元素做修飾

下面的 .my-class 所有的 div, button, p 都會吃到它的效果

需要注意的地方是 `.` 只會出現在 CSS 檔案中，因為 `.` 是 CSS 用來配對 class 屬性的字元

```html=
<style>
    .my-class {
  color: red;
}
</style>

<div class="my-class"></div>
<button class="my-class"></button>
<p class="my-class"></p>
```

下方的這行程式碼一樣會吃到 my-class 的修飾儘管他還有其他很多的 seletors ，因為 CSS 只要搜尋到 class 定義到的屬性就會修飾其符合的元素，而不是必須 ”完全符合“ 才會修飾它

```html=
<div class="my-class another-class some-other-class"></div>
```

小提醒 避免命名你的 class 名稱開頭是數字例如 `.1element` 這樣是不會被接受的喔！

### ID selector 

如果 html tag 有 id 屬性的話，則這個 id 只能出現一次在此頁面中，選取方式如下

```html=
<style>
#rad {
  border: 1px solid blue;
}
</style>

<div id="rad"></div>
```

* 跟 class selector 很像，不過 id selector 使用 # 對應
* 除非特定目的需求，你才會使用到 id selector 因為他不能重複使用
* 如果你使用了複數的 id selector 且 value 一樣，CSS 一樣會配對符合的 selector 給該元素使用，但是盡量避免這樣使用

### Attribute selector 

選取特定的 html attribute ，使用在 CSS 內通常會以 `[]` 包起來

```css=
[data-type='primary'] {
  color: red;
}
```

對應的 html tag 

```html=
<div data-type="primary"></div>
```

---

除了寫死 value 之外也可以，只抓取 attribute 

```css=
[data-type] {
  color: red;
}
```

這邊下方的兩個 tage 都會文字變成紅色，它們後方的 value 都會被忽略

```html=
<div data-type="primary"></div>
<div data-type="secondary"></div>
```
---

甚至可以使用 `s` operator 來只操作在小寫的 value 上

以下方程式為例則 Primary 就不會應用到文字變成紅色

```css=
[data-type='primary' s] {
  color: red;
}
```

如果想要只操作在大寫的 value 上，則使用 `i` operator

---

甚至可以配對 attribute 中特定的 value 字串來當作 selector 

如果 href 中有 example.com 則文字變成紅色
如果 href 中開始於 https 則文字變成綠色
如果 href 中結束於 .com 則文字變成藍色

```css=
/* A href that contains “example.com” */
[href*='example.com'] {
  color: red;
}

/* A href that starts with https */
[href^='https'] {
  color: green;
}

/* A href that ends with .com */
[href$='.com'] {
  color: blue;
}
```


常常可以看到的使用範例

針對檔案名稱的結尾去做使用 selector ，並且給予相應的圖片

```css=
a[href$=".pdf"]::before {
  background-image: url(https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/fc7bLiJYf5US6QxTOKsF.png);
}

a[href$=".jpg"]::before,
a[href$=".png"]::before {
  background-image: url(https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/N79qCc0c06217YT4ofYM.png);
}
```

就可以看到左邊的圖是有針對檔案的內容做出操作

![](https://i.imgur.com/M1ybOOe.png)


### Grouping selectors 

下方的 CSS 會套用在 `<strong> <em> .my-class lang 屬性` 包含這寫的元素中

```css=
strong,
em,
.my-class,
[lang] {
  color: red;
}
```

### Pseudo-classes and pseudo-elements 


#### pseudo-classes

針對互動的元素或是眾多子元素中的選取都可以使用 pseudo-classes ，寫在 css 中會使用 `:`

* 當 hover 時候會觸發 css
* 選取 child element 做特定的 css 

```css=
/* Our link is hovered */
a:hover {
  outline: 1px dotted green;
}

/* Sets all even paragraphs to have a different background */
p:nth-child(even) {
  background: floralwhite;
}
```

#### pseudo-element

使用上很像是使用 css 插入新的 element 進去原本的 html elememt ，寫在 css 中會使用 `::`

比較需要注意的地方是如果操作在比較舊的瀏覽器環境，則必須使用 `:before, :after`
例如使用在 IE8

正常使用下會像是下方這樣

```css=
.my-element::before {
  content: 'Prefix - ';
}
```

* 使用 before 會是在元素開始時 
* 使用 after 會是在元素結束時

pseudo-element 還可以指定元素特定的部分做 CSS 修飾

從下方例子中可以看到選取了 li 前方的圓點做修飾 

```css=
/* Your list will now either have red dots, or red numbers */
li::marker {
  color: red;
}
```

還可以使用 `::selection` 來修飾使用者 highlight 的部分

## Complex selectors 

當你需要控制你的 html 更細緻一點時，可以透過 complex selectors 來達成，這邊需要注意的是儘管這些 selectors 給了我們更多的手段控制 css 但是我們只能夠向下控制也就是選擇 child elements 而已，並不能 select 到 parent 去

### Combinators 

Combinator 它一般會出現在兩個 selectors 之間，像是下方的 combinator 就是 `>`

```css=
p > strong 
```

它會選擇元素基於其在檔案中的位置

#### Descendant combinator 

這邊需要先解釋 parent, child element 的概念

* p tag 為 parent element
* strong 則為 child element

```html=
<p>A paragraph of text with some <strong>bold text for emphasis</strong>.</p>
```

descendant combinator 允許我們可以指定 child elememt 使用了空格的方式呈現

這樣一來 p tag 內部所有的 strong tag 都會文字變成藍色，這邊不管有幾個 strong tag 都會吃到一樣的效果

```css=
p strong {
  color: blue;
}
```

#### Next sibling combinator 

使用 Next sibling combinator `+` ，主要操作到具有 sibling element 的元素（範例處的圖片中的 first element 因為沒有 sibling 所以就不會吃到 marign-top）

這邊包住這三個 I have 的 div 的 class 為 .top

![](https://i.imgur.com/7jzR9YJ.png)

我們要如何做到剛好中間都有紅色的 margin 呢？

首先給 .top 所有的 child 加上margin-top 可以嗎？

```css=
.top * {
  margin-top: 1.5em;
}
```
出來的效果不太一樣， .top 的 first child 也吃到了 margin-top 了

![](https://i.imgur.com/9a5toMt.png)

所以我們這樣做會更好

使用到 Next sibling combinator `+` ，如此一來就不會選到 first child 摟，只會選到 .top 內部具有 sibling element 的元素

```css=
.top * + * {
  margin-top: 1.5em;
}
```

#### Subsequent- sibling combinator 

使用了 operator `~` ，他跟 next sibling combinator 的差別在於這邊選取的元素必須緊跟 operator 而不是只要有 next sibling element 就好

它可以用來製作可以 toggle checkbox 切換顏色的效果

```css=
:checked ~ .toggle__decor {
  background: rebeccapurple;
}
```
當 checkbox 的狀態是 checked 時 .toggle__decor 的背景會變成紫色，而這個 .toggle__decor 必須緊跟著 :checked 其後的元素才會生效

![](https://i.imgur.com/vIgPpV6.png)

#### Child combinator 

又名為 direct descendant 他的 operator 是 `>` 正如其名它只能作用在其 child element 上面

我們在使用上面 next sibling 操作到的空間加點東西上去

![](https://i.imgur.com/wrgPqAU.png)

我們加上了一些 strong, code, em tag 因此他們也成為了 next sibling combinator 作用的對象因此他們也加上去了 margin top

這時候就可以操作 child combinator 


```css=
.top * + * {
  margin-top: 1.5em;
}
```

把它變成這樣

```css=
.top > * + * {
  margin-top: 1.5em;
}
```

可以看到他們的 margin 又恢復正常了，因為這個時候 margin top 只會作用在 .top 直屬的 child element 有作用而已，而在 child 裏面的 child 就不會吃到摟！

![](https://i.imgur.com/XjvIJUQ.png)

#### Compound selectors 

可以組合 selectors 來增加明確性以及可讀性

像是下方的例子就是要抓取所有的 a tag 中並且含有 my-class 屬性的元素

```css=
a.my-class {
  color: red;
}
```

# 003 The cascade

> 有時候會有多個 CSS 要套用到同一個元素上面，本章可以了解到瀏覽器怎麼選擇該使用哪個以及如何控制它

cascade algorithm 有四個方向

1. Position and order of appearance:
 CSS 在檔案中的順序，例如排序的先後
 
2. Specificity
由演算法決定哪個 CSS 具有較高的權重（代表挑選順序比較高）

3. Origin
 CSS 出現順序以及它源自哪裡，有可能來自瀏覽器插件或是你自己本身寫好的規則
 
4. Importance
`!important` 寫上它就可以打敗其他規則的權重


## Position and order of appearance 

引入 CSS 的方式有數種

1.  Link 
2.  embedded 使用 `<style>` tag
4.  inline style 直接寫在 html tag 中

然而這幾種方式決定權重的方式在檔案位置中得先後決定，**由後者蓋過前者**

```html=
<link rel="我是黑色" />
<link rel="我是藍色" />
```

像是上述的範例，基本上就會使用 "我是藍色" 的 link 檔案做使用因為他排在後面

--- 

這邊比較的是 style 嵌入在 head 以及被放在 body 內的 link ，因為 link 的位置比較下面所以他會覆蓋掉上面的 style tag 

```html=
<head>
    <style>    
        .button{
            color:red;
        }
    </style>
</head>

<body>
    <link href='我是藍色'>
</body>
```

---

最後介紹 inline style 它基本上會蓋過全部其他的檔案，不管所在的位置，除非你的 CSS 中有 `!important` 屬性

```html=
<head>
    <style>    
        .button{
            color:red;
        }
    </style>
</head>

<body>
    <link href='我是藍色'>
    
    <p style="color:green;">This is a paragraph.</p>
</body>
```

--- 

如果比較的對象是 CSS 內部的話一樣會以先後順序排權重，這邊吃到的顏色就會是 purple 

```css=
.my-element {
  background: green;
  background: purple;
}
```

這種排序權重的方式有時候可以這樣操作

利用後面排序的規則會蓋過前面的，來操作當 `clamp()` 沒有被當前的瀏覽器支援的話，則使用備案就是上面設置的 1.5rem 

```css=
.my-element {
  font-size: 1.5rem;
  font-size: clamp(1.5rem, calc(1rem + 3vw), 2rem);
}
```

CSS 可以這樣操作是因為它不像其他語言一樣會針對看不懂的程式部分報錯或是停止程序，而是忽略它

## Specificity

> Specificity 是一個由演算法來決定哪一個 selector 使用的順序要優先，藉由一個計算分數或是重量的系統
> 
> 如果你想讓某個 selector 具有更高的權重，其可以把其他的 seletcor 的權重設定的比較一致，讓想要突出的 selector 附上較高的權重就可以讓它比較突出摟！


使用 class selector 的權重會比 type selector 的高

```html=
<style>
    .my-element {
      color: red;
    }

    h1 {
      color: blue;
    }
</style>

<h1 class="my-element">Heading</h1>
```
所以這邊的 h1 的顏色會是紅色而不是藍色喔儘管 type selector 的位置位於下方

如果使用 id selector 則他的權重會比 class selector 更高，所以一般不會使用到 id selector 來修飾元素，因為會比較難去複寫掉他的 CSS 規則

### Specificity is cumulative 

> 權重是會疊加的

下方範例處的 CSS 權重因為多個 selector 的選取因此他們的權重會全部加在一起，所以它的 CSS 就會難以被覆蓋因為它的權重變得很高

```css=
a.my-class.another-class[href]:hover {
    color:red;
}
```

所以在撰寫的時候盡量保持 CSS 不要串接太多 selector 保持簡單，也可以把 selector 權重的串接當作一種操作手段也是可行的

## Origin

> 使用者寫的 CSS 不是瀏覽器唯一使用的 CSS ，包括瀏覽器內部預設的 CSS 或是瀏覽器插件使用的 CSS 或是電腦系統使用的 CSS 以及使用者寫的 CSS


而這些 origin 們的權重如下由低至高

1. User agent base styles: 瀏覽器預設的 CSS 
3. Local user styles: 這部分可以來自電腦系統，舉凡字體或是變化動作的偏好，或是來自瀏覽器插件
5. Authored CSS. 這邊是使用者寫的 CSS
7. Authored !important. 所有加上 !important 的使用者寫的 CSS
8. Local user styles !important. Any !important 來自電腦系統或是瀏覽器插件中
10. User agent !important. 任何 !important 加在瀏覽器預設的 CSS 中

![](https://i.imgur.com/Vr14RI3.png)


## Importance

比較不同 CSS properties 的權重由低到高

1. normal rule type: font-size, background or color
1. `animation` rule type
1. `!important` rule type (following the same order as origin)
1. `transition` rule type


## Using DevTools to find out why some CSS is not applying 

可以從開發者工具中清楚地看到被畫線處理的 selector 就是權重輸給別人啦！

![](https://i.imgur.com/vaXoDC1.png)


## 總結

The Cascade 可以用來

* 解決複數 style 要使用在同一個元素上面的衝突
* 確保在跑畫面的時候，只有一個 style value 會使用在元素上面
* 計算 style 規則的分數或是重量
* 排序以及分類 style attributes

# 004 Specificity

> 權重這部分是 cascade 的重點


請問下面的 button 會是什麼顏色呢 ?

```html=
<button class="branding">Hello, Specificity!</button>

```

```css=
button {
  color: red;
}

.branding {
  color: blue;
}
```
會是藍色喔

![](https://i.imgur.com/VhNPCE6.png)

至於為什麼就是經過權重 specificity 來做計算後得出的結果

## Specificity scoring 

* 每個 selector 都有自己的分數加成，而 specificity 則是這些分數最後出來的成績，分數高者會勝出也會優先被使用

* 在現實中要盡量把讓大家的分數弄的平均且要比較低一點會有助於使用權重這個系統，因為可以比較輕鬆讓你想要讓其凸出的 selector 操作成功

* 並且只付加上適當的分數就好，不然之後要再做覆蓋的動作會非常麻煩


## Scoring each selector type 

> 每種 selector 都有自己的分數，必須把所有分數加總之後才會是其權重分數

### Universal selector 

他的分數是 0 分，換句話說誰都可以蓋過它

```css=
* {
  color: red;
}
```

### Element or pseudo-element selector 

type , pseudo selector 都是 1 分

#### Type selector 

```css=
div {
  color: red;
}
```

#### Pseudo-element selector 

```css=
::selection {
  color: red;
}
```

### Class, pseudo-class, or attribute selector 

class, pseudo-class, attribute selector 都是 10 分

#### Class selector 

```css=
.my-class {
  color: red;
}
```

#### Pseudo-class selector #

```css=
:hover {
  color: red;
}
```

#### Attribute selector #

```css=
[href='#'] {
  color: red;
}
```

#### The `:not()` pseudo-class

這個比較特別因為前面有 type selector 所以他是 11 分

```css=
div:not(.my-class) {
  color: red;
}
```

### ID selector 

他是 100 分！

```css=
#myID {
  color: red;
}
```

### Inline style attribute 

inline style 直接寫在 html 內會得到 1000 分

```html=
<div style="color: red"></div>
```

#### !important rule 

他會得到 10000 分 也是所有權重分數最高


要注意的是 !important 添加在其他 selector 內不等於其他的也是同等的權重，而是只有那一條屬性的權重這麼高分而已

```css=
.my-class {
  color: red !important; /* 10,000 points */
  background: white; /* 10 points */
}
```

## Specificity in context 

在 html 元素中的 selectors 權重分數是可以疊加的

比方下方的權重分數就是：

* a : type selector 1分
* .my-class : class selector 10 分
* .another-class : class selector 10 分
* [href] : attr selector 10 分
* :hover : pseudo selector 10 分

總計
這個 lightgrey 的分數就是 41 分


```css=
a.my-class.another-class[href]:hover {
  color: lightgrey;
}
```

## Visualizing specificity 

下圖是另一種 css specificity 的表示方式會出現在 IDE 上～

![](https://i.imgur.com/NBtGbCI.png)

分成三個團體表示～

![](https://i.imgur.com/9FeEKic.png)


以這邊為例子的話

位於位階 1 的 為 0 個
位於位階 2 的 為 4 個
位於位階 3 的 為 1 個

所以排序為 0-4-1

```css=
a.my-class.another-class[href]:hover {
  color: lightgrey;
}
```

可以用下方做練習

```css=
1-1-1
section#specialty.dark

1-2-1
#specialty:hover li.dark

1-3-0
[data-state-rad].dark#specialty:hover

1-1-2
li#specialty section.dark
```

## Pragmatically increasing specificity 


今天我們要操作的範例如下

```html=
<button class="my-button" onclick="alert('hello')">Click me</button>
```

```css=
.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}
```

會出現什麼顏色的背景呢？

.my-button: 10 分 
button[onclick] : 11 分 因為 type selector + attribute selector 

但是今天你想要 .my-button 贏該如何操作呢？

很簡單把 .my-button 寫兩遍，它就會以 20 分的權重分數勝出摟

```css=
.my-button.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}
```

需要注意的是如果你很常需要這樣疊加來取得較高的權重代表你需要重構你的 css 寫法，降低其他的權重會是更好的做法

## A matching specificity score sees the newest instance win 

我們繼續上面的 button 做範例：

這邊的 newset instance win 其實就是在說順序比較新的會勝出


簡單來說如果兩個 selector 的分數一樣則會透過誰在下方來決定勝負，像是下方範例處的話就是 .my-button 勝利，理由就是他位於下方比較新寫出來的扣

```css=
[onclick] {
  background: grey;
}

.my-button {
  background: blue;
}
```

# 005 Inheritance

> 這個章節主要在解釋：有些 CSS 會直接繼承，如果你沒有給他設定 value 的話
> 以及如何利用他們


```html=
<a href="http://example.com" class="my-button">I am a button link</a>
```

```css=

article a {
  color: maroon;
}

.my-button {
  display: inline-block;
  padding: 1rem 2rem;
  text-decoration: none;
  background: pink;
  font: inherit;
  text-align: center;
}
```

這邊的文字顏色不如預期是因為 inheritance 到 aticle a 的值去了，本章節可以明白這邊發生了什麼事以及如何去利用它

## Inheritance flow 

首先我來們看看 inheritance 如何操作的

``` html=
<html>
  <body>
    <article>
      <p>Lorem ipsum dolor sit amet.</p>
    </article>
  </body>
</html>
```

針對整個 html 做修飾

```css=
html {
  color: lightslategray;
}
```
**這邊要注意 html 裡面的不會 inherit 到任何東西因為它就是第一個元素沒有東西在繼承了**

然後會發現 p 裡面的文字 inherit 到 html 所以它的 color 是 litghtslategray 

![](https://i.imgur.com/yO1A40e.png)

這邊可以知道的是所有可以 inherit color 的元素如果沒有設置定值給他們的話就會直接 inherit color:lightslategray 這個屬性，這樣的行為就是 inherit


### 範例二

```html=
<article>
  <p>This paragraph has italic text. Lorem ipsum dolor sit amet.</p>
  <div>This is a div so has normal text.</div>
  <p>This is another paragraph that has italic text.</p>
</article>
```

```css=
html {
  color: #141414;
}

body {
  font-size: 1.2em;
}

p {
  font-style: italic;
}

article > * + * {
  margin-top: 1em;
}
```

印出結果如下：

![](https://i.imgur.com/2rXPuXr.png)

從範例中可以發現 

1. html 的修飾基本上全部都 inherit 下去了
2. body 也是
3. p 的修飾只吃在 p tag 中 div 沒吃到


## Which properties are inheritable? 

下面列出可以 inherit 的屬性

* azimuth
* border-collapse
* border-spacing
* caption-side
* color
* cursor
* direction
* empty-cells
* font-family
* font-size
* font-style
* font-variant
* font-weight
* font
* letter-spacing
* line-height
* list-style-image
* list-style-position
* list-style-type
* list-style
* orphans
* quotes
* text-align
* text-indent
* text-transform
* visibility
* white-space
* widows
* word-spacing

## How inheritance works 

> 每個 htmlt tag 都有一些預設的 css 屬性，這邊所謂的預設屬性指的是如果 inherit 的屬性失敗了，那些依舊生效的 css 屬性

![](https://i.imgur.com/uu1jZIo.png)

上面的粗體字因為被包裹在 span tag 內，所以 font-weight:300 這個屬性就失效了（inherit 失效），這時候他的初始值或是使用者寫的扣就會蓋過它

## How to explicitly inherit and control inheritance 


### The inherit keyword 

可以使屬性繼承其父母層的屬性藉著使用 inherit 這個關鍵字

```css=
strong {
  font-weight: 900;
}

.my-component {
  font-weight: 500;
}

.my-component strong {
  font-weight: inherit;
}
```

下圖可以看到

第一段文字的 strong 是自吃到 default 的所以是 bold 

接下來可以看到因為 inherit 關鍵字，並且因為下一個 strong tag 的位置為 .my-component 的子層所以直接繼承到 font-weight:500 的屬性

![](https://i.imgur.com/knyjc5O.png)


### The initial keyword 

可以使屬性回復到初始值

```css=
aside strong {
  font-weight: initial;
}
```

像是這邊的 strong 會讓文字變成粗體

但是因為下方的 aside 內的 strong 被寫入 initial 關鍵字了因此被取消粗體返回初始值

![](https://i.imgur.com/vn6DNTx.png)


### The unset keyword 

unset 會根據元素是否能 inherit 有不一樣的功能

* 如果元素為 inheritable 則其功能會跟 inherit 一樣
* 如果元素不為 inheritable 則其功能會跟 initial 一樣

要記住所有屬性是否可以 inherit 比較困難，所以這個屬性就可以有所幫助

```css=
/* Global color styles for paragraph in authored CSS */
p {
  margin-top: 2em;
  color: goldenrod;
}

/* The p needs to be reset in asides, so you can use unset */
aside p {
  margin: unset;
  color: unset;
}
```


```html=
<article>
  <p>I have various properties set, globally.</p>
</article>
<aside>
  <p>I want the global properties set on paragraphs unset.</p>
</aside>
```

從下圖中可以看出

margin 是不能 inherit 的，所以他的功能為 initial
color 可以 inherit 他的功能為 inherit 

可以明顯看出 margin 直接沒有效果了
而 color 直接繼承了

![](https://i.imgur.com/B3fMjbi.png)


不過如果我們對 p tag 多增加幾個屬性呢？

```css=
/* Global color styles for paragraph in authored CSS */
p {
	margin-top: 2em;
	color: goldenrod;
	padding: 2em;
	border: 1px solid;
}

/* Not all properties are accounted for anymore */
aside p {
	margin: unset;
	color: unset;
}
```

你會發現除了 margin 跟 color 有被應用之外其他屬性都正常執行

![](https://i.imgur.com/R1NjDPr.png)


所以可以使用 all 屬性來操作


```css=
aside p {
	margin: unset;
	color: unset;
	all: unset;
}
```

這樣一來所有的屬性都會吃到 unset 屬性摟！

![](https://i.imgur.com/3bVVXnJ.png)

# 006 Color

> 有數種不同的方式來使用 color 在 CSS 中，這個章節會看到一些比較常被使用到的 color 的值

CSS 有各種不同的資料型態可以參考 [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types)



## Numeric colors 

> Color 是其中一種型態，並且它使用其他的型態來定義其值像是 number


### Hex colors (Hexadecimal)

為 RGB 的簡寫，指派了數值給 紅 綠 黃 三種 primary color ，為最受歡迎的 color 表現方式

```css=
h1 {
  color: #b71540;
}
```

也可以使用 alpha 值來設置透明度

透明度 50 % 為 `#00000080` ，因為 計算範圍從 0~9 A~F 中間值為 80

一些常用的數值

* 0% 完全透明 00: `#00000000`
* 50% alpha is 80: `#00000080`
* 75% alpha is BF: `#000000BF`

![](https://i.imgur.com/C0FDNz7.png)


B ： 11 乘 16 ＝ 176 （因為是 16 進位的）
F ： 等於 15
176 + 15 = 191
The alpha value is 191—75% of 255

### 縮寫

```
#aa44ee => #a4e

#aa44ee88 => #a4e8

#000000 => #000
```


## RGB (Red, Green, Blue) 

```css=
h1 {
  color: rgb(183, 21, 64);
}
```

RGB 的顏色是由 `rgb()` 這個函式定義的，可以使用數字或是百分比做為參數

* 數字的話得介於 0-255 之間
* 百分比則是 0-100% 之間
* 255 就等於 100 %
* 0 等於 0 %

白色
```css=
rgb(255, 255, 255)
rgb(100%, 100%, 100%)
```

黑色

```css=
rgb(0 0 0)
rgb(0%, 0%, 0%)
```

至於 alpha 值有兩種設置方式

使用 /

```css=
rgb(0 0 0 / 0.5)
rgb(0 0 0 / 50%)
```

使用函式 `rgba()`

```css=
rgba(0, 0, 0, 50%)
rgba(0, 0, 0, 0.5)
```

![](https://i.imgur.com/J6PNvPN.png)



**`lab() lch()` 這兩種比較新的顏色 function 移除了逗號直接以空格當作間隔，因此為了一致性所以 `rgb() and hsl()` 也可以使用空格**(不過為了使其適應比較舊的環境還是可以使用逗號)


## HSL (Hue, Saturation, Lightness) 

```css=
h1 {
  color: hsl(344, 79%, 40%);
}
```

**Hue 指的是在 color wheel 0~360 之間的度數**

* 從紅色(0 度開始)
* 180 度或是 50% 代表顏色是藍色

![](https://i.imgur.com/5VbOcJY.png)

**Saturation 代表的是 Hue 的震盪值**

一個完全沒有震盪的 Hue 為 0% 會是灰階（grayscale）

**lightness 代表一個 scale 從白到黑色**

100% 會給你白色 反之則是黑色

![](https://i.imgur.com/IRJDSYi.png)

### hsl function 

黑色會被定義為
* hsl(0 0% 0%)
* 或是 hsl(0deg 0% 0%)
* hsl(0turn 0% 0%) 也可以

要注意的是 saturation 以及 lightness 都得使用百分比來呈現

[angle type](https://developer.mozilla.org/en-US/docs/Web/CSS/angle)非常適合使用來操作 hsl function 

![](https://i.imgur.com/IKLK28Y.png)


至於 alpha 值有兩種設置方式

使用 /

```css=
hsl(0 0 0 / 0.5)
hsl(0 0 0 / 50%)
```

使用函式 `hsla()`

```css=
hsla(0, 0, 0, 50%)
hsla(0, 0, 0, 0.5)
```

`lab() and lch()`  是更新的 CSS color function ，可以呈現出比 RGB 更廣的顏色


## Color Keywords 

> 目前有 148 種被命名的顏色 [MDN參考](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#color_keywords)
> 他們是存粹由英文命名的顏色像是 purple, tomato and goldenrod

![](https://i.imgur.com/pXIdwyc.png)


針對這些 color 也有特殊的關鍵字可以使用

* transparent 是完全透明，也是 background-color 的預設值
* currentColor 會繼承 color 設置的顏色，舉個例子如果 color 設置為紅色此時如果設置 border-color: currentColor 也就會是紅色，但是如果 color 並沒有設置顏色的話則會採用更外層的設定

### system keyword 

像是電腦背景色 `Background` 或是當你選擇某個元件時觸發的 `Highlight` 色，都是由電腦操作系統定義的中多選項之一而已 [參考網站](https://www.w3.org/wiki/CSS/Properties/color/keywords#System_Colors)

這邊要注意的是所有的 color keyword 都是大小寫都可以接受的，但是 system color 會使用大寫來跟其他顏色區分

## Where to use color in CSS rules 

只要 css 檔案接受 color data type 則上面介紹的所有方式都可以用來呈現 color 

下面是一些可以接受 color 的 css properties

for text styling

* color
* text-shadow 
* text-decoration-color


for background

* background 
* background-color

for gradient(操作漸層顏色)

接受不同形式的 color function 像是 hex, rgb or hsl.

* linear-gradient


for border

* border-color
* outline-color


for shadow

* box-shadow

# 007 Sizing Units

> 此章節可以了解如何操作元素的大小使用 CSS 屬性

使用 `ch` 單位來使 text 的容器大小可以被預測

```css=
h1 {
  font-size: 3.5rem;
  line-height: 1.2;
  max-width: 5ch;
}
```

上面這樣使用的話 max-width 不會超過 5 個字母寬

![](https://i.imgur.com/cRtpsbG.png)


## Numbers 

* Numbers 可以用來定義 opacity, line-height, rgb 這些屬性的數值
* Numbers 是沒有單位的整數或是小數 (1, 2, 3, 100) / (.1, .2, .3).

在 line-height 中如果沒有給數字單位的話

```css=
p {
  font-size: 24px;
  line-height: 1.5;
}
```
他操作起來的 1.5 代表 p font-sieze 預設值的 1.5 倍，這代表著如果 p 的 font-size 為 24 的的話則 line-height 會為36px 

並且因為 font-size 是可以 inheritable 的因此，一般來說使用沒有單位的 line-height 對版面來說是比較好的（因為是相對的數值看起來會比較整齊）

Numbers 也可以用在這些地方：

1. filter: sepia(0.5)
2. opacity: 0.5
3. rgb(50, 50, 50)
4. transform: scale(1.2)


## Percentages 

必須明白 percentages 在 css 是如何計算的，舉例來說的話就是

width 的部分就是會繼承父母層的趴數來計算的

```css=
div {
  width: 300px;
  height: 100px;
}

div p {
  width: 50%; /* calculated: 150px */ 這邊計算父母層的 50%
}
```

**如果 margin 以及 pagging 被設置百分比的話則會繼承 width 來計算百分比**

```css=
div {
  width: 300px;
  height: 100px;
}

div p {
  margin-top: 50%; /* calculated: 150px */
  padding-left: 50%; /* calculated: 150px */
}
```

計算 transition 的百分比的話

必須先計算 width 之後，在計算 transition

300px * 50%  = 150px 

150px * 10 % = 15px

```css=
div {
  width: 300px;
  height: 100px;
}

div p {
  width: 50%; /* calculated: 150px */
  transform: translateX(10%); /* calculated: 15px */
}
```

## Dimensions and lengths 

> 如果把數字加上單位的話，就會變成 dimensions 像是 `1rem`
> 而 length 的話則是 跟距離有關的 dimensions 他們可以是 absolute, relative 

## Absolute lengths 

![](https://i.imgur.com/KrWOY1V.png)

可以用來使用在印刷的檔案中，比方說設定 width:10cm 就會印出 10 cm 的寬度

## Relative lengths 

相對長度是會有一個基底數值來去做計算的比較像是百分比的概念，比較不一樣的地方是相對長度是可以根據父層的長度來計算子層的

舉例說明：

1. ch 就是以 text 的大小來計算的
2. vw 是以使用者本身的螢幕寬度來計算寬度

相對長度對於現代的 RWD 設計是非常必須的

### Font-size-relative units 



* em 以1.5em 為例的話，代表了其父母層的 font-size 的 1.5 倍
* ex 1ex 會使用父母層 font-size 的 一半大小 相當於 0.5em
* cap 會使用父母層字首的 font-size 大小
* ch Average character advance of a narrow glyph in the element's font (represented by the "0" glyph).
* ic 	Average character advance of a full width glyph in the element's font, as represented by the "水" (CJK water ideograph, U+6C34) glyph.
* rem root font-size 的倍數
* lh 元素的行高的倍數
* rlh root 元素行高的倍數


![](https://i.imgur.com/SnNwte7.png)


### Viewport-relative units 

* vw 為使用者的螢幕寬度，如果 100% 就是完整使用者螢幕大小
* vh 同上不過是高度
* vi 為 root 元素的 inline-axis
* vb 為 root 元素的 block-axis
* vmax vmin为vw和vh中較小的那个
* vmin vw和vh中較大的那個


![](https://i.imgur.com/DjFjltl.png)

上圖範例中的 10% vw 代表使用者螢幕大小的 10 分之 1
60ch 則是 60 個字母寬

相對單位的目標是在於 RWD

## Miscellaneous units 

### Angle units 

旋轉的角度

```css=
div {
  width: 150px;
  height: 150px;
  transform: rotate(60deg);
}
```

1turn = 360deg
還有其他的角度單位如

rad, grad都可以表示角度


### Resolution units 

`dpi` 為解析度的單位 意思是 dots per inch


```css=
div {
  background-image: url('a-low-resolution-image.jpg');
}

@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
  div {
    background-image: url('a-high-resolution-image.jpg');
  }
}
```

# 008 Layout

> 本章節會介紹多種不同的 layout 會使用在不同的 component 或是 page 上面


## Layout: a brief history 

[history of css](https://24ways.org/2019/a-history-of-css-through-15-years-of-24-ways/)

![](https://i.imgur.com/rqV8yZZ.png)

## Layout: the present and future 

## Understanding the display property 

```css=
.my-element {
  display: inline
}
```

display 會做兩件事情，第一是會決定物件行為是 block 或是 inline

#### inline

* inline 會緊貼鄰近的元素 像是 span, strong 一般用來修飾 p 段落內的文字
* 要注意的是不能設置 width, height 給 inline 元素使用
* block level 的 margin, padding 也會被忽略


#### block

```css=
.my-element {
	display: block;
}
```

* block 元素不會緊鄰彼此而是佔據一整行的位置，除非使用 css 做調整
* 所以方向的 margin 都會有效果

#### flex

```css=
.my-element {
	display: flex;
}
```

display 也能夠定義其子層的行為，像是 flex 會把當前元素定義為 block-level 之外，還會把其子層轉換為 flex-item ，此時 flex 的屬性就可以發生效用像是 aligment, ordering, flow


## Flexbox and Grid 

> 兩種定位多個元素的 display 屬性，flex, grid ，他們有共同點但被製造出來解決不同的問題


### Flexbox 

flex 是一種 loyout 機制用來處理單一方向的元素，比方說 X 軸或是 Y 軸，其預設屬性會讓 flex-item 也就其子層成 inline 方向排列鄰近彼此，並且 strech 成等高的 block 方向，所以他們的高度都會相同

```css=
.my-element {
	display: flex;
}
```

![](https://i.imgur.com/gUddZHI.png)

flex-item 在同一條軸線上面的元素會試著擠壓彼此為了保持在線上並且不會斷行，這樣的預設行為可以藉由 align-items, justify-content and flex-wrap properties 這些屬性來操作


沒使用屬性之前
![](https://i.imgur.com/L4HYGtA.png)

使用 flex wrap
![](https://i.imgur.com/oddtGkh.png)

使用 align-items center
![](https://i.imgur.com/jFAEVOP.png)

使用 space between
![](https://i.imgur.com/0IzR7bm.png)



flex 屬性是他們的縮寫 flex-grow, flex-shrink and flex-basis

```css=
.my-element div {
 	flex: 1 0 auto;
}

.my-element div {
 flex-grow: 1;
 flex-shrink: 0;
 flex-basis: auto;
}
```

### Grid 

與 flex 有很多相同的地方，但 grid 是為了處理複數 axios loyout 而誕生的，並且會有一些 function 可以操作像是 repeat() minmax() ，grid 特有的單位 fr 代表剩餘空間的一段

可以使用 grid 建立傳統的 12 column grids 並且中間有空間

```css=
.my-element {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1rem;
}
```

這八個物件會平分這個空間並且保持 gap 為 1rem 

![](https://i.imgur.com/lZL1gbj.png)


我們可以控制第一個元素他的位置佔據 1~3 個位置在 row 時
佔據 1~4 的位置在 column 時
```css=
.my-element :first-child {
  grid-row: 1/3;
  grid-column: 1/4;
}
```

![](https://i.imgur.com/br9QGjp.png)


## Flow layout 

不使用 flex, grid 也有幾種方法可以使用

### Inline block 

簡單來說就是 inline 屬性的元素可以使用 margin, padding

從下圖可以看出使用 inline-block 屬性的 span 是可以設定 margin-top 的

![](https://i.imgur.com/qAL0pn1.png)

### Floats 

可以用 floats 實現文字繞圖片的效果

```css=
img {
	float: left;
	margin-right: 1em;
}
```

![](https://i.imgur.com/WKbzB0E.png)

可以使用這些屬性操作floats : left, right or inherit


要留意那些緊鄰著 floats elememts 的元素，可能會因此調整自己的 layout ，為了避免其發生可以使用 clear:both 屬性在那些鄰近的元素上或是 display: flow-root 在 floats 的父母元素上

想了解更多可以[參考這邊](https://rachelandrew.co.uk/archives/2017/01/24/the-end-of-the-clearfix-hack/)

### Multicolumn layout 

假設你有超多國家要顯示在網頁中，可以使用 column-count 來分行，以及 column-gap 來決定其間距

```html=
<h1>All countries</h1>
<ul class="countries">
  <li>Argentina</li>
  <li>Aland Islands</li>
  <li>Albania</li>
  <li>Algeria</li>
  <li>American Samoa</li>
  <li>Andorra</li>
  …
</ul>
```

```css=
.countries {
	column-count: 2;
	column-gap: 1em;
}
```

![](https://i.imgur.com/7MnZcqg.png)



除了直接定義要幾行之外，也可以定義 column 的寬度，所以使用者的螢幕多大就可以呈現更多行摟

```css=
.countries {
	width: 100%;
	column-width: 260px;
	column-gap: 1em;
}
```


### Positioning 

position 會改變元素在網頁中的行為，以及其與其他元素相對絕對的定位

static 為預設值 其他為可以操作的屬性 relative, absolute, fixed and sticky

#### position: relative

```css=
.my-element {
  position: relative;
  top: 10px;
}
```

這個被設定的元素比原本的位置相對向下方偏移了 10px ，並且原本的位置會依然存在

#### position : absolute 

則會以 父層定位的 relative 來移動其位置，並且直接浮上所有的空間，所以原本空間不存在會被其他元素填滿，不像是 relative 的偏移

top, right, bottom and left 使用這四個屬性來定義 absolute 的元素

```css=
.my-element {
  position: relative;
  width: 100px;
  height: 100px;
}

.another-element {
	position: absolute;
	bottom: 0;
	right: 0;
	width: 50px;
	height: 50px;
}
```

#### position : fixed 

跟 absolute 很像，但是他會被釘在頁面上怎麼滑都不會移動，但是他會定位的地方一定是 html 也就是整個網頁，不會 absolute 定位在父層的 relative 

top, right, bottom and left 一樣使用四屬性操作


#### position: sticky

基本上操作方式 = relative + fixed 

當螢幕滾動 scroll 碰到 sticky 時，就會變成 fixed 屬性在這之前都會保持 relative 的偏移定位效果



static
![](https://i.imgur.com/zsMMmC8.png)

relative 可以發現原本的位置依舊被佔據著
![](https://i.imgur.com/dwVqXYS.png)

absolute 的位置就被其他元素填滿了
![](https://i.imgur.com/onwg3vZ.png)

fixed 可以發現位置跟 absolute 一樣被填滿並且畫面滑到哪邊他就跟到哪邊因為被固定住了
![](https://i.imgur.com/ANYe51f.png)

sticky 可以發現，跟 relative 一樣原本的位置一樣被佔據著並且當 scroll 碰到設定好的位置時，元素變成像是 fixed 一樣固定在畫面上（但是原本位置沒有被填滿喔要注意）
![](https://i.imgur.com/ALNNmLC.png)

# 009 Flexbox

> Flexbox 是設計來排列單一維度的 layout 機制(比方說 X軸 Y軸)



flexbox 的優點在於，它可以把不同大小的物件做出最好的排列出來，它不只是可以幫助 inline 的排列甚至可以當剩餘空間不夠時，可以做到斷行的效果

所以除了把所以的容器大小寫死之外，使用 flexbox 可以讓其邊界設置更具有靈活性來做出暗示整體視窗可以怎麼操作（比方說縮小視窗就會斷行）

![](https://i.imgur.com/QriT1UF.png)

設置 flex-wrap 的效果
![](https://i.imgur.com/DVpe4PE.png)

## What can you do with a flex layout? 


* flex-item 可以呈現 行 或是 列
* flexbox 允許操作 writng mode of document
* flexbox 基本上呈現會是單行或是列，但可以操作 wrap 來操控多行或是列
* flex-item 可以更改他們在 document 上面的順序
* 空間可以被分布在 flexbox 內部，他們的大小取決於其父母層的可用空間
* 空間可以環繞著 flex-item 做分配並且可以操作 wrap 藉由一些 alignment 屬性
* flex-item 可以對齊派列 X 或是 Y 軸


## The main axis and the cross axis 


![](https://i.imgur.com/bMUQZ4T.png)

要了解 flexbox 最重點的點就是理解軸線 main Axis, corss Axis

flex-direction 來操作其方向

* row 就是行 X 軸線操作 - main Axis
* column 則列是 Y 軸線操作 - corss Axis

## Creating a flex container 

```html=
<div class="container" id="container">
  <div>One</div>
  <div>Item two</div>
  <div>The item we will refer to as three</div>
</div>
```

```css=
.container {
  display: flex;
}
```

基本上針對要操作的元素的父母層直接給他 flex 下去

這邊有個重點是所以的 CSS 屬性都有自己的預設值，所以當 display:flex 一下去，所以的物件就會開展現出 flexbox 的一些基礎屬性

The initial values mean that:

* flex-items 會呈現 行 排列 (row)
* 它們不會斷行
* 它們不會自動填滿 container
* 它們從 container 開頭開始對齊


## Controlling the direction of items 

即便你還沒設置 flex-direction 物件們就已經成行 (row) 排列是因為，這就是它的預設值，所以這就是你想要的排列的話，就不需要使用這個屬性

下面是 flex-direction 可以操作的屬性

* row: 成行排列從頭開始
* row-reverse: 成行排列從尾開始
* column: 成列排列從頭開始
* column-reverse : 成列排列從尾開始

row

![](https://i.imgur.com/7bmeq1m.png)

reverse-row 注意 item one 的順序

![](https://i.imgur.com/tF3To3I.png)

column

![](https://i.imgur.com/j0hAxpl.png)

reverse-colunm 一樣注意 item one 的順序

![](https://i.imgur.com/RdYZJv9.png)

## Reversing the flow of items and accessibility 

> The reordering only happens for the visual order, not the logical order

這段英文是重點像是上面使用到的範例 row-reverse and column-reverse 他們只會發生在畫面上而不會在邏輯上面，文中給的範例是在 reverse 的 link 中去使用方向鍵做切換會發現會整個順序倒過來，因為畫面的順序切換，但是邏輯的順序還在原本的地方是的關係

正常順序的 row 往右點方向鍵就會往右邊切換
![](https://i.imgur.com/WccCmVg.png)

reverse row 的話則是往右邊按方向鍵的話卻是往左切換
![](https://i.imgur.com/fw5gg5R.png)


什麼樣的 css 屬性會造成 reordering 呢

* Using position: absolute, fixed and taking an item out of flow visually.
* The order property in Flexbox and Grid layout.
* The row-reverse and column-reverse values for flex-direction in Flexbox.
* The dense value for grid-auto-flow in Grid Layout.
* Any positioning by line name or number, or with grid-template-areas in Grid Layout.

## Writing modes and direction

flex-direction 的 row 會是 default 會照各國的文字系統去決定其文字的 row 以及 reverse-row 的方向

像是阿拉伯文的預設方向如下，因為他們是由右邊開始書寫

![](https://i.imgur.com/5OY3jbr.png)

像是日文的話就是會 row 呈現的是 vertical writing mode

![](https://i.imgur.com/0xhHMVH.png)

**從上方範例可以理解 flex-item 的 row 預設行為是藉由 document 的書寫模式去定義的，而不是都是由左到右，或是都是水平的書寫模式**

正因為上面這些原因所以 flex 沒有使用 top/bottom/left/right 來定位方向，而是使用 start / end ，讓使用者可以更好理解


![](https://i.imgur.com/mLX6sgy.png)

## Wrapping flex items 

flex-wrap 屬性的預設值為 nowrap ，而這樣不換行的行為就會造成 overflow 的發生也就是當前的物件滿出頁面

![](https://i.imgur.com/1Tr8siN.png)

使用 wrap 後可以做到換行

```css=
.container {
  display: flex;
  flex-wrap: wrap;
}
```

![](https://i.imgur.com/aMCBnW4.png)


### The flex-flow shorthand 

flex-direction + flex-wrap = flex-flow

```css=
.container {
  display: flex;
  flex-flow: column wrap;
}
```

## Controlling space inside flex items 


### 範例一 flex 預設值
假設 flex-item 沒有佔滿整個容器，那麼此時的排列會是預設的 start 排列對其左邊，並且依舊有其他的空間沒有填滿那是因為 flex- 的預設值為

* flex-grow: 0 items do not grow.
* flex-shrink: 1 items can shrink smaller than their flex-basis.
* flex-basis: auto items have a base size of auto.

![](https://i.imgur.com/sOCQqRX.png)

flex:initial 代表上方的縮寫

### 範例二 flex 隨著 item 大小，越大會有更多的空間

使用 flex:auto 代表，item 的大小最後都會隨著內容物大小而不同，隨著 item 大小，越大會有更多的空間

* flex-grow: 1: items can grow larger than their flex-basis.
* flex-shrink: 1: items can shrink smaller than their flex-basis.
* flex-basis: auto: items have a base size of auto.

![](https://i.imgur.com/KemDxIu.png)

可以使用 flex: auto 代表上方的縮寫


### 範例三 操作 flex:1 讓所有 item 大小一致

簡單來說就是關掉 flex:auto 變成 1 ，並且把 basis 設為 0 ，他們就會都一樣大摟

* flex-grow: 1: items can grow larger than their flex-basis.
* flex-shrink: 1: items can shrink smaller than their flex-basis.
* flex-basis: 0: items have a base size of 0.


![](https://i.imgur.com/Khy7dSx.png)

可以使用 flex: 1 代表上方的縮寫

### 範例四 flex:none 

代表不會伸縮的 flex-item

* flex-grow: 0: items can grow larger than their flex-basis.
* flex-shrink: 0: items can shrink smaller than their flex-basis.


這個屬性可以用在你單純想要 flex 的排列但是不要它的伸縮的屬性時可以使用

它的縮寫為 flex: none

### Allowing items to grow at different rates 

為了讓每個 flex items 可以有不同的大小，不需要每一個 items 都寫上 flex-grow:1，而是可以針對其參數做調整

```css=
.item1 {
  flex: 1;
}

.item2 {
  flex: 2;
}

.item3 {
  flex: 3;
}
```

![](https://i.imgur.com/I7zijNq.png)

也可以藉由 flx-basis: auto 來達成，一般不會這樣寫，但就要寫得很明白全部屬性要寫出來，他是會由瀏覽器來決定 items 的大小，如果你想要 item 變大的幅度比 grow 在大一點的話可以這樣操作

```css=
.item1 {
  flex: 1 1 auto;
}

.item2 {
  flex: 2 1 auto;
}

.item3 {
  flex: 3 1 auto;
}
```

## Reordering flex items 

使用 order 這個屬性來操作 items 的順序

```css=
.box:nth-child(2) {
  order: 2;
}

.box:nth-child(3) {
  order: 3;
}
```

![](https://i.imgur.com/HqgrPXH.png)

上圖可以發現當給 item one 設置 oreder 2 時，會排在 item two 前面因為他們的 order 一樣

![](https://i.imgur.com/8DIsxHg.png)

但當 item one 設置 order 3 時就會排在 item 2 後面，但是會排在 item 3 前面因為他們的 order 一樣

![](https://i.imgur.com/LI2ReuA.png)

除非給到 item one 設置 order 4 時候才會排到最後

**Warning: Using order has the same problems as the row-reverse and column-reverse values of flex-direction**

需要注意的是 order 一樣會造成跟 row-reverse and column-reverse values of flex-direction 一樣的問題就是他們只會發生在畫面上而不會在邏輯上面，所以記得不要使用會造成部分使用者體驗不佳，直接改 html 順序吧

## Flexbox alignment overview 


用在 分配空間 的屬性:

* justify-content: space distribution on the main axis.
* align-content: space distribution on the cross axis.
* place-content: a shorthand for setting both of the above properties.

用在 flexbox內排列 的屬性:

* align-self: aligns a single item on the cross axis
* align-items: aligns all of the items as a group on the cross axis

## Distributing space on the main axis 

justify-content 的屬性：

flex-start: 元素和容器的 start 對齊。
flex-end: 元素和容器的 end 對齊。
center: 元素在容器裏居中。
space-between: 元素"之間"保持相等的距離，會碰到底部。
space-around: 元素"周圍"保持相等的距離。
space-evenly: 元素"之間"保持相等的距離，但不會碰到底部。

這些屬性要發生效果必需有餘裕的空間留在 main axis ，如果 item 已經佔滿空間則不會發生效果


### With flex-direction: column 

轉變 flex-direction 就會改變 main-axis 所以當變成 column 時，main-axis 就會是 column 方向

象徵使用個 center 代表一下

![](https://i.imgur.com/5quWFSV.png)


## Distributing space between flex lines 

針對 flex-wrap 被斷行的元素可以透過 align-content 來操作整個 .container 內的 item

而他的預設值是 stretch

圖片中是直接針對 container 設定 align-content：stretch
![](https://i.imgur.com/sVDHOUF.png)

flex-end
![](https://i.imgur.com/Yi50vwQ.png)


### The place-content shorthand 

justify-content + align-content = place-content

*  place-content 只有一個值則代表兩個屬性的值相同
*  place-content 有兩個值第一個值代表 align-content 第二個是 justify-content

```css=
.container {
  place-content: space-between;
/*     兩者的值都為 space-between */
}

.container {
  place-content: center flex-end;
  
/*   wrapped lines 在 cross axis 為 center
  在 main axis 則為 flex-end  */
  /* wrapped lines on the cross axis are centered,
  on the main axis items are aligned to the end of the flex container */
}
```

### Aligning items on the cross-axis 

這邊會操作 align-itmes, align-self 來排列 flex line 內的元素

 align-self 的初始值為 stretch 這也是為什麼 flex-item in row direction 會是所有的 item 延展到跟當中最大的元素一樣高
 
 
stretch 會把元素延伸到跟當中最大的元素一樣高 
 ![](https://i.imgur.com/Nk376RJ.png)

align-self center
![](https://i.imgur.com/GJivZoR.png)

**align-self 只操控一個 flex-item**

**align-items 則可以操作在 container 來排列全部 items** 


align-items stretch 
![](https://i.imgur.com/oIC9CwU.png)

align-items center 
![](https://i.imgur.com/mGVLfU4.png)


## align-items 跟 align-content 的不同之處

* 在於 align-content 是針對整個 container 做排列
* 而 align-items 則是針對 flex-lines 內去做排列


## Why is there no justify-self in flexbox? 

因為 flex 把 main-axis 視為一個整體因此沒有辦法單一 item 來操作，不過 In grid layout the justify-self and justify-items works 

所以如果要在 main-axis 裡面處理單一元素的話建議使用 margin auto 來操作之中的間距


針對最右邊的 item 處理 margin-left auto 就可以做到這樣的效果
![](https://i.imgur.com/c4Klhcx.png)


## How to center an item vertically and horizontally 

簡單來說就是處理兩個軸的 center 

```css=
.container {
  width: 400px;
  height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;
}
```