I am creating a calculator, that I want to use on browser and mobile as progressive web app. I created my own input buttons and don't want to see the virtual keyboard on mobile. For that reason I am using the attribute readonly
on the input
.
I want to show the cursor, so the user knows, where the number or operator will be inserted.
Unfortunately a readonly input shows the cursor only in firefox mobile, not in chrome mobile. So I cannot rely on the built in cursor.
I need a way to show the cursor for the input field, while the virtual keyboard is not opened, when clicking into the input field.
To solve the issue, I implemented my own caret. I created a div with 1px width and proper height. The #caret
is positioned relatively to the .input-group
.
To make it easy, I use a monospaced font on the input. So every character has same width. Then I just listen for any event on the input and update the position of the caret accordingly. text-shadow
and transparent color
make the original caret invisible on firefox mobile.
My input field is aligned to the right.
Updated https://jsfiddle.net/9fr46y2w/3/
HTML
<div class="input-group">
<input type="text" id="input" onclick="showCaret(this);">
<div id="caret"></div>
</div>
CSS
#input {
color: transparent;
font-family: monospace;
font-size: 36px;
height: 48px;
margin: 0;
padding: 0;
text-align: right;
text-shadow: 0 0 0 #yourTextColor;
width: 100%;
}
.input-group {
margin: 0;
padding: 0;
position: relative;
}
#caret {
background: white;
color: transparent;
height: 41px;
position: absolute;
top: 4px;
right:0;
width: 1px;
animation-duration: 1s;
animation-name: blink;
animation-iteration-count: infinite;
}
@keyframes blink {
from {
opacity: 1;
}
49.9% {
opacity: 1;
}
50% {
opacity: 0;
}
99.9% {
opacity: 0;
}
to {
opacity: 1;
}
}
JavaScript
function showCaret(input) {
let widthSizeRatio = 21.6/36;
let charWidth = widthSizeRatio * 36;
let length = input.value.length;
let cur = input.selectionStart;
document.getElementById("caret").style.right = Math.floor((length - cur) * charWidth) + "px";
}