上面的圖是題目,而我們要做出幾乎一樣的樣子,題目中還有附上出題官方的CodePen,也有附上給我們解題用的template,當我們真的不會的時候,還是可以參考他們的寫法,所以沒有想像中困難。
我做好的此題CSS Challeage解答
那麼我們就開始吧。
這個題目要求我們製作一個Profile的介面。
介面卡片底下是一個漸層的陰影,介面卡片上面的每個按鈕包含右邊的Posts, Likes, Follower都有滑鼠指上的效果。
主要挑戰的是圓形的照片區塊,滑鼠指上線條圖節點的時候,外圍的線條要有360度的交叉旋轉,外圈的向右順時針旋轉,內圈的向左逆時針旋轉。
且兩個圓圈之間的視覺上要看起來距離是平均的,必須是兩個有缺口的同心圓。
<div class="frame">
<div class="card">
<!-- left side -->
<div class="profile">
<div class="profilePic"></div>
<div class="info"></div>
<div class="action"></div>
</div>
<!-- right side -->
<div class="statistic"></div>
</div>
</div>
一開始先開出基礎的版型,我們使用官方提供的template做修改,把 .center
改成 .card
做為卡片區塊,在裡面再區分成左右兩邊,左邊是 .profile
,右邊是.statistic
。
$coffee: #786450;
.frame {
background: linear-gradient(45deg, #eebe6b 0%,#ca7c4d 100%);
color: $coffee;
}
這時候就可以使用我們第一天教的小工具來吸色,再使用工具內的漸層產生工具(可以參考第一天的文章),來製作底色(當然要自己也也可以,這邊我使用45度來寫漸層。
另外,由於卡片整體的顏色都是咖啡色,加上照片四周的動畫區塊,下面圓角按鈕在滑鼠指上後變化的底色,看起來也都是同一個顏色,所以這邊我直接使用變數儲存這個顏色。
.card {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
width: 320px;
height: 300px;
border-radius: 3px;
box-shadow: 10px 10px 15px 0 rgba(0,0,0,.3);
background-color: #fff;
display: flex;
}
先幫中間的卡片區塊做出樣式。
置中的部分,本來template在 .center
就已經做好了,所以我們只需要加上寬高、些微的圓角、背景色跟看起來類似的 box-shadow
。
由於我們已經確定 .card
內部的樣子是需要左右擺放的,所以這裡我們直接在卡片上加上一句 display: flex
讓裡面左右兩個 div
可以實現併排(雖然畫面上衣片空白都還看不到)
做好之後長這樣:
<!-- left side -->
<div class="profile">
<div class="profilePic"></div>
<div class="info">
<h1 class="name">Hitomi Yang</h1>
<span class="job">Front-end Developer</span>
</div>
<div class="action">
<button class="btn" type="button">Follow</button>
<button class="btn" type="button">Message</button>
</div>
</div>
接著設定卡片內左右物件內的元件,.profile
內依序是.profile
info
action
,我習慣先把東西都整理好再來設定CSS。
.info
內我就放上我自己的名稱跟職稱,分別用 h1
跟 span
來包裹他們。
.action
內就照著題目放入兩個 button
,取名為 .btn
,文字則依照題目的貼上不同的文字內容。
<div class="statistic">
<div class="box">
<span class="value">523</span>
<span class="param">Posts</span>
</div>
<div class="box">
<span class="value">1387</span>
<span class="param">Likes</span>
</div>
<div class="box">
<span class="value">146</span>
<span class="param">Follower</span>
</div>
</div>
右邊是由三個資訊塊組成的,所以我先設定右邊內的每個區塊都叫 .box
,這樣他們能才吃到一樣的樣式。
在 .box
裡面再依照內容,用兩個 sapn
去包裹數值 .value
跟名稱 .param
,照著題目把內容的文字都貼上去,接著就來設定它的樣式。
剛畫好還沒有任何 style 的時候長這樣:
.profile {
width: 220px;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
& > * + * {
margin-top: 20px;
}
}
先設定好左邊 .profile
區域的寬度,將他的 display
設定為 flex
,並設定 flex-direction: column
,讓排列的順序由上往下排。
接著加入 justify-content: center
跟 align-items: center
,這是為了要排列內部的所有東西除了垂直置中以外,也能在這個區塊的上下置中的位置呈現。
這裡我喜歡的一個小技巧是 & > * + *
選擇器,他能選擇這個區塊內所有第一層的物件中,他的後面還有物件的物件。這樣講可能拗口,簡單說,他就是能讓你選擇「這個區塊內,第一層的所有物件,除了第一個物件」,選到他們之後,我就會加上 margin-top: 20px
讓他們彼此之間有 20px
的固定間距。
但是第一個物件,他距離上面是不會有 margin
的,這真的很方便。
大區塊調整完了,來製作內容,照片那區由於要做動畫,我們最後再來弄。
我們首先調整名字跟職稱的部分。
.info {
.name {
padding: 0;
margin: 0;
line-height: 1;
font-size: 15px;
font-weight: 600;
text-align: center;
}
.job {
font-size: 11px;
font-weight: 300;
}
}
name
這邊因為我使用了 h1
,所以要進行 CSS Reset,我就在裡面針對 margin
padding
加入了0的設定。調整字體大小等等,跟題目類似就可以了。
剛做好的時候長這樣:
我們繼續把底下按鈕的部分做完。
.action {
display: flex;
flex-direction: column;
width: 120px;
& > * + * {
margin-top: 10px;
}
}
首先是調整他的排列,跟剛剛 .profile
的部分一樣,我們先使用 flex
屬性讓他從上往下排列,設定區塊的寬度,然後用剛剛教的間距小技巧,讓兩個上下按鈕之間有一定的距離。
這還沒完,接著就來調整按鈕的樣子,還有滑鼠指上的動態。
.action {
...
.btn {
border: 1px solid $coffee;
background-color: #fff;
border-radius: 24px;
color: $coffee;
font-size: 12px;
font-weight: 600;
padding: 7px 12px;
width: 100%;
cursor: pointer;
transition: all ease-in-out .4s;
&:hover {
background-color: $coffee;
color: #fff;
}
}
}
依照題目的樣式,先加入邊框跟底色,調整一下字體的大小,修改 border
的圓角,加入 :hover
時的樣式,滑鼠指上時,我們只有改變背景色跟字體顏色。
最後不要忘記加入動態漸變的關鍵屬性 transition: all ease-in-out .4s
在按鈕本人身上。選擇 all
是為了讓他所有屬性都能使用,包含背景跟字體顏色,.4s
的漸變時間設定好之後,加上 cursor: pointer
,按鈕的區域就全部都完成了。
.statistic {
display: grid;
grid-template-rows: repeat(3, minmax(0, 1fr));
grid-gap: 1px 0;
}
右邊的區塊是用3個格子組成的,加上格子之間都要有白色的空隙,這段如果用 border
來寫,個人覺得很醜,所以這邊又是我最愛的 grid
的主場了。
設定它有3個一樣的 row
,並且設定它們之間上下有 1px
的 gap
,就這樣漂亮的完成了基礎的架構。
再來做裡面每個 .box
的樣式跟文字,加上 :hover
的樣式。
.statistic {
...
.box {
width: 100%;
display: flex;
flex-direction: column;
text-align: center;
background-color: #F5E8DF;
justify-content: center;
cursor: pointer;
transition: all ease-in-out .5s;
&:hover {
background-color: #E1CFC2;
}
.value {
font-size: 17px;
font-weight: 600;
}
.param {
font-size: 11px;
}
}
}
每個 .box
設定成 flex
,並且使用 flex-direction: column
讓它的方向是從上往下,這樣裡面的文字就可以漂亮的上下並排。
再來就是基礎的 flex
設定,讓物建在裡面能漂亮的上下左右置中。
底色一樣使用第一天的小工具來吸色,設定它 :hover
時的底色之後,不要忘了回到 .box
本人身上加上 transition: all ease-in-out .5s
這邊我設定 .5s
,看起來一切都非常完美,畫面卻有個問題:
明明寬度已經設定100%了,為什麼不會滿版呢?
其實這時候如果你把卡片寬度剪去左邊 .profile
的寬度,把剩下的寬度設定在 .statistic
身上就可以解決,但我偏偏不要!我就是想要他自由擴展。
還記得我們在卡片 .card
上面設定了 flex
這個屬性來把卡片分左右兩邊嗎?
這時候就是 flex
在搞事。flex
預設不會自動填滿剩餘的空間,尤其是我們父元素內有其他子元素(例如 .profile
)限制了空間的使用時。
這時候有兩種解法:
解法一:
1. 在你要限制寬度的那個區塊上(這裡的話是 .profile
),加上 flex:none
不允許他伸展或收縮以適應父容器的變化。
2. 在你要根據剩餘空間自動調整寬度的區塊上(這裡的話是 .statistic
),加上 flex:auto
,讓他根據剩餘空間自動調整寬度,同時允許他隨著父容器變化而擴展。
解法二:在要自由擴展的那個區塊(這裡的話是 .statistic
),加上 flex-grow: 1
,一樣是為了設定讓他可以自由擴展。
這樣我們的基礎版面就做好了:
由於篇幅太長了,我決定分兩篇寫,下一篇再來寫後面的個人頭像跟動畫的部分,敬請期待。
希望改變了這種按照步驟的寫法,能讓更多人看得懂,也能跟我一樣喜歡上寫CSS。
那今天就先到這裡,明天我們再繼續來玩下集。