J'ai actuellement un certain nombre d'entrées comme ceci:
<input type="number" id="milliseconds">
Ce champ d’entrée sert à représenter une valeur en millisecondes . Cependant, j’ai plusieurs entrées numériques qui prennent une valeur en dB ou en pourcentage.
<input type="number" id="decibel">
<input type="number" id="percentages">
Ce que je voudrais faire est d’ajouter un suffixe de type dans le champ de saisie pour permettre aux utilisateurs de savoir quel type de valeur l’entrée représente. Quelque chose comme ça:
(Cette image est modifiée pour indiquer le résultat souhaité, j'ai également masqué les flèches haut et bas du type d'entrée).
J'ai essayé de faire une recherche sur Google mais je n'arrive pas à trouver quoi que ce soit à ce sujet. Est-ce que quelqu'un sait si c'est possible et comment vous pouvez accomplir quelque chose comme ça?
Vous pouvez utiliser un wrapper <div>
pour chaque élément d'entrée et positionner l'unité en tant que pseudo-élément ::after
avec la content
de vos unités correspondantes.
Cette approche fonctionne bien car les pseudo-éléments positionnés de manière absolue n’affecteront pas les présentations existantes. Néanmoins, l’inconvénient de cette approche est que vous devez vous assurer que la saisie de l’utilisateur n’est pas aussi longue que le champ de texte, sinon l’appareil sera désagréablement affiché ci-dessus. Pour une longueur d'entrée utilisateur fixe, cela devrait fonctionner correctement.
/* prepare wrapper element */
div {
display: inline-block;
position: relative;
}
/* position the unit to the right of the wrapper */
div::after {
position: absolute;
top: 2px;
right: .5em;
transition: all .05s ease-in-out;
}
/* move unit more to the left on hover
for arrow buttons will appear to the right of number inputs */
div:hover::after {
right: 1.5em;
}
/* set the unit abbreviation for each unit class */
.ms::after {
content: 'ms';
}
.db::after {
content: 'db';
}
.percent::after {
content: '%';
}
<div class="ms">
<input type="number" id="milliseconds" />
</div>
<hr />
<div class="db">
<input type="number" id="decibel" />
</div>
<hr />
<div class="percent">
<input type="number" id="percentages">
</div>
Une autre approche intéressante consisterait à utiliser un peu de JavaScript pour que le suffixe colle réellement au texte saisi (ce qui est probablement mieux):
const inputElement = document.getElementById('my-input');
const suffixElement = document.getElementById('my-suffix');
inputElement.addEventListener('input', updateSuffix);
updateSuffix();
function updateSuffix() {
const width = getTextWidth(inputElement.value, '12px arial');
suffixElement.style.left = width + 'px';
}
/**
* Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
*
* @param {String} text The text to be rendered.
* @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
*
* @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393
*/
function getTextWidth(text, font) {
// re-use canvas object for better performance
var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
var context = canvas.getContext("2d");
context.font = font;
var metrics = context.measureText(text);
return metrics.width;
}
#my-input-container {
display: inline-block;
position: relative;
font: 12px arial;
}
#my-input {
font: inherit;
}
#my-suffix {
position: absolute;
left: 0;
top: 3px;
color: #555;
padding-left: 5px;
font: inherit;
}
<div id="my-input-container">
<input type="number" id="my-input" value="1500">
<span id="my-suffix">ms.</span>
</div>
Cependant, ceci est juste une preuve de concept. Vous devrez travailler un peu plus loin pour le rendre prêt pour la production, par exemple. faites-en un plugin réutilisable.
En outre, vous devrez gérer un cas où l'élément d'entrée est débordé.
Si vous avez l'option d'ajouter des éléments à saisir, vous pouvez essayer ceci: -
<div class="container">
<input type="text" id="milliseconds">
<span class="ms">ms</span>
</div>
.container {
max-width: 208px; /*adjust it*/
margin: auto;
position: relative;
display: inline-block;
}
#milliseconds {
padding-right: 35px;
}
.ms {
position: absolute;
top: 0;
right: 10px;
}