---
# System prepended metadata

title: Mars Weather - SASS project
tags: ['HTML, CSS, SASS']

---

# Mars Weather - SASS project

---
tags: HTML, CSS, SASS relate
---

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

# 製作一個火星天氣觀測網頁

## 成品:

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


[成品網址](https://chiehliu.github.io/git-projects/MarsWeatherApp/index.html)

## 成品功能:
1. cel/fah的按鈕可以做切換
2. 下方的七天天氣可以點擊按鈕開關

# HTML

## html程式碼:

# SCSS


## 全域設定

* 全域設定border-box這樣做margin, padding, border比較方便
* 設定所有的顏色、文字大小以及粗細
* .sr-only 主要給聽障人士使用(這邊用來隱藏元素)
* body, h1, a 都是比較常見的設定 

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

:root {
    --fw-light: 300;
    --fw-normal: 400;
    --fw-semi: 500;
    --fw-bold: 700;
    --fs-h1: 1.5rem;
    --fs-h2: 2.25rem;
    --fs-body: 1rem;
    --fs-xl: 4.5rem;
    --clr-light: #fff;
    --clr-gray: #989898;
    --clr-dark: #444;
    --clr-accent: #D06D6D;
    --clr-accent-dark: #613131;
}

.sr-only:not(:focus):not(:active) {
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}

body {
    margin: 0;
    font-family: 'Montserrat', sans-serif;
    line-height: 1.6;
    background-image: url(https://raw.githubusercontent.com/kevin-powell/Mars-Weather-App/master/img/mars.jpg);
    background-size: cover;
    height: 100vh;
    overflow: hidden;
    color: var(--clr-light);
}

h1,
h2,
h3 {
    line-height: 1;
}

a {
    color: var(--clr-accent);

    &:hover {
        color: var(--clr-accent-dark);
    }
}
```

## .mars-current-weather

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


* 做grid以及分三個欄位(等長)等下做使用
* 設定max-width避免拉太長跑版
* 背景做透明
```sass=
.mars-current-weather {
    background: rgba(0, 0, 0, .7);
    padding: 2em;
    max-width: 1000px;
    margin: 4em 0 0 4em;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 2em;
}
```

### .main-title

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


* 抓取grid的欄位1~-1讓main-title可以延續整個面板長度
* 全轉成大寫
* 字母間距2px(作者喜好)

```sass=
.main-title {
    font-size: var(--fs-h1);
    font-weight: var(--fw-light);
    text-transform: uppercase;
    color: var(--clr-accent);
    letter-spacing: 2px;
    grid-column: 1/-1;
}
```

### .section-title

綠色框框處
![](https://i.imgur.com/lRzFp5Z.png)


```sass=
.section-title {
    font-size: var(--fs-h2);
    font-weight: var(--fw-bold);
    margin: 0;
}
```
讓日期部分最大最顯眼

```sass=
.section-title--date {
    font-size: var(--fs-xl);
}
```

### .reading

綠色框框處
![](https://i.imgur.com/bwK3ooy.png)


```sass=
.reading {
    font-size: var(--fs-h1);
    margin: 0;
    color: var(--clr-gray);
}
```

### .date

內容包含天次以及日期
![](https://i.imgur.com/6swOmfN.png)


整個視窗的抓取位置在第一到第二欄位

```sass=
.date {
    grid-column: 1/2;

    &__day {
        font-size: var(--fs-h2);
        margin: 0;
        color: var(--clr-gray);
        font-weight: var(--fw-light);
    }
}
```

### .temp

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

* 抓取位置在第二到第三格
* 處理左右兩邊的格線

```sass=
.temp {

    // 像這邊的var設置在temp裡面所以並不能給外面使用
    --border: solid .25em var(--clr-accent-dark);
    grid-column: 2/3;
    border-left: var(--border);
    border-right: var(--border);
    padding: 0 2em;
}
```

### .wind


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

第二次grid為了排列圓盤以及標題風速
![](https://i.imgur.com/TSATGVa.png)

第三次grid為了排列指針
![](https://i.imgur.com/OEpfQMh.png)

#### 整個.wind區塊
* 抓取位置在第三到第四格
* 在進行第二次gird為了讓內容物作排列

#### 圓盤區域
* 進行第三次grid為了排列裡面的指針並且使用`place-items: center;`全置中
* 圓盤的部份跨越了兩個row所以使用`grid-row: 1/span 2;`

#### 指針區域
* 指針的部份使用clip-path: polygon裁剪出三角形
* 使用transform做好定位並且指向0度的方向
* transform-origin讓三角形的旋轉是以底部的中心點轉才不會偏調

```sass=
.wind {
    grid-column: 3/4;
    display: grid;
    grid-template-columns: repeat(2, 1fr);

    // 這一步是為了讓Wind標題與風速之間的間距縮小讓行距大小跟內容一樣
    grid-template-rows: min-content 1fr;
    
    //往上對齊
    align-self: start;

    //幫它們做好排列位置
    .section-title,
    .reading {
        grid-column: 2/3;
    }

    //圓圈的部分修飾
    &__direction {
        --size: 6rem;
        width: var(--size);
        height: var(--size);
        background-color: rgba(255, 255, 255, .5);
        border-radius: 50%;
        display: grid;
        place-items: center;
        grid-row: 1/span 2;
    }

    &__arrow {
        --direction: 0deg;
        --size: 1rem;
        height: calc(var(--size)*3);
        width: var(--size);
        background: var(--clr-accent-dark);
        clip-path: polygon(50% 0, 0% 100%, 100% 100%);
        transform: translateY(-50%) rotate(var(--direction));
        transform-origin: bottom center;
    }
}
```

### .info

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

* 抓取位置

```sass=
.info {
    grid-column: 1/3;
}
```

### .unit

可調整式按鈕藉由SCSS全部製作出來!
![](https://i.imgur.com/s3HT8kN.png)


#### 整個外框

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

* 先放置到位置`grid-column: 3/4;`
* 使用place-self:end會把物件放到最右邊最下方
* 要把unit內部元素弄成一橫排直接flex
* 做一點透明度以及hover時會有特效

#### input區域的checkbox

隱藏前的樣子
![](https://i.imgur.com/DMfjeRx.png)

* 引入的sr-only的內容隱藏checkbox


#### unit__toggle

* 中間的橢圓形外框修飾


#### unit__toggle::after

* 中間的圓球的部分點擊兩側的溫度則會移動，左側自動填滿margin所以球會移動到最右邊
* ![](https://i.imgur.com/8FZWj2V.png) 因為這個checked關係球會預設在°C
* 使用`margin-left:auto;`會讓球往右邊跑因為左邊auto直接填滿
* 使用`margin-left: 3px;`會讓球回到左側因為3px就是原本預設的margin


偽類選擇器`:checked`只會使用在任何選中狀態下的`radio(<input type="radio">)，checkbox (<input type="checkbox">) 或("select") `元素中的option HTML元素("option")。

```sass=
:checked~.unit__toggle::after {
        margin-left: 3px;
    }
```


```sass=
.unit {
    grid-column: 3/4;

    // place-self是align-self and justify-self的縮寫
    // 使用end會把物件放到最右邊最下方
    place-self: end;
    color: var(--clr-light);
    display: flex;
    opacity: .7;
    transition: opacity 275ms linear;

    &:hover {
        opacity: 1;
    }

    label {
        cursor: pointer;
    }

    // 要隱藏input區域那個圓形checkbox
    // 一樣使用sr-only的屬性貼在這邊使用
    input {
        clip: rect(0 0 0 0);
        // 這個clip-path主要會把input的checkbox裁減掉
        clip-path: inset(50%);
        height: 1px;
        overflow: hidden;
        position: absolute;
        white-space: nowrap;
        width: 1px;
    }

    // 中間按鈕的部分修飾
    &__toggle {
        cursor: pointer;
        width: 4em;
        border: 2px solid var(--clr-light);
        background: transparent;
        padding: 0;
        // vmax = vh,vw的最大值
        border-radius: 100vmax;
        margin: 0 1em;

        // 中間圓點修飾
        &::after {
            content: '';
            display: block;
            background: var(--clr-light);
            border-radius: 50%;
            height: 1rem;
            margin: 3px;
            width: 1rem;
            // 左側自動填滿margin所以球會移動到最右邊
            margin-left: auto;
        }
    }

    // 偽類選擇器:checked只會使用在任何選中狀態下的radio(<input type="radio">)，checkbox (<input type="checkbox">) 或("select") 元素中的option HTML元素("option")。
    // 當選中checked時則底下的after修飾也就是圓點的部分會移動回左邊只有margin:3px的狀態
    :checked~.unit__toggle::after {
        margin-left: 3px;
    }
}
```


## .previous-weather

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

* 把整個區塊往下拉
* 下拉做動畫`transition: transform 350ms ease;`


### .previous-weather

```sass=
.previous-weather {
    background: var(--clr-light);
    color: var(--clr-dark);
    position: absolute;
    bottom: 0;
    width: 100%;

    // 把previous-weather欄位往下60%
    transform: translateY(60%);
    transition: transform 350ms ease;
    padding: 3em;
}
```

### .show-previous-weather

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

* 設定定位上面`transform: translate(-50%, calc(-100% - 3rem));`因為整個previou-weather視窗padding是3rem這邊必須扣掉不然會超出去
* line-height跟其他地方一樣都設定1
* clip-path: polygon 一樣使用裁減功能成三角形
* 特別的地方是font-family必須使用繼承inherit才吃的到

#### .span
* span的部份做箭頭旋轉特效但這邊還沒轉顯示正常的0度


```sass=
.show-previous-weather {
    cursor: pointer;
    position: absolute;
    background: var(--clr-light);
    left: 50%;
    width: 10rem;

    // 這邊因為在previous-weather上加入padding會使箭頭區域跑掉所以加上clac而外加上3rem來確保位置不會跑掉
    transform: translate(-50%, calc(-100% - 3rem));
    text-align: center;
    font-size: var(--fs-h2);
    line-height: 1;
    clip-path: polygon(50% 0, 0 100%, 100% 100%);
    color: var(--clr-gray);
    border: 0;
    font-family: inherit;

    &:hover,
    &:focus {
        color: var(--clr-dark);
    }

    span {
        display: block;
        transform: rotate(0);
        transition: transform 300ms ease;
    }
}
```

### .previous-days, .previous-weather__title, .previous-day

下方的整區
![](https://i.imgur.com/s2nuu2M.png)

* flex直接讓他們成行排列並且space-between讓中間空隙一樣
* title置中
* 針對文字，按鈕做修飾

```sass=
.previous-days {
    display: flex;
    justify-content: space-between;
}

.previous-weather__title {
    text-align: center;
}

.previous-day {
    opacity: 0;

    &>* {
        margin: 0;
    }

    &__date {
        font-size: .9rem;
        color: var(--clr-gray);
    }

    &__more-info {
        border: 0;
        border-radius: 100vmax;
        background: var(--clr-dark);
        color: var(--clr-light);
        text-transform: uppercase;
        padding: .3em 1em;
        cursor: pointer;
        margin-top: 1em;

        &:hover {
            background: var(--clr-gray)
        }
    }
}
```

### .show-weather.previous-weather

這邊針對加上.show-weather的.previous-weather做處理也就是整個視窗移上來的時候

#### span

* 當視窗移動上來的時候span裡面的箭頭會轉180度
* Y軸也要調整不然會跑版

#### .previous-weather__title, .previous-day

* 做透明變成不透明特效並且製作slideUpIn特效 
* 使用forwards讓特效結束後停在原地不繼續執行
* 把標題移動到左邊

#### 使用@each

* 個別印出不同的delay時間做出這個特效

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


* 使用sass list 建立包含(index delay時間)
* 使用each 個別印出list內部所有元素
* 使用#{}選取動態的變數丟入nth-child()內
* 使用nth()選取list內部的第一位以及第二位分別貼上nth-child,animation-delay


```sass=
$slidTime: 1 100ms,
    2 125ms,
    3 150ms,
    4 175ms,
    5 200ms,
    6 225ms,
    7 250ms;

    @each $slide in $slidTime {
        .previous-day:nth-child(#{nth($slide,1)}) {
            animation-delay: #{nth($slide,2)};
        }
    }
```

#### @keyframes

* 設定透明以及標題移動特效


```sass=
.show-weather.previous-weather {
    transform: translateY(0);

    .show-previous-weather span {
        display: block;
        transform: rotate(180deg) translateY(-6px);
    }

    .previous-weather__title,
    .previous-day {
        opacity: 1;
        animation: slideUpIn 750ms forwards;
    }

    .previous-weather__title {
        text-align: left;
    }

    // 讓previous-day的資料有一個一個上來的特效
    $slidTime: 1 100ms,
    2 125ms,
    3 150ms,
    4 175ms,
    5 200ms,
    6 225ms,
    7 250ms;

    @each $slide in $slidTime {
        .previous-day:nth-child(#{nth($slide,1)}) {
            animation-delay: #{nth($slide,2)};
        }
    }
}

@keyframes slideUpIn {
    0% {
        opacity: 0;
        transform: translateY(50%);
    }

    100% {
        opacity: 1;
        transform: translateY(0%);
    }
}
```