題目除了基本 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。
那今天就先到這裡,明天我們再繼續來玩下一集。