題目除了基本 Notification Card介面樣式以外,還有兩個重要的介面
Menu
Search
上面的圖是題目,而我們要做出幾乎一樣的樣子,題目中還有附上出題官方的CodePen,也有附上給我們解題用的template,當我們真的不會的時候,還是可以參考他們的寫法,所以沒有想像中困難。
我做好的此題CSS Challeage解答
那麼我們就開始吧。
我們上次已經做完 Notification Card - 藍色 header 的部分,長這樣:
那我們今天先來做卡片白色區塊的訊息部分。
<div class="content">
<div class="line"></div>
<div class="notify">
<div class="dot"></div>
<span class="time">9:24 AM</span>
<p><b>John Walker</b>posted a photo on your wall.</p>
</div>
</div>
首先,一樣先開版,把結構作出來。
通知有三則,但我示範就不寫出來,大家記得 copy 三段 .notify 並且把內文改成跟題目一樣的其他通知。
畫面上有一條灰色直線,所以我做一個 div 取名 .line。
接下來的是一則通知包裹在一個 div 裡面,所以將這個 div 取名為 .notify。
他裡面的結構分別是藍色空心圓點,取名 .dot。
小字的時間,這邊我用 span 來製作,取名 .time。
主要的通知文字,這邊我用 p 來製作,裡面人名的部分有粗體,所以直接給他包一個 b。
這樣基礎架構就完成了,剛做好還沒有寫樣式的時候會是這樣:
.content {
...
.line {
position: absolute;
background-color: #EBEBEB;
width: 3px;
top: 0;
left: 27px;
bottom: 0;
}
}
我們上一集已經設定過 .content 了,這次就直接在裡面加入 .line 的樣式。
先設定它的 position: absolute 讓我們能定位他,接著一樣用第一天教的小工具去吸色,改好他的背景色,設定好寬度,基本上就差不多了。
.content {
...
.notify {
position: relative;
margin: 25px 20px 25px 40px;
cursor: pointer;
&:hover {
color: $blue;
}
}
}
因為通知裡面的 .dot 會需要用 absolute 定位的方式來製作,所以這邊先把 .notify 加上 position: relative。
接著視覺上檢查調整一下 padding 的部分。
由於題目是滑鼠指上時,整則通知的文字要變成藍色,且我看他並沒有需要漸變效果,所以這邊我就只有加上 cursor: pointer 及滑鼠指上的變色,我就沒有做 transition。
剛做好的時候長這樣:
.content {
...
.notify {
.time {
display: block;
font-size: 11px;
}
.p {
font-size: 15px;
line-height: 20px;
.b {
font-weight: 600;
display: inline-block;
margin-right: 5px;
}
}
}
}
那我們就再去裡面調整 .time p 各自的文字樣式,字體大小,字距行高等等。調整完之後長這樣:
接著來做藍色空心圓點的部分
.content {
...
.notify {
...
.dot {
position: absolute;
width: 7px;
height: 7px;
border: 2px solid $blue;
background-color: #fff;
box-shadow: 0 0 0 3px #fff;
top: 0;
left: -17px;
border-radius: 100%;
z-index: 3;
}
}
}
一般這種空心圓點,大部分有概念的人應該都知道,就是做一個 div 給他個藍色的 border,使用 border-radius 讓他變成圓形,中間 background-color 填白色就好。
但是他這顆比較特別是,他的藍色 border 外面還有一圈白色。
這個部分對初學的人可能會有點 tricky,但也可能有人完全沒有注意到這個小細節...
其實這個外圍的白色不難,我們只要用 box-shadow 就可以做到,這邊我設定的是 box-shadow: 0 0 0 3px #fff。
在 box-shadow: 0 0 0 3px #fff 中,各數字代表不同的含義:
0:水平偏移量,控制陰影向左或向右的偏移。0:垂直偏移量,控制陰影向上或向下的偏移。0:模糊半徑,控制陰影的模糊程度(0 表示無模糊)。3px:擴展半徑,控制陰影的擴展範圍。#fff:陰影的顏色,這裡為白色。這樣的設定使陰影均勻地包圍元素,視覺上看起來就像一條 3px 左右的白色線條包在外面似的,達到跟題目一樣的效果,這樣卡片的介面開版就做好了。
.notify 的動畫接著我們來處理初次載入畫面的時候,.notify 的動畫效果。
@keyframes fade-up {
from {
opacity: 0;
transform: translate(0, 50px);
}
to {
opacity: 1;
transform: translate(0, 0);
}
}
我先寫了一個 fade-up 動畫,從完全透明並向下偏移 50px 開始,逐漸變為完全不透明並回到原始位置 translate(0, 0)。
然後把這個動畫套用到我們 .notify 的元素內。
.notify {
...
@for $i from 2 through 4 {
&:nth-child(#{$i}) {
animation: fade-up .5s ease-out ($i/5 + s);
animation-fill-mode: both;
}
}
這邊我不直接把動畫寫在 .notify 上,是因為它們的出現有延遲,不像這題的其他動畫,都是單純的移動跟出現,這邊動畫的 .notify 是一則一則出現的,所以我們需要去計算這個延遲。
使用 @for 迴圈來針對每個第 2 到第 4 個子元素 nth-child(2) 到 nth-child(4) 應用動畫。
這是因為 .notify 內的第一個元素是 .line 灰色線條,而他不需要做這個延遲出現的動畫。
animation 設定為剛剛做好的 fade-up,持續 0.5 秒,並且每個元素的動畫延遲 (i/5) 秒以產生依次淡入的效果。
(i/5) 這段是指在動畫的延遲時間上根據元素的位置進行計算。在這裡,$i 是 Sass 的變數,它從 2 到 4 迴圈執行。
(2/5) 秒,也就是 0.4 秒。(3/5) 秒,也就是 0.6 秒。(4/5) 秒,也就是 0.8 秒。這樣可以讓每個元素按順序依次出現並淡入,達成我們想要的效果。
這樣整個 Notification Card 就做好了,接著我們來製作上面的 Search Input。

<header>
<div class="menuIcon"></div>
<h1>Notifications</h1>
<button class="searchIcon">
<i class="fa fa-search search-icon"></i>
</button>
<input class="searchInput" type="text" placeholder="Search ..." /> //增加這句
</header>
我們先在原先的 .searchIcon 後面增加一個 input 取名為 .searchInput。
header {
.searchInput {
position: absolute;
right: 55px;
z-index: 5;
box-sizing: border-box;
background-color: #fff;
outline: none;
font-size: 12px;
padding: 8px 16px;
border-radius: 17px;
width: 77%;
}
}
先把 position: absolute 加上後,由於他是要從右邊滑出來,所以我讓他的定位點是在右邊,這裡我設定 right: 55px。

記得加上 outline: none 讓 :focus 時 input 的外框消失。
再依據視覺上看起來的樣式,調整一下上下左右的 padding border-radius 跟文字大小等等,就差不多可以了。
做好之後長這樣:
.searchInput {
...
opacity: 0;
transition: all ease-in-out .3s;
transform: translateX(15px);
&.show {
opacity: 1;
transform: translateX(0);
}
}
動畫部分的原理是這樣的,當使用者點擊旁邊的 search icon 時,我們寫一段 javascript 去檢查我們目前的這個 search input 上面有沒有 .show 這個樣式,沒有的話加上,有的話移除。
所以我們可以先來修改一下 .searchInput,先把他的透明度改成 0,因為一開始的時候是看不到這個 input 的。這時候當然要在 .show 裡面同步加上透明度 1,這樣才會如願顯示。
把 transform: translateX(15px) 加上,讓整個 search input 往右邊位移 15px,並且在 .show 裡面同步加上 transform: translateX(0) 讓他回到原點。
因為動態是做在 .searchInput 本人身上,所以不要忘記在他身上加上漸變用的 .transition: all ease-in-out .3s。
然後我們來設定JS,先 include 這個 library
$(".searchIcon").bind('click', function(){
$('.searchInput').toggleClass('show');
});
然後我們加上 javascript,去 toggle 增加或刪除 .show 這個 class,這樣我們的按鈕就可以操作了。
雖然按鈕可以操作,但一定有人發現問題了。
就是雖然按鈕看起來消失了,但我們滑鼠在 .menuIcon 的位置附近晃,尤其是靠近Icon右上角圓點的地方,竟然會出現輸入的滑鼠游標?
因為他雖然看不到,可是他只是透明的而已,而且在那個位置他擋住 .menuIcon 讓他的右半邊都按不到,這是蠻嚴重的問題,讓我們來修正吧~
.searchInput {
...
pointer-events: none;
&.show {
...
pointer-events: all;
}
}
這時候就回到剛剛 .searchInput 的地方,加上一句 pointer-events: none,用 CSS 控制讓他不接受任何滑鼠的動作。
那同樣的,記得在 .show 這邊加回來讓滑鼠可以動作的語法 pointer-events: all 這樣就差不多完成了。
由於篇幅太長了,我決定再分篇寫,下一篇再來寫後面的 Menu。
希望改變了這種按照步驟的寫法,能讓更多人看得懂,也能跟我一樣喜歡上寫CSS。
那今天就先到這裡,明天我們再繼續來玩下一集。