大家出門去玩的時候,多少會拍下一些相片,其中有些特別值得紀念的相片,這時候就可以考慮製作個自己的相片集來呈現~
今天我們來實作Day #13
相簿的相片皆取自於Unsplash
Unsplash有世界各地的攝影師或是民眾們拍的高畫質相片,供使用者免費使用,是個許多人找相片素材的地方。此次相片集的地點均在台灣,主題為山,作者的部分以Unsplash Photographers概括。
CodePen: https://codepen.io/stevetanus/pen/BaxZEXG
一開始我們會看到四張照片(.profile),滑鼠滑過時會有遮罩效果(.overlay),並顯示加號(.plus)
按下加號後,我們會看到一個叉叉(.close)一張背景圖片(img.header)、一個大頭貼(.cover)、作者資訊(.name)和更多動作(.action)
這邊特別介紹img
標籤,一定要包含src跟alt兩個屬性,src指向相片的url,alt則為相片失效時的文字。
HTML img tag: https://www.w3schools.com/tags/tag_img.asp
.frame {
...
position: absolute;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
.profile {
position: relative;
margin: 4px 0 0 4px;
width: 194px;
height: 194px;
cursor: pointer;
}
.frame
設定為flexbox,flex-wrap: wrap
使得相片在超過.frame
的寬度時,會跳到下一排,而align-content: stretch
,我們將它改為align-content: flex-start
使得兩排之間沒有空白,在.profile
裡面再使用margin: 4px 0 0 4px
製造出每個相片上方跟左方的margin,讓四張相片完美的在寬長400px的正方形中排列。
remove flex wrap gap between rows: https://stackoverflow.com/questions/38084835/removing-large-gap-between-rows-in-flexbox-layout
img {
object-fit: cover;
width: 100%;
height: 100%;
}
img
設定object-fit: cover
會依照設定的寬長剪裁相片,並保持原本相片比例。
https://stackoverflow.com/questions/15167545/how-to-crop-a-rectangular-image-into-a-square-with-css
.overlay {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
background: #000;
opacity: 0;
transition: all 0.6s ease-in-out;
}
.overlay
設定為絕對屬性,上下左右皆設為0,完整蓋住.profile
,在hover的時候會加上opacity: 0.4
,讓相片產生遮罩效果。
.plus {
position: absolute;
width: 50px;
height: 50px;
top: 50%;
left: 50%;
margin: -25px 0 0 -25px;
background: $red;
transition: all 0.4s ease-in-out;
opacity: 0;
transform: scale(2);
&:before {
position: absolute;
content: "";
width: 14px;
height: 2px;
top: 24px;
left: 18px;
background: #fff;
}
&:after {
position: absolute;
content: "";
width: 2px;
height: 14px;
top: 18px;
left: 24px;
background: #fff;
}
.plus
為在.profile
中的正方形,使用偽元素形成加號,在hover時,會設定opacity: 1
跟transform: scale(1)
的屬性,使其有收斂顯現的感覺。
.detail
的內容一開始會在.frame
的外面,我們透過translate3d
改變Y軸數字來先隱藏內容,再加入.active
的class時,會有背景圖片、個人圖片、叉叉滑下來,以及個人資訊滑上去。
.detail {
...
z-index: 2;
overflow: hidden;
pointer-events: none;
font-size: 0;
&.active{
pointer-events: all;
.header {
transform: translate3d(0, 0, 0);
transition: all 0.6s ease-out;
}
.cover {
transform: translate3d(0, 0, 0);
transition: all 0.6s ease-out;
}
.infos {
transform: translate3d(0, 0, 0);
transition: all 0.6s ease-out;
}
// background會在0.3s從紅色轉為白色,transform的動畫會慢0.6s開始
.close {
transform: rotate(45deg) translate3d(0, 0, 0);
transition: background 0.3s ease-in-out, transform 0.6s ease-out 0.6s;
}
}
.detail
加上.active
後,所有元素都會移動到(0,0,0)的位置,我們以.header
(背景圖片)為例:
.header {
width: 400px;
height: 200px;
object-fit: cover;
transform: translate3d(0, -100%, 0);
transition: all 0.6s ease-in 0.4s;
}
背景圖片占了.frame
的一半,原本的位置為(0, -100%, 0)看不見,在.detail
加上.active
時,才會出現在位置(0,0,0),而.active
被移除時,也會有離開的動畫,等候0.4s,在0.6s的時間回到(0, -100%, 0)
.infos
則是會從下面往上顯現:
.infos {
box-sizing: border-box;
background: $red;
height: 200px;
padding: 67px;
transform: translate3d(0, 105%, 0);
transition: all 0.6s ease-in 0.4s;
}
.infos
為.detail
的下半部,在.detail
加上.active
時,會從原本的位置(0, 105%, 0)來到(0, 0, 0),與上面的背景圖片連接在一起,而.active
被移除時,也會有向下離開的動畫。
由SCSS的屬性知道,.active
為開闔個人資訊的關鍵:
let detail = document.querySelector('.detail');
let profiles = document.querySelectorAll('.profile');
profiles.forEach( profile => {
profile.addEventListener("click", () =>{
detail.classList.add('active');
} )
})
let closeBtn = document.querySelector('.close');
closeBtn.addEventListener('click', function() {
detail.classList.remove('active');
});
在每一張相片(.profile
)點擊時,都會在.detail
加上.active
的class,使得個人資訊出現,而個人資訊頁面的叉叉按鈕被點擊時,會移除.active
的屬性,回復到相片集呈現相片。
forEach: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
HTML
目標 | 屬性 |
---|---|
img tag | url , alt 為必須屬性 |
CSS | |
目標 | 屬性 |
------------- | ------------- |
flex-wrap的中間空白消除 | align-content: flex-start |
保持寬長與相片比例 | object-fit: cover 剪裁相片 |
遮罩 | color: #000 加上opacity: 0 到opacity: 0.4 的hover動畫 |
加號 | transform: scale(2) 到scale(1) ,opacity: 0 到opacity:1 達到收斂出現 |
雙向動畫 | JS控制.active 去達到雙向動畫,兩邊都可以設置transition 來形成不同效果 |
User Gallery的原作者的範例是使用float去排版,因為Thibe小弟弟我學藝不精,尚未接觸過float,未來有機會再去碰碰,就繼續用flex排版,也是從中學習到一些小眉角,原本感覺四四方方的應該很好排吧,其實卻不然。這小小的相片集其實也是富有美感的,從遮罩跟加號的運用再到切換個人頁面,全是細節,讓我也很感嘆竟然在2016年我還是高中生的時候,就已經有這麼厲害的網頁設計,現在起步能學習的東西實在好多