iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0
Modern Web

Dive into CSS Challenge:從問題到解決方案的實踐之旅系列 第 14

Day 14 - CSS Challenge #9:Rainy Night - Weather UI (上)

  • 分享至 

  • xImage
  •  

題目

CSS Challenge Day9
https://ithelp.ithome.com.tw/upload/images/20240926/20169403Uu6JEZvXsn.png

題目是一個看起來像是 Weather Widget 的介面,配上下雨的動畫,並且在初次 loading 時,月亮會有升起的動畫。

上面的圖是題目,而我們要做出幾乎一樣的樣子,題目中還有附上出題官方的CodePen,也有附上給我們解題用的template,當我們真的不會的時候,還是可以參考他們的寫法,所以沒有想像中困難。

我做好的此題CSS Challeage解答

那麼我們就開始吧。

題目分析

這個題目要求我們製作一個天氣 Widget 的畫面

  • 分為上下兩個區塊
    1. 上方圖片
    2. 下方天氣資訊
  • 圖片分為三個部分
    1. 月亮及動畫(初始時由下方升起)
    2. 夜空與後面的山坡地
    3. 下雨的動畫

那這裡我一樣會拆解成幾篇來寫,避免版面太長(我會寫的太累)
首先我們先來寫基本架構,明天再來做動畫。

HTML Preprocessor

https://ithelp.ithome.com.tw/upload/images/20240926/20169403ODPOGkkVeM.png

因為我並不想要放好幾個一樣的 div 在裡面,所以在這裡我跟題目一樣使用了 slim 版本的 HTML 預處理器來寫。

Slim 是一個輕量化的模板語言,它使用縮排來結構化 HTML,簡化了標籤的書寫,不需要閉合標籤,並減少了重複的代碼。這樣可以讓 HTML 更加簡潔易讀,常用於像 Ruby on Rails 這樣的框架中。

例如,傳統 HTML 的寫法:

<div class="container">
  <h1>Hello World</h1>
</div>

在 Slim 中可以這樣寫:

.container
  h1 Hello World

這種語法可以大幅減少 HTML 的冗餘,使模板更易維護。

開始解題

基礎架構

.frame
	.view
	.label
		.temperature 12°
		.info
			.left  Wind: E 7 km/h <br/> Humidity: 87%
			.right
				span TUE
				span 21° / 9°
				span WED
				span 23° / 10°
  • .view:圖片區域
  • .label:下方文字資訊區域
    • .temperature:溫度:文字區域內的左方,氣溫的部分。
    • .info:小資訊:文字區域右方區塊的小字。
      • left:小資訊的左半邊:風速、濕度。
      • right:小資訊的右半邊:顯示不同星期的最高及最低氣溫。
$primary: #3D476A;
$labelH: 90px;
$viewH: 400px - $labelH;

這邊是我先為了目前會用到的區塊設定的變數。

primary:下方資訊區塊的文字顏色,這時候一樣拿出我們第一天的小工具來吸色。這裡我是吸12那邊稍粗一點的字體顏色。

labelH:拿第一天教的小工具出來量下方資訊區塊的高度。
viewH:由於是滿版的,我們已經知道 .frame 本人的高度之後,就直接拿來剪掉下方天氣資訊的高,就可以得知圖片區域多高了。

.frame {
    ...
    background: #192238;
    color: $primary;
}

變數設定好之後,把 frame 的底色跟文字顏色加上去。

.view {
	width: 100%;
	height: $viewH;
	overflow: hidden;
}

這邊是明天我們要做的上方圖片區塊的基本值,先放上去,讓它有一個高度,好方便我們先做底下的天氣資訊。


天氣資訊

背景

.label {
	height: $labelH;
	background-color: #fff;
	box-sizing: border-box;
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 0 20px;
    
    	& > * + * {
		margin-left: 15px;
	}
}

首先,來設定 .label 區塊。

