持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情
前言
前段时间在掘金薅了一个键盘,研究了好久,决定用css画一个一(毫)模(不)一(相)样(干)的键盘出来看看。
😛 实物图看起来还不错哦,就是画起来有点不太容易了。
拆分元素
😳 由于这个键盘是61键的,所以就比较简单一点
😳 整体分为五层去实现
<div class="keyboard">
<div class="row">
<div class="kbd" tabindex="1" data-key="Esc"></div>
<div class="kbd" data-key="1" data-alt="!"></div>
<div class="kbd" data-key="2" data-alt="@"></div>
<div class="kbd" data-key="3" data-alt="#"></div>
<div class="kbd" data-key="4" data-alt="$"></div>
<div class="kbd" data-key="5" data-alt="%"></div>
<div class="kbd" data-key="6" data-alt="^"></div>
<div class="kbd" data-key="7" data-alt="&"></div>
<div class="kbd" data-key="8" data-alt="*"></div>
<div class="kbd" data-key="9" data-alt="("></div>
<div class="kbd" data-key="0" data-alt=")"></div>
<div class="kbd" data-key="-" data-alt="_"></div>
<div class="kbd" data-key="=" data-alt="+"></div>
<div class="kbd" data-key="backspace"></div>
</div>
</div>
data-key表示当前按键的主元素data-alt表示当前按键的附元素(需要通过shift +获取的)
.keyboard {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 0;
border-radius: 4px;
border: 13px solid #777;
border-top-color: #666;
border-bottom-color: #888;
outline: 3px solid rgba(0, 0, 0, 0.2);
outline-offset: -1px;
box-shadow: inset 0 1rem 1rem rgba(0, 0, 0, 0.5), 0 2rem 3rem -0.5rem rgba(0, 0, 0, 0.55);
background-image: radial-gradient(#111, #222);
padding: 0.25rem;
}
.row {
height: 40px;
display: flex;
justify-content: space-between;
width: 617.2px;
padding-top: 1px;
margin-bottom: 2px;
}
.kbd {
border-radius: 3px;
box-sizing: border-box;
color: rgba(0, 0, 0, 0.75);
display: inline-block;
font-family: system-ui, sans-serif;
font-size: 1rem;
font-weight: 400;
line-height: 1.125;
padding: 0.33em;
position: relative;
text-align: center;
vertical-align: middle;
width: 40px;
height: 40px;
border: 3px solid transparent;
border-top: 2px solid transparent;
border-bottom: 6px solid transparent;
background-color: #e9e8e6;
border-color: #c3c0bb;
border-top-color: #eeedeb;
border-bottom-color: #a6a29a;
box-shadow: 0 -0.125em 0 -0.063em #a6a29a, 0 0.125em 0 -0.063em rgba(0, 0, 0, 0.5);
transition: -webkit-transform 100ms;
transition: transform 100ms;
transition: transform 100ms, -webkit-transform 100ms;
outline: 0;
}
- 按键通过
border-color的样式做了一些边框阴影的处理效果 - 由于部分特殊按键颜色不一致,所以可以单独进行处理
.kbd[data-key=tab], .kbd[data-key=enter], .kbd[data-key=caps], .kbd[data-key=backspace], .kbd[data-key=lshift], .kbd[data-key=rshift], .kbd[data-key=lctrl], .kbd[data-key=rctrl], .kbd[data-key=lalt], .kbd[data-key=ralt], .kbd[data-key=lwin], .kbd[data-key=rwin], .kbd[data-key=rfn] {
background-color: #CD853F;
border-color: #A0522D;
border-top-color: #CD853F;
border-bottom-color: #A0522D;
box-shadow: 0 -0.125em 0 -0.063em #A0522D, 0 0.125em 0 -0.063em rgba(0, 0, 0, 0.5);
}
.kbd[data-key=tab]:after, .kbd[data-key=enter]:after, .kbd[data-key=caps]:after, .kbd[data-key=backspace]:after, .kbd[data-key=lshift]:after, .kbd[data-key=rshift]:after, .kbd[data-key=lctrl]:after, .kbd[data-key=rctrl]:after, .kbd[data-key=lalt]:after, .kbd[data-key=ralt]:after, .kbd[data-key=lwin]:after, .kbd[data-key=rwin]:after, .kbd[data-key=rfn]:after {
font-size: 0.725em;
top: 0;
left: 0;
right: 0;
line-height: 31.2px;
position: absolute;
}
.kbd[data-key=tab]::before, .kbd[data-key=enter]::before, .kbd[data-key=caps]::before, .kbd[data-key=backspace]::before, .kbd[data-key=lshift]::before, .kbd[data-key=rshift]::before, .kbd[data-key=lctrl]::before, .kbd[data-key=rctrl]::before, .kbd[data-key=lalt]::before, .kbd[data-key=ralt]::before, .kbd[data-key=lwin]::before, .kbd[data-key=rwin]::before, .kbd[data-key=rfn]::before {
border-left-color: #D2691E;
border-right-color: #D2691E;
border-bottom-color: #A0522D;
box-shadow: 0 4px 4px -3px rgba(0, 0, 0, 0.15);
background-image: linear-gradient(to right, #A0522D, #A0522D 5%, transparent 40%, transparent 60%, #A0522D 95%, #A0522D);
}
- 将所有特殊按键的背景颜色和边框颜色都做一下特殊处理
填充键盘文字
😕 键盘文字是通过标签属性添加的,并没有直接写在标签之间,所以我们需要通过伪类样式直接处理
.kbd[data-key]::after {
position: relative;
z-index: 1;
content: attr(data-key);
text-transform: capitalize;
}
.kbd[data-alt]::after {
white-space: pre;
content: attr(data-alt) "\a" attr(data-key);
line-height: 0.95rem;
font-size: 0.7em;
position: absolute;
top: 0;
left: 0;
right: 0;
text-align: center;
}
content使用attr方法来从页面元素中动态的获取内容(获取的是data-中定义的内容)
特殊按键
🧐 中间的字母按键都一样的处理方式,下面就描述一下空格周边的特殊按键处理方法
<div class="row">
<div class="kbd" data-key="lctrl"></div>
<div class="kbd" data-key="lwin"></div>
<div class="kbd" data-key="lalt"></div>
<div class="kbd" data-key="space"></div>
<div class="kbd" data-key="ralt"></div>
<div class="kbd" data-key="rwin"></div>
<div class="kbd" data-key="rfn"></div>
<div class="kbd" data-key="rctrl"></div>
</div>
- 将空格作为中间键,左右的按键分为 l 和 r (left、right)
shift按键同理(可以在文章结尾码上掘金中查看源码)
.kbd[data-key=lshift]::after, .kbd[data-key=rshift]::after {
content: 'Shift';
}
.kbd[data-key=lctrl]::after, .kbd[data-key=rctrl]::after {
content: 'Ctrl';
}
.kbd[data-key=lwin]::after, .kbd[data-key=rwin]::after {
content: 'Win';
}
.kbd[data-key=lalt]::after, .kbd[data-key=ralt]::after {
content: 'Alt';
}
.kbd[data-key=space]::after {
content: none;
}
.kbd[data-key=rfn]::after {
content: 'fn';
}
.kbd[data-key=lalt]::after, .kbd[data-key=ralt]::after {
content: 'Alt';
}
- 针对特殊按键使用伪类添加按键值
.kbd[data-key=tab], .kbd[data-key="\\"] {
width: 60px;
}
.kbd[data-key=caps] {
width: 70px;
}
.kbd[data-key=backspace] {
width: 80px;
}
.kbd[data-key=enter] {
width: 90px;
}
.kbd[data-key=lshift] {
width: 90px;
}
.kbd[data-key=rshift] {
width: 110px;
}
.kbd[data-key=lctrl], .kbd[data-key=rctrl], .kbd[data-key=lalt], .kbd[data-key=ralt], .kbd[data-key=lwin], .kbd[data-key=rwin], .kbd[data-key=rfn] {
width: 50px;
}
.kbd[data-key=space] {
width: 250px;
}
- 针对特殊按键设置不同的宽度值
键盘按下
😏 当某个按键按下时,就给当前按键一个按下的 class 值
window.addEventListener('keydown', function (e) {
console.log(e);
var el = codeToElement[e.code] || $key(e.key.toLowerCase());
if (el) {
el.classList.add('pressed');
e.preventDefault();
}
});
window.addEventListener('keyup', function (e) {
var el = codeToElement[e.code] || $key(e.key.toLowerCase());
if (el) {
el.classList.remove('pressed');
e.preventDefault();
}
});
- 通过
window.addEventListener方法监听键盘事件
.kbd:active, .kbd.pressed {
-webkit-transform: scale(0.96, 0.96) translate(0, 3px);
transform: scale(0.96, 0.96) translate(0, 3px);
}
- 键盘按下事件通过
transform给一个下沉 和 弹起的效果