CSS Grid中display:contents元素设position:relative为何无法定位子元素?
问题分析与解决方案
核心结论
不能在display:contents的元素上使用position:relative——因为display:contents的元素不会生成任何可视渲染盒子,浏览器会直接忽略它的定位属性,绝对定位的子元素会向上查找最近的非static定位祖先(也就是你的Grid容器)作为定位基准,这就是菜单始终相对于Grid定位的原因。
原因拆解
当元素设置display:contents时,它会从渲染树中“隐身”,所有子元素都会直接成为其父容器的子节点。你给这个容器加的position:relative完全不起作用,相当于没加。
可行解决方案
方案1:给行内单元格加定位容器
把上下文菜单放在行内的任意一个单元格里,给这个单元格设置position:relative,让菜单相对于单元格定位。如果需要菜单覆盖整行,调整宽度即可:
<div class="Grid" style="display:grid;grid-template-columns:min-content min-content;grid-column-gap:10px;"> <div>cell1</div> <div>cell2</div> <div>cell1</div> <div>cell2</div> <div>cell1</div> <div>cell2</div> <!-- 目标行 --> <div style="position:relative;" @oncontextmenu="@(()=>isShowingMenu = !isShowingMenu)" @oncontextmenu:preventDefault> right click for context menu @if (isShowingMenu) { <div style="position:absolute; border:1px solid #000; background-color:aquamarine; width: calc(100% + 10px + min-content); left:0; top:100%;"> Context menu </div> } </div> <div>right click for context menu</div> <div>cell1</div> <div>cell2</div> </div> @code { private bool isShowingMenu; }
方案2:通过鼠标事件坐标定位菜单
直接利用右键点击的坐标来定位菜单,不需要依赖行的定位属性,这种方式更灵活:
<div class="Grid" style="display:grid;grid-template-columns:min-content min-content;grid-column-gap:10px; position:relative;"> <div>cell1</div> <div>cell2</div> <div>cell1</div> <div>cell2</div> <div>cell1</div> <div>cell2</div> <div @oncontextmenu="ShowMenu" @oncontextmenu:preventDefault>right click for context menu</div> <div @oncontextmenu="ShowMenu" @oncontextmenu:preventDefault>right click for context menu</div> <div>cell1</div> <div>cell2</div> @if (isShowingMenu) { <div style="position:absolute; border:1px solid #000; background-color:aquamarine; left:@menuXpx; top:@menuYpx;"> Context menu </div> } </div> @code { private bool isShowingMenu; private int menuXpx; private int menuYpx; private void ShowMenu(MouseEventArgs e) { isShowingMenu = !isShowingMenu; menuXpx = (int)e.ClientX; menuYpx = (int)e.ClientY; } }
方案3:给Grid行单独设置定位容器
如果需要菜单严格对应整行,可以给每一行套一个不影响Grid布局的容器,用display:grid; grid-column: 1 / -1;让容器占满整行,再给这个容器加position:relative:
<div class="Grid" style="display:grid;grid-template-columns:min-content min-content;grid-column-gap:10px;"> <div>cell1</div> <div>cell2</div> <div>cell1</div> <div>cell2</div> <div>cell1</div> <div>cell2</div> <!-- 整行容器 --> <div style="display:grid; grid-template-columns:min-content min-content; grid-column-gap:10px; grid-column: 1 / -1; position:relative;" @oncontextmenu="@(()=>isShowingMenu = !isShowingMenu)" @oncontextmenu:preventDefault> <div>right click for context menu</div> <div>right click for context menu</div> @if (isShowingMenu) { <div style="position:absolute; border:1px solid #000; background-color:aquamarine; left:0; top:100%;"> Context menu </div> } </div> <div>cell1</div> <div>cell2</div> </div> @code { private bool isShowingMenu; }
内容的提问来源于stack exchange,提问作者Matias Masso
相关产品推荐
相关产品推荐

