??前言
- 這個(gè)小項(xiàng)目源于github項(xiàng)目:?50 projects 50 days, 這個(gè)項(xiàng)目包含了50個(gè)小型前端項(xiàng)目,適合學(xué)習(xí)了Html+Css+JavaScript但是還沒(méi)有學(xué)習(xí)框架的前端新手作為練習(xí)。
- 這里是原項(xiàng)目的代碼實(shí)現(xiàn)??擴(kuò)展卡片 Expanding Cards
??分析

??布局
- 卡片橫向排列,可以使用flex布局.
- 文字位于卡片左下角,可以將卡片設(shè)置為相對(duì)定位
position:relative;,文字設(shè)置為絕對(duì)定位position:absolute;,然后設(shè)置left和bottom屬性.
??文字樣式
- 大卡片有文字,小卡片沒(méi)有文字,一開(kāi)始的想法是給小卡片的文字設(shè)置
display:none;,大卡片的文字設(shè)置display:block;。后來(lái)發(fā)現(xiàn)不可行,因?yàn)辄c(diǎn)擊小卡片后,一開(kāi)始卡片還沒(méi)完全變大,但是如果此時(shí)將文字的display:none;更換為display:block;則會(huì)出現(xiàn)文字被較小的寬度擠成好幾行,盡管設(shè)置成溢出時(shí)不換行、顯示省略號(hào)的樣式,文字也是突然出現(xiàn)的,較為突兀。
- 顯示文字與否可以用調(diào)整透明度實(shí)現(xiàn),不顯示則
opacity:0;,顯示則opacity:1;,并且可以使用transition:opacity ease;,這樣的話,過(guò)渡就會(huì)比較自然。
??點(diǎn)擊事件
- 這里我使用了事件委托,而不是每一個(gè)卡片都綁定點(diǎn)擊事件,這樣可以提高效率。事件委托是給這些卡片的父元素綁定點(diǎn)擊事件,通過(guò)事件冒泡原理,當(dāng)點(diǎn)擊卡片時(shí),父元素會(huì)檢測(cè)到點(diǎn)擊事件,然后可以通過(guò)event對(duì)象的target屬性找到是哪一個(gè)卡片被點(diǎn)擊了。這樣的話就可以只綁定一個(gè)點(diǎn)擊事件,而不是有多少卡片就要綁定多少點(diǎn)擊事件,從而提高了效率。
- 點(diǎn)擊事件觸發(fā)后:
- 所有卡片變成小卡片,即寬度設(shè)置為統(tǒng)一的較小的值。
- 被點(diǎn)擊的卡片變成大卡片,即寬度設(shè)置為較大的值。
- 修改被點(diǎn)擊的卡片內(nèi)部文字的
opacity,使其顯現(xiàn)。
??代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>expanding-cards</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
min-height: 100vh;
}
.container{
min-height: 100vh;
width: 100%;
/* 使用flex布局 */
display: flex;
align-items: center;
justify-content: center;
padding: 0 60px;
}
.item{
width: 10%; /* 小卡片統(tǒng)一的寬度 */
height: 80vh;
margin: 0 1rem;
position: relative; /* 卡片設(shè)置相對(duì)定位 */
border-radius: 2rem;
background-repeat: no-repeat;
background-size: cover;
cursor: pointer;
transition: all ease-in-out 0.5s;
}
/* 卡片的背景圖片源自原項(xiàng)目 */
.item:nth-of-type(1){
background-image: url('https://images.unsplash.com/photo-1558979158-65a1eaa08691?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
}
.item:nth-of-type(2){
background-image: url('https://images.unsplash.com/photo-1572276596237-5db2c3e16c5d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
}
.item:nth-of-type(3){
background-image: url('https://images.unsplash.com/photo-1507525428034-b723cf961d3e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1353&q=80');
}
.item:nth-of-type(4){
background-image: url('https://images.unsplash.com/photo-1551009175-8a68da93d5f9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1351&q=80');
}
.item:nth-of-type(5){
background-image: url('https://images.unsplash.com/photo-1549880338-65ddcdfd017b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
}
/* 大卡片的寬度 */
.focus{
margin: 0 1rem;
width: 50%;
}
.item p{
/* 小卡片內(nèi)部文字是不可見(jiàn)的 */
opacity: 0;
}
.focus p{
/* 大卡片內(nèi)部文字可見(jiàn) */
opacity: 1;
transition: all ease-in-out 0.5s;
color: #fff;
font-size: 32px;
font-weight: bold;
/* 文字使用絕對(duì)定位,并設(shè)置bottom和left,將文字置于卡片左下角 */
position: absolute;
bottom: 40px;
left: 40px;
}
</style>
</head>
<body>
<div class="container">
<div class="item focus"><p>Explore the world</p></div>
<div class="item"><p>Wild Forest</p></div>
<div class="item"><p>Sunny Beach</p></div>
<div class="item"><p>City on Winter</p></div>
<div class="item"><p>Mountains - Clouds</p></div>
</div>
</body>
<script>
window.onload = function(){
// 獲取DOM元素
const container = document.getElementsByClassName('container')[0];
const item = document.getElementsByClassName('item');
//綁定點(diǎn)擊事件(事件委托)
container.onclick = function(e){
e = window.event || e; //兼容firefox
const target = e.target; //從target屬性獲取到被點(diǎn)擊的元素
//首先將所有卡片設(shè)置為小卡片
for(let i=0;i<item.length;i++){
item[i].classList.remove('focus');
}
//被點(diǎn)擊的卡片額外設(shè)置成大卡片
target.classList.add("focus");
}
}
</script>
</html>
參考文章