欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > CSS flex布局 列表单个元素点击 本行下插入详情独占一行

CSS flex布局 列表单个元素点击 本行下插入详情独占一行

2025/2/22 2:03:29 来源:https://blog.csdn.net/Cxiaomu/article/details/145596947  浏览:    关键词:CSS flex布局 列表单个元素点击 本行下插入详情独占一行

技术栈:Vue2 + javaScript

简介

在实际开发过程中有遇到一个场景:一个list,每行个数固定,点击单个元素后,在当前行与下一行之间插入一行元素详情,便于更直观的查看到对应的数据详情。
这种情形,在移动端比较常见,比如用户列表,点击单个列表 展示详情,可以考虑 flex 布局 + position relative 定位。

实现

思路

对于需求重点和实现拆解

  1. 列表元素:for 遍历
  2. 每行固定(3)个元素:flex布局、宽度%
  3. 详情在该元素下独占一行:for 内元素、position relative

核心代码

mock数据

// list数据
list: [{ id: 1, name: '测试数据1', desc: '测试数据1描述测试数据1描述测试数据1描述测试数据1描述' },{ id: 2, name: '测试数据2', desc: '测试数据2描述测试数据2描述测试数据2描述测试数据2描述' },{ id: 3, name: '测试数据3', desc: '测试数据3描述测试数据3描述测试数据3描述测试数据3描述' },{ id: 4, name: '测试数据4', desc: '测试数据4描述测试数据4描述测试数据4描述测试数据4描述' },{ id: 5, name: '测试数据5', desc: '测试数据5描述测试数据5描述测试数据5描述测试数据5描述' },{ id: 6, name: '测试数据6', desc: '测试数据6描述测试数据6描述测试数据6描述测试数据6描述' },{ id: 7, name: '测试数据7', desc: '测试数据7描述测试数据7描述测试数据7描述测试数据7描述' },{ id: 8, name: '测试数据8', desc: '测试数据8描述测试数据8描述测试数据8描述测试数据8描述' },{ id: 9, name: '测试数据9', desc: '测试数据9描述测试数据9描述测试数据9描述测试数据9描述' },{ id: 10, name: '测试数据10', desc: '测试数据10描述测试数据10描述测试数据10描述测试数据10描述' },{ id: 11, name: '测试数据11', desc: '测试数据11描述测试数据11描述测试数据11描述测试数据11描述' }],showDetail: false, // 是否显示详情detail: {}, // 详情数据

DOM结构

<!-- 列表容器 -->
<div class="container"><!-- 单个元素 start--><div v-for="(item, index) in list" :key="index" class="item-box" @click="toggleEvent(item)"><div class="item-name">{{ item.name }}</div><!-- 详情 start --><div class="item-detail" v-if="showDetail && detail.id == item.id" :style="caculateDetailLeft(index)"><!-- 气泡三角 --><div class="top-jian" :style="caculateJianLeft(index)"></div><!-- 详情描述 --><div>{{ detail.desc }}</div></div><!-- 详情 end --></div><!-- 单个元素 end -->
</div>

CSS 与 动态位移

.container {width: 80vw; // 列表固定宽度display: flex;gap: 16px; // 元素间距flex-wrap: wrap;.item-box {// calc((父元素宽度 - 间距*(每行个数-1)) / 每行个数)width: calc((100% - 32px) / 3); .item-detail {width: 80vw; // 列表固定宽度position: relative; background: #AFF050;.top-jian {width: 20px;height: 20px;position: absolute;background: #AFF050;-webkit-transform: rotate(45deg);transform: rotate(45deg);top: -6px;}}}
}
 caculateDetailLeft(index) {return {// calc(calc(calc(100% + 16px) * ${index%3}) * -1)// calc(-1 * (100% + 间距) * ${index % 每行个数})left: `calc(-1 * (100% + 16px) * ${index % 3})`}},
caculateJianLeft(index) {return {// calc(calc(calc((100% - 32px) / 3) * ${index%3}) + calc((100% - 32px) / 6))// calc((100% - 间距*2) * (${index % 每行个数} / 每行个数 + 1 / (每行个数*2)))left: `calc((100% - 32px) * (${index % 3} / 3 + 1 / 6))`}}

效果

展开效果

完整代码

<template><div class="container"><div v-for="(item, index) in list" :key="index" class="item-box" @click="toggleEvent(item)"><div class="item-name">{{ item.name }}</div><div class="item-detail" v-if="showDetail && detail.id == item.id" :style="caculateDetailLeft(index)"><div class="top-jian" :style="caculateJianLeft(index)"></div><div>{{ detail.desc }}</div></div></div></div>
</template>
<script>export default {name: 'Test',data() {return {list: [{ id: 1, name: '测试数据1', desc: '测试数据1描述测试数据1描述测试数据1描述测试数据1描述' },{ id: 2, name: '测试数据2', desc: '测试数据2描述测试数据2描述测试数据2描述测试数据2描述' },{ id: 3, name: '测试数据3', desc: '测试数据3描述测试数据3描述测试数据3描述测试数据3描述' },{ id: 4, name: '测试数据4', desc: '测试数据4描述测试数据4描述测试数据4描述测试数据4描述' },{ id: 5, name: '测试数据5', desc: '测试数据5描述测试数据5描述测试数据5描述测试数据5描述' },{ id: 6, name: '测试数据6', desc: '测试数据6描述测试数据6描述测试数据6描述测试数据6描述' },{ id: 7, name: '测试数据7', desc: '测试数据7描述测试数据7描述测试数据7描述测试数据7描述' },{ id: 8, name: '测试数据8', desc: '测试数据8描述测试数据8描述测试数据8描述测试数据8描述' },{ id: 9, name: '测试数据9', desc: '测试数据9描述测试数据9描述测试数据9描述测试数据9描述' },{ id: 10, name: '测试数据10', desc: '测试数据10描述测试数据10描述测试数据10描述测试数据10描述' },{ id: 11, name: '测试数据11', desc: '测试数据11描述测试数据11描述测试数据11描述测试数据11描述' }],showDetail: false,detail: {},}},methods: {toggleEvent(item) {if (item.id == this.detail.id) {this.showDetail = !this.showDetail} else {this.showDetail = truethis.detail = { ...item }}},caculateDetailLeft(index) {return {// calc(calc(calc(100% + 16px) * ${index%3}) * -1)left: `calc(-1 * (100% + 16px) * ${index % 3})`}},caculateJianLeft(index) {return {// calc(calc(calc((100% - 32px) / 3) * ${index%3}) + calc((100% - 32px) / 6))left: `calc((100% - 32px) * (${index % 3} / 3 + 1 / 6))`}}}
}
</script>
<style lang="scss" scoped>
.container {width: 80vw;display: flex;gap: 16px;flex-wrap: wrap;.item-box {width: calc((100% - 32px) / 3);.item-name {border: 1px solid #ccc;padding: 30px;text-align: center;border-radius: 15px;}.item-detail {width: 80vw;position: relative;background: #AFF050;margin-top: 16px;padding: 30px;border-radius: 15px;.top-jian {width: 20px;height: 20px;position: absolute;background: #AFF050;-webkit-transform: rotate(45deg);transform: rotate(45deg);top: -6px;}}}
}
</style>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词