border-collapse在Firefox中的细节问题

本文探讨了使用Table布局时在不同浏览器(如Firefox与IE系列)中遇到的边距显示不一致的问题,提供了具体的解决方案及代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

虽然现在DIV+CSS布局已经很流行并且很成熟了,但仍有一些顽固之人坚持用Table布局,并且嵌套N层表格,他们的理由是追求稳定!进入正题,说一下我最近在一个要用Table布局的项目中遇到的问题:当给页面最顶部的table加了样式以下样式后,该Table的border-top在Firefox(我用的是Firefox3.5)中显示的效果并不是预期的效果,而是比设定的值少几个像素,而在IE上没有问题。如果将border-collapse:collapse;去掉则会(在Firefox与IE中)正常显示。

 

 

 

border-collapse属性设置表格的边框是否被合并为一个单一的边框,还是象在标准的 HTML 中那样分开显示。在一般情况下使用border-collapse并不会出现什么问题,我只在以上的情况中遇到这个问题。为了解决该问题,只有想办法增加在Firefox中距离顶部的距离或是增加上边框的宽度,但并不知道应该增加多少个像素。经过反复试验,发现应该增加的高度(m)与边框高度(b)的关系为:m = (b%2==0) ? b/2 : (b+1)/2。例如上面的边框为5px,则应该增加上边距为3px。

 

因此为了解决上边距在IE6,IE7, Firefox 3.5中的一致性,样式修改如下:

 

 

但是这个方法在IE8上去无法起作用,因为IE8与Firefox识别的是同样的值,即margin:3px auto auto auto,因此在IE8上就要出现边距。到现在还没有找到解决方法。

 

 

完整示例如下:

