50 Projects 50 Days不使用任何前端框架,适合初学者练手,巩固前端基础,在这里记录一下学习过程,尤其是一些细节上的问题。
Expanding Cards
Expanding Cards
其实很简单,就是利用flex布局中设置不同的拉伸比例来实现展开效果,通过设置一个特殊的class,这个class的拉伸比例设置为较大的值,再通过JavaScript将该class的设置与点击事件进行绑定即可实现。
使用container
包裹作用只是为了限制左右宽度而已,去掉container结构对样式影响不大。
container
内,每个div只包含一个H3标题子元素,图片部分通过背景样式填充。
<div class="container">
<div class="panel active" id="World">
<h3>Worldh3>
div>
<div class="panel" id="Forest">
<h3>Foresth3>
div>
<div class="panel" id="Beach">
<h3>Beachh3>
div>
<div class="panel" id="City">
<h3>Cityh3>
div>
<div class="panel" id="Mountains">
<h3>Mountainsh3>
div>
div>
跟原项目有一些区别的是我并没有把背景图片链接直接写在div里,而是通过id在css中设置,两者其实效果一致,无非就是这样看起来HTML文件更简洁一些。
body
部分
1. 设置flex主要是为了让元素在整个页面中都是居中显示
2. margin清零则是为了消除浏览器的用户代理样式表对显示效果的影响。
3. height设置100%视高可以让网页全屏显示,实际本地调试发现不设置也OK。
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
margin: 0;
}
container
部分利用flex布局来控制下面的卡片伸缩,这里需要设置一个宽度,否则子元素卡片由于父级没有设置宽度不能撑开盒子尺寸。
.container{
display: flex;
width: 90vw;
}
panel
部分就是卡片主体
1. 设置高度,可以在这里设置,也可以再container统一设置,差别就是有margin的时候在外面设置高度要纳入计算
2. 设置flex拉伸比例flex: 0.5
,这里如果不设置拉伸比例默认是flex: 0 1 auto
,表示不会拉伸,同时由于卡片自身没有设置宽度,子元素又因为绝对定位并不会撑开尺寸,flex布局将会使卡片尺寸缩小至0
3. 背景图片需要调整,background-size: cover
表示优先考虑卡片自身尺寸将背景图覆盖,background-position: center
将背景图片中心和卡片中心对齐,background-repeat: no-repeat
在这里可设可不设,表示不会重复
4. 设置为相对定位是为了给子元素标题绝对定位使用
5. 设置一个特殊class,只改变flex的拉伸比例
.panel{
height:80vh;
flex: 0.5;
margin: 10px;
border-radius: 50px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
position:relative;
transition:all 0.7s ease-in;
cursor: pointer;
}
.panel.active{
flex: 5;
}
panel h3
卡片子元素
1. 改为绝对定位,将标题设置到卡片的左下角,这样之后脱离文档流,父元素将不再拥有基本尺寸,需要注意设置其拉伸比例。
2. 默认透明,特殊class时显示。
.panel h3{
position: absolute;
bottom: 20px;
left: 20px;
color: #fff;
opacity: 0;
}
.panel.active h3{
opacity: 1;
transition:opacity 0.4s ease-in 0.3s;
}
将所有panel
卡片绑定点击事件,回调函数中先是遍历所有元素清楚掉active的class,再给响应事件的对应卡片再加上active。
const panels = document.querySelectorAll('.panel');
const removeActiveClass = () => {
panels.forEach(panel => panel.classList.remove('active'));
}
panels.forEach(panel => {
panel.addEventListener('click', ()=>{
removeActiveClass();
panel.classList.add('active');
})
});
最后要提醒的是,这段脚本要想生效,必须是在body内部引入,因为绑定事件的程序需要再页面加载时就要执行,而如果放在head部分,dom还没有加载出来就已经装载,也不会立即执行,只有在调用的地方才会执行,因此并不能成功给卡片绑定事件。
<body>
<div class="container">
div>
<script src="script.js">script>
body>