如何纯CSS实现动态宽度钢琴键盘的黑键定位与间隙控制
纯CSS实现动态宽度的钢琴键盘黑键覆盖效果
可以通过Flex布局结合绝对定位实现无需JavaScript的解决方案,完美满足你的所有需求:
完整代码实现
CSS部分
:root { --piano-width: 600px; --piano-height: 150px; --piano-keys-gap: 1px; --piano-black-keys-height-perc: 0.6; --white-key-count: 7; /* 一个八度的白键数量,多八度可按比例调整 */ } .piano-container { display: flex; justify-content: center; margin: 20px; } .piano-keys { display: flex; width: var(--piano-width); height: var(--piano-height); gap: var(--piano-keys-gap); /* 用gap直接控制白键间的px级间隙 */ position: relative; /* 作为黑键绝对定位的参考容器 */ } .piano-key { position: relative; box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.2); cursor: pointer; border-radius: 0 0 3px 3px; } .piano-key.key-white { background-color: #eeeeee; flex: 1; /* 自动平分父容器宽度,实现动态适配 */ } .piano-key.key-black { position: absolute; background-color: #333; width: calc((100% / var(--white-key-count)) * 0.9); /* 黑键宽度为白键的90% */ height: calc(var(--piano-height) * var(--piano-black-keys-height-perc)); z-index: 1; /* 确保黑键在白键上方 */ top: 0; } /* 定位每个黑键到正确位置(一个八度的布局) */ .piano-key.key-black:nth-child(2) { left: calc((100% / var(--white-key-count)) * 0.55); } .piano-key.key-black:nth-child(4) { left: calc((100% / var(--white-key-count)) * 1.55); } .piano-key.key-black:nth-child(7) { left: calc((100% / var(--white-key-count)) * 3.55); } .piano-key.key-black:nth-child(9) { left: calc((100% / var(--white-key-count)) * 4.55); } .piano-key.key-black:nth-child(11) { left: calc((100% / var(--white-key-count)) * 5.55); }
HTML部分
<div class="piano-container"> <div class="piano-keys"> <div class="piano-key key-white note-selector" data-note="C">C</div> <div class="piano-key key-black note-selector" data-note="C#">C#</div> <div class="piano-key key-white note-selector" data-note="D">D</div> <div class="piano-key key-black note-selector" data-note="D#">D#</div> <div class="piano-key key-white note-selector" data-note="E">E</div> <div class="piano-key key-white note-selector" data-note="F">F</div> <div class="piano-key key-black note-selector" data-note="F#">F#</div> <div class="piano-key key-white note-selector" data-note="G">G</div> <div class="piano-key key-black note-selector" data-note="G#">G#</div> <div class="piano-key key-white note-selector" data-note="A">A</div> <div class="piano-key key-black note-selector" data-note="A#">A#</div> <div class="piano-key key-white note-selector" data-note="B">B</div> </div> </div>
方案说明
动态宽度适配:
- 白键使用
flex:1,自动平分piano-keys容器的宽度,无论容器宽度如何变化,都能填满且均匀分配。 - 通过
--white-key-count变量统一控制白键数量,多八度场景只需调整该变量和黑键的nth-child选择器即可。
- 白键使用
黑键宽度控制:
- 黑键宽度通过
calc((100% / var(--white-key-count)) * 0.9)计算,确保始终为白键宽度的90%,无需硬编码数值。
- 黑键宽度通过
px级间隙控制:
- 直接利用Flex布局的
gap属性设置--piano-keys-gap变量,精确控制白键间的间隙大小,单位支持px。
- 直接利用Flex布局的
黑键覆盖定位:
- 黑键采用
position:absolute脱离文档流,通过calc计算left值,精准定位到两个白键的重叠区域,结合z-index:1确保覆盖在白键上方。
- 黑键采用
内容的提问来源于stack exchange,提问作者RrR2010
相关产品推荐
相关产品推荐