<template> <div class="cmp-office-list-box" v-if="dataList.length > 0"> <el-scrollbar :style="isCollapse ? 'border: 1px solid rgb(221 221 221 / 61%);height: 750px' : 'height: 750px'"> <!-- 文件列表 --> <div :class="isCollapse ? 'cmp-office-list' : 'cmp-office-list-is-collapse'"> <div class="list"> <div class="list-des-wrap"> <!-- :hid-upload="true" 传true,就是将录入的时候只显示协作文档上传,传了true, 如果不传没有上传入口,那么删除按钮也不需要展示了 --> <div v-for="(item, index) in dataList" :key="item" @click="activateChange(index)"> <iteration-card :isCollaborateForm="isCollaborateForm" :iteration="item" :class="{ active: activeIndex === index }" :hid-upload="hidUpload" :collaborateFileId="collaborateFileId" :dataList="dataList" @save="handleSave" @created="handleCreated" @version="openVersion" @compare="openCompare" @openRecord="openRecord" @lock="handleLock" @unlock="handleUnLock" @delete="handleDelete" @download="handleDownload" > </iteration-card> </div> </div> </div> </div> </el-scrollbar> <div :class="collapseText" @click="isCollapse = !isCollapse" :data-title="isCollapse?'收起':'展开'"></div> <!-- class="custom-tooltip" data-title="提示" --> </div> </template> <script> import bus from '../../../../common/bus'; export default { props: { width: { type: String, default: "290px", }, title: { type: String, default: "合同文档", }, dataList: { type: Array, default: () => [], }, hidUpload: { type: Boolean, default: false, }, isCollaborateForm: { type: Object, default: {}, }, }, data() { return { activeIndex: 0, collaborateFileId: null, isCollapse: true, isInitialized: false, // 监听是否确认最终版 }; }, created() { bus.$on('setMainFile', (data) => { const index = this.dataList.findIndex(item => item.collaborateFileId === data.collaborateFileId); // 神奇逻辑,如果dataList改变会把你设置的activeIndex - 1所以这里加一传入就是正确的索引 this.activateChange(index); }); }, methods: { activateChange(index) { // 每次预览的是新的文件,需要重新加载 if (this.activeIndex !== index && index !== -1) { this.activeIndex = index; this.collaborateFileId = this.dataList[this.activeIndex].collaborateFileId; this.$emit("handleFileIdCallback", this.collaborateFileId); } }, openVersion(iteration){ this.$emit('version', iteration) }, openCompare(iteration){ this.$emit('compare', iteration) }, openRecord(iteration){ this.$emit('openRecord', iteration) }, handleSave(iteration){ this.$emit('save', iteration) }, handleCreated(iteration){ this.$emit('created', iteration) }, async handleLock(iteration) { try { if(iteration.collaborateFileId) { await this.$axios.post(`/composition/collaborate/files/lock/${iteration.collaborateFileId}`, { hideLoading: false }); // 加载协同文件列表 bus.$emit('initCollaborateList') } } catch (error) { console.log(error) } }, async handleUnLock(iteration) { try { if(iteration.collaborateFileId) { await this.$axios.post(`/composition/collaborate/files/unlock/${iteration.collaborateFileId}`, { hideLoading: false }); // 加载协同文件列表 bus.$emit('initCollaborateList') } } catch (error) { console.log(error) } }, handleDelete(iteration) { const { contractId, contractNo } = this.$route.query; // 判断是否是录入页面(区别于草稿页面 草稿页面!==录入页面 const idDraft = contractId || contractNo const { baseInfo , baseInfoData } = this.$store.getters.getInitModel || {} const { agreementType = 0} = baseInfo || baseInfoData || {} const agreementFlag = [1, 2].includes(agreementType); if(idDraft) { const isMainFile = iteration.isMainAttachment === 'Y' const confirmDelete = isMainFile && (contractId || contractNo) && !agreementFlag ? this.$t("message.document.scan.confirmDeleteMain") : this.$t("message.document.scan.confirmDelete") this.$confirm(confirmDelete, this.$t('message.document.borrow.notice'), { confirmButtonText: this.$t('message.document.borrow.confirm'), cancelButtonText: this.$t('message.document.borrow.cancel'), lockScroll:false, type: 'warning' }).then(async () => { // this.$axios.put(`/composition/collaborate/files/delete/${iteration.collaborateFileId}`,{},{ // hideLoading: true // }).then(res=>{ // if( res.data.status === 0 ){ // this.$emit('collaborateDel', iteration) // if(contractId && isMainFile){ // this.$axios.post(`/ai/risk/collaborate/delete/${contractId}`,{ // hideLoading: true // }).then(res=>{ // }) // } // } // }) const delete1 = this.$axios.put(`/composition/collaborate/files/delete/${iteration.collaborateFileId}`,{},{ hideLoading: true }) let delete2 = null; if(contractId && contractNo) { const attachmentList = this.dataList.filter(item=>item.attachmentId !== iteration.attachmentId) const data = { contractId: this.$route.query.contractId, contractNo: this.$route.query.contractNo, attachmentList, } delete2 = this.$axios.post(`/composition/collaborate/batchUpdateAtt`, data) } const deleteReqArr = delete2 ? [delete1, delete2] : [delete1] await Promise.all(deleteReqArr).then(res=>{ const resFlag = res.every(item=> item.data.status === 0) if( resFlag ){ this.$emit('collaborateDel', iteration) if(contractId && isMainFile && !agreementFlag){ this.$axios.post(`/ai/risk/collaborate/delete/${contractId}`,{ hideLoading: true }).then(res=>{ }) } } }) // this.$message.success(this.$t('message.composition.field.delete1')) }).catch(() => { }); } else { this.$emit('collaborateDel', iteration) } }, handleDownload(iteration, type) { if(iteration.collaborateFileId) { const fileType = type ? `&fileType=${type}`: "" this.$axios .post(`/composition/collaborate/files/download/?fileId=${iteration.collaborateFileId}${fileType}`).then((res)=>{ window.open(res.data.data.url); }) } }, }, watch: { dataList: { deep: true, handler(newVal, oldVal) { this.collaborateFileId = null; if (!newVal || newVal.length === 0) { this.activeIndex = -1; this.isInitialized = false; } else { /** * * 修正 activeIndex:向前移一位,但确保在合法范围内 * newVal,activeIndex 表示当前“激活”的文件在列表中的位置。每当文件列表有变化(比如删除了一个文件), * 让激活的文件向前移动一位,但又不能越界(不能小于0,也不能超过最后一个文件)。 * * */ this.activeIndex = Math.max(0, Math.min(this.activeIndex - 1, newVal.length - 1)); const activeItem = newVal[this.activeIndex]; this.collaborateFileId = activeItem.collaborateFileId; this.isInitialized = activeItem.isFinalized; } if(oldVal.length === 0){ const index = newVal.findIndex(item => item.isMainAttachment === 'Y'); this.activateChange(index); } // 触发事件 this.$emit("handleFileIdCallback", this.collaborateFileId); this.$emit("isFinalizedChange", this.isInitialized); bus.$emit('contractFileUploadChange', newVal); }, }, }, computed: { isCreaterOrOwner() { const { ownerId = '', creatorId = '' } = this.$store.getters.getInitModel.baseInfo || {} const { user = {} } = this.$store.state.currentUserInfo return user.id === ownerId || user.id === creatorId }, collapseText() { return this.isCollapse ? 'el-icon-arrow-left headline-wrapper-show custom-tooltip' : 'el-icon-arrow-right headline-wrapper-show custom-tooltip'; }, cmpOfficeListTips_1() { const tipsContent = this.$store.getters.getTooltipConfig( "cmpOfficeListTips_1" ); if (tipsContent.content) { return tipsContent.content; } else { return "空配置,请全局消息配置cmpOfficeListTips_1"; } }, } }; </script> <style> /* 隐藏横向滚动条 */ .cmp-office-list-box .el-scrollbar__bar.is-horizontal { display: none !important; } .cmp-office-list-box .el-scrollbar__wrap { scrollbar-width: none; /* 去掉Firefox默认滚动条 */ } .cmp-office-list-box .el-scrollbar__bar.is-vertical { opacity: 1; } </style> <style scoped> /* 基础样式 */ .cmp-office-list-box { height: 750px; display: flex; } .cmp-office-list { width: 240px; height: 100%; background: color(display-p3 1 1 1); border-radius: 4px; transition: width 0.3s ease; } .cmp-office-list-is-collapse { width: 0px; overflow: hidden; transition: width 0.3s ease; } .list { height: 100%; } .headline-wrapper-show { cursor: pointer; font-size: 12px; font-weight: 500; opacity: 1; height: 40px; line-height: 40px; background: #e5e5e5; color: #ffffff; border: 1px solid transparent; transition: width 0.3s ease; border-right: 1px solid #82828224; margin-top: 377px; transform: translateX(-10px); /* el-scrollbar 会遮住,导致按钮小角落点不了 */ z-index: 999; } .headline-wrapper-show:hover { border: 1px solid #3a8ee6; } .el-icon-arrow-left { left: 0; border-top-left-radius: 4px; border-bottom-left-radius: 4px; } .el-icon-arrow-right { left: 286px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; } .title { font-size: 16px; font-weight: bold; color: #333; padding: 5px 0; letter-spacing: -1px; } .icon { display: flex; justify-content: center; align-items: center; border-radius: 4px; margin-right: 8px; flex-shrink: 0; } .list-des-wrap { width: 100%; height: 100%; border: 1px solid #b2b1b129; transition: width 0.3s ease; } .list-des { height: 68px; display: flex; align-items: center; border-bottom: 1px solid #b2b1b129; padding: 5px 10px; cursor: pointer; box-sizing: content-box; } .list-des.active { display: flex; border-radius: 4px; background: linear-gradient(90deg, color(display-p3 0.2235 0.5059 0.9412) 0%, color(display-p3 0.298 0.6627 0.9725) 100%); } .list-des.active * { color: #fff; } /* 文档名称 start */ .doc-name-item-box { display: flex; } .cmp-office-icon-right-text { width: 100%; } .custom-tooltip:hover::after { /* css接收dom传参 */ content: attr(data-title); background-color: #333; color: #fff; padding: 5px 10px; border-radius: 5px; white-space: nowrap; position: absolute; transform: translateX(5px); } /* end*/ </style> 如果当前激活项是 const index = newVal.findIndex(item => item.isMainAttachment === 'Y'); 则激活这个条件对应的this.activeIndex, 如果handleDelete方法触发删除, 还是保持Y所在的this.activeIndex 如果用户切换了文件, 比如切换了第三个文件,将第二个文件进行删除, 则需要this.activeIndex -1 操作 根据我描述对handleDelete进行修改
最新发布
07-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值