每個標籤內的內容會被排列成一條水平的行,並透過 display: flex 控制對齊。

align-items: center 讓所有元素在垂直方向上置中,而 justify-content: space-between 讓內容均分左右,分別對齊兩端。

padding: 0 20px 則是設定內容左右的內邊距。

另外,& > * + * 則是我很喜歡使用的小技巧,這讓 .label 內第一層的每個元素彼此之間會有 15px 的間距,用來避免內容貼在一起。

溫度

	.temperature {
		font-size: 45px;
		font-weight: 300;
		line-height: 2;
		flex: none;
	}
  • font-size: 45px:將字體大小設為 45px,確保溫度的數字很大,易於閱讀。
  • font-weight: 300:字重設置為 300,表示字體較細,不會過於粗重。
  • line-height: 2:行高設定為 2,讓內容之間有更多的垂直間距,增加可讀性。
  • flex: none:因為這邊我們需要讓右邊的區塊吃到所有剩餘的寬,這樣才能關閉 flex 子元素的彈性行為,保持該元素不會自動調整大小或位置。

小資訊

	.info {
		font-weight: 300;
		display: flex;
		align-items: center;
		line-height: 1.5;
		font-size: 15px;
		flex: 1;

這邊外面再包一層主要是設定區塊內的文字樣式,並且實現靈活的 flex 布局。

  • display: flex:因為這個區塊內的文字,又再分成了左右兩塊,這邊我們就使用 flex 屬性來排列內容,確保子元素能得到靈活的布局。
  • flex: 1:讓這個區塊在彈性容器內占滿剩餘空間。
    .info{
        ...
		.left {flex: 1;}
    }

小資訊區塊內左方的文字,這邊其實是一行字,我們單純的使用
<br/> 來讓它們換行就已經足夠,加上剛剛已經設定好的 line-height,這邊並不需要太多的操心。

加上由於已經設定好的字體的大小顏色等等,這邊只需要設定這個區塊的 flex ,確保它能夠在彈性容器內占滿剩餘的空間即可。

    .info {
        ...
        .right {
			flex: 1;
			display: grid;
			grid-template-columns: repeat(2, minmax(0, 1fr));
			text-align: right;
			column-gap: 10px;
			justify-content: space-between;
			
			span:nth-child(odd) {
				text-transform: uppercase;
			}
			span:nth-child(even) {
				font-weight: 400;
			}
		}
    }

這邊是小資訊的右方區塊。
這邊我使用我愛用的 grid 來進行編排,讓我說明一下:

  • flex: 1:讓 .right 區塊在父容器中填滿剩餘的空間。
  • grid-template-columns: repeat(2, minmax(0, 1fr)):將區塊分成左右兩個等寬的欄位,有超出的 column 都會依照這個規則繼續往下往右排列。
  • text-align: right:將文本對齊到右側。
  • column-gap: 10px:欄位之間的間距設定為 10px。
  • span:nth-child(odd)span:nth-child(even):為奇數和偶數的 <span> 元素設定不同樣式,奇數大寫,偶數設置較細字重。這邊奇數的就是星期幾的部分,而偶數則是右邊的最高/最低溫的區域。

那做完之後大概就長這樣
https://ithelp.ithome.com.tw/upload/images/20240928/20169403UQtRNabdg5.png

由於之前我都一次寫太多,搞的自己很累,我決定之後儘量分小段寫,這樣比較不會太辛苦,那就先這樣,明天我們再來繼續做上方圖片的部分。


Wrap up and go home

希望改變了這種按照步驟的寫法,能讓更多人看得懂,也能跟我一樣喜歡上寫CSS。

那今天就先到這裡,明天我們再繼續來玩下一集。


上一篇
Day 13 - CSS Challenge #8:Metaballs use CSS filter for animation
下一篇
Day 15 - CSS Challenge #9:Rainy Night - Weather UI (中)
系列文
Dive into CSS Challenge:從問題到解決方案的實踐之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言