# Mars Weather - SASS project
---
tags: HTML, CSS, SASS relate
---
###### tags: `HTML, CSS, SASS`
# 製作一個火星天氣觀測網頁
## 成品:

[成品網址](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

* 做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

* 抓取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
綠色框框處

```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
綠色框框處

```sass=
.reading {
font-size: var(--fs-h1);
margin: 0;
color: var(--clr-gray);
}
```
### .date
內容包含天次以及日期

整個視窗的抓取位置在第一到第二欄位
```sass=
.date {
grid-column: 1/2;
&__day {
font-size: var(--fs-h2);
margin: 0;
color: var(--clr-gray);
font-weight: var(--fw-light);
}
}
```
### .temp

* 抓取位置在第二到第三格
* 處理左右兩邊的格線
```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

第二次grid為了排列圓盤以及標題風速

第三次grid為了排列指針

#### 整個.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

* 抓取位置
```sass=
.info {
grid-column: 1/3;
}
```
### .unit
可調整式按鈕藉由SCSS全部製作出來!

#### 整個外框

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

* 引入的sr-only的內容隱藏checkbox
#### unit__toggle
* 中間的橢圓形外框修飾
#### unit__toggle::after
* 中間的圓球的部分點擊兩側的溫度則會移動,左側自動填滿margin所以球會移動到最右邊
*  因為這個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

* 把整個區塊往下拉
* 下拉做動畫`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

* 設定定位上面`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
下方的整區

* 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時間做出這個特效

* 使用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%);
}
}
```