Ajuster la largeur du champ de saisie à son entrée

<html> <head> </head> <body> <input type="text" value="1" style="min-width:1px;" /> </body> </html> 

C'est mon code et ça ne fonctionne pas. Existe-t-il une autre façon de HTML, JavaScript, PHP ou CSS pour définir une largeur minimale?

Clarification de Marcel: L'OP veut un champ de saisie de texte avec une largeur de changement dynamique, de sorte que le champ de saisie des fluides autour de son contenu.

Il semble que votre attente soit que le style soit appliqué de manière dynamique à la largeur de la zone de texte en fonction du contenu de la zone de texte. Si oui, vous aurez besoin de quelques js pour courir sur le changement de contenu de la zone de texte, quelque chose comme ceci :

 <input id="txt" type="text" onkeypress="this.style.width = ((this.value.length + 1) * 8) + 'px';"> 

Remarque: cette solution ne fonctionne que lorsque tous les caractères sont exactement 8px largeur.

Pour calculer la largeur de l'entrée actuelle, vous devrez l'intégrer dans un élément d' span temporaire, joindre cette chose au DOM, obtenir la largeur calculée (en pixels) à l'aide de la propriété scrollWidth et retirer la span nouveau. Bien sûr, vous devrez vous assurer que la même famille de polices, la taille de la police, etc., est utilisé dans l' input ainsi que dans l'élément de span . Par conséquent, je leur ai assigné la même classe.

J'ai attaché la fonction à l'événement de la keyup , car à la keypress la keypress le caractère d'entrée n'est pas encore ajouté à la value entrée, ce qui entraînera une mauvaise largeur. Malheureusement, je ne sais pas comment se débarrasser du défilement du champ de saisie (lors de l'ajout de caractères à la fin du champ); Il se déplace, car le caractère est ajouté et affiché avant que l' adjustWidthOfInput() soit appelée. Et, comme je l'ai dit, je ne peux pas le faire à l'inverse car alors vous aurez la valeur du champ de saisie avant que le caractère pressé ne soit inséré. Je vais essayer de résoudre ce problème plus tard.

BTW, j'ai seulement testé ceci dans Firefox (3.6.8), mais vous obtiendrez le but, j'espère.

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Get/set width of &lt;input&gt;</title> <style> body { background: #666; } .input-element { border: 0; padding: 2px; background: #fff; font: 12pt sans-serif; } .tmp-element { visibility: hidden; white-space: pre; } </style> </head> <body> <input id="theInput" type="text" class="input-element" value="1"> <script> var inputEl = document.getElementById("theInput"); function getWidthOfInput() { var tmp = document.createElement("span"); tmp.className = "input-element tmp-element"; tmp.innerHTML = inputEl.value.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); document.body.appendChild(tmp); var theWidth = tmp.getBoundingClientRect().width; document.body.removeChild(tmp); return theWidth; } function adjustWidthOfInput() { inputEl.style.width = getWidthOfInput() + "px"; } adjustWidthOfInput(); inputEl.onkeyup = adjustWidthOfInput; </script> </body> </html> 

Voici une modification de la réponse de Lyth qui prend en compte:

  • Effacement
  • Initialisation
  • Les espaces réservés

Cela permet également un nombre quelconque de champs de saisie! Pour le voir en action: http://jsfiddle.net/4Qsa8/

Scénario:

 $(document).ready(function () { var $inputs = $('.resizing-input'); // Resize based on text if text.length > 0 // Otherwise resize based on the placeholder function resizeForText(text) { var $this = $(this); if (!text.trim()) { text = $this.attr('placeholder').trim(); } var $span = $this.parent().find('span'); $span.text(text); var $inputSize = $span.width(); $this.css("width", $inputSize); } $inputs.find('input').keypress(function (e) { if (e.which && e.charCode) { var c = String.fromCharCode(e.keyCode | e.charCode); var $this = $(this); resizeForText.call($this, $this.val() + c); } }); // Backspace event only fires for keyup $inputs.find('input').keyup(function (e) { if (e.keyCode === 8 || e.keyCode === 46) { resizeForText.call($(this), $(this).val()); } }); $inputs.find('input').each(function () { var $this = $(this); resizeForText.call($this, $this.val()) }); }); 

Style:

 .resizing-input input, .resizing-input span { font-size: 12px; font-family: Sans-serif; white-space: pre; padding: 5px; } 

HTML:

 <div class="resizing-input"> <input type="text" placeholder="placeholder"/> <span style="display:none"></span> </div> 
 $(document).ready(function() { var $inputs = $('.resizing-input'); // Resize based on text if text.length > 0 // Otherwise resize based on the placeholder function resizeForText(text) { var $this = $(this); if (!text.trim()) { text = $this.attr('placeholder').trim(); } var $span = $this.parent().find('span'); $span.text(text); var $inputSize = $span.width(); $this.css("width", $inputSize); } $inputs.find('input').keypress(function(e) { if (e.which && e.charCode) { var c = String.fromCharCode(e.keyCode | e.charCode); var $this = $(this); resizeForText.call($this, $this.val() + c); } }); // Backspace event only fires for keyup $inputs.find('input').keyup(function(e) { if (e.keyCode === 8 || e.keyCode === 46) { resizeForText.call($(this), $(this).val()); } }); $inputs.find('input').each(function() { var $this = $(this); resizeForText.call($this, $this.val()) }); }); 
 .resizing-input input, .resizing-input span { font-size: 12px; font-family: Sans-serif; white-space: pre; padding: 5px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> <div class="resizing-input"> First: <input type="text" placeholder="placeholder" /> <span style="display:none"></span> </div> <br> 

POUR UN NICER LOOK & FEEL

Vous devez utiliser l'événement jQuery keypress () en combinaison avec String.fromCharCode (e.quelle) pour obtenir le caractère pressé. Par conséquent, vous pouvez calculer quelle sera votre largeur. Pourquoi? Parce qu'il sera beaucoup plus sexy 🙂

Voici un jsfiddle qui se traduit par un bon comportement par rapport aux solutions utilisant l'événement keyup: http://jsfiddle.net/G4FKW/3/

Html de base.

 <input type="text" /> <span style="display:none"></span> 

Le jQuery.

 $('input[type="text"]').keypress(function(e) { if (e.which !== 0 && e.charCode !== 0) { // only characters var c = String.fromCharCode(e.keyCode|e.charCode); $span = $(this).siblings('span').first(); $span.text($(this).val() + c) ; // the hidden span takes // the value of the input $inputSize = $span.width() ; $(this).css("width", $inputSize) ; // apply width of the span to the input } }) ; 

Le css.

 input, span { padding:0; font-size:9px; font-family:Sans-serif; white-space:pre; // white-spaces will work effectively } /* it's important the input and its span have same styling */ 

Vous pourriez faire quelque chose comme ça

 // HTML <input id="input" type="text" style="width:3px" /> // jQuery $(function(){ $('#input').keyup(function(){ $('<span id="width">').append( $(this).val() ).appendTo('body'); $(this).width( $('#width').width() + 2 ); $('#width').remove(); }); }); 

Vous pouvez également définir la largeur d'une entrée en utilisant l'attribut size . La taille d'une entrée détermine sa largeur en caractères.

Une entrée pourrait ajuster dynamiquement sa taille en écoutant les événements clés.

Par exemple

 $("input[type='text']").bind('keyup', function () { $(this).attr("size", $(this).val().length ); }); 

JsFiddle ici

Voici un JS simple et un plugin jQuery que j'ai écrit qui traitera le redimensionnement d'un élément de saisie à l'aide d'un canevas et de la taille / famille de la police pour déterminer la longueur de chaîne réelle lors de son rendu. (Fonctionne uniquement dans> IE9, chrome, safari, firefox, opéra et la plupart des autres navigateurs majeurs qui ont implémenté l'élément toile).

PlainJS:

 function autoSize(input, o) { o || (o = {}); o.on || (o.on = 'keyup'); var canvas = document.createElement('canvas'); canvas.setAttribute('style', 'position: absolute; left: -9999px'); document.body.appendChild(canvas); var ctx = canvas.getContext('2d'); input.addEventListener(o.on, function () { ctx.font = getComputedStyle(this,null).getPropertyValue('font'); this.style.width = ctx.measureText(this.value + ' ').width + 'px'; }); } //Usage autoSize(document.getElementById('my-input')); 

JQuery Plugin:

 $.fn.autoSize = function(o) { o = $.extend({}, { on: 'keyup' }, o); var $canvas = $('<canvas/>').css({position: 'absolute', left: -9999}); $('body').append($canvas); var ctx = $canvas[0].getContext('2d'); return this.on(o.on, function(){ var $this = $(this); ctx.font = $this.css('font'); $this.width(ctx.measureText($this.val()).width + 'px'); }) } //Usage: $('#my-input').autoSize(); 

Remarque: cela ne gérera pas les modifications de texte, l'espacement des lignes et l'espacement des lettres, et probablement d'autres propriétés de modification de la taille du texte. Pour gérer la propriété text-transform set et ajuster la valeur du texte pour correspondre à cette propriété. Les autres sont probablement assez simples. Je vais mettre en œuvre si cela commence à prendre une certaine traction …

Vous pouvez le faire encore plus simple en angularjs en utilisant la directive intégrée ng-style .

Dans votre html:

  <input ng-style="inputStyle(testdata)" ng-model="testdata" /> 

Dans votre contrôleur:

  $scope.testdata = "whatever"; $scope.inputStyle = function(str) { var charWidth = 7; return {"width": (str.length +1) * charWidth + "px" }; }; 

Dans votre css:

 input { font-family:monospace; font-size:12px; } 

Réglez le charWidth pour qu'il corresponde à la largeur de votre police. Il semble être 7 à une taille de police de 12px;

Voici une solution sans la police monospaced nécessaire, avec seulement très petit code pièce de javascript , n'ont pas besoin de calculer les styles calculés , et même supporter l'ime .

 // copy the text from input to the span $(function () { $('.input').on('input', function () { $('.text').text($('.input').val()); }); }); 
  * { box-sizing: border-box; } .container { display: inline-block; position: relative; } .input, .text { margin: 0; padding: 2px 10px; font-size: 24px; line-height: 32px; border: 1px solid #ccc; box-radius: 3px; height: 36px; font: 20px/20px sans-serif; /* font: they should use same font; */ } .text { padding-right: 20px; display: inline-block; visibility: hidden; white-space: pre; } .input { position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 100%; } 
 <script src="https://code.jquery.com/jquery-3.2.0.min.js"></script> <div class="container"> <span class="text"> some text </span> <input class="input" value="some text" /> </div> 

Dans les versions modernes du navigateur, l'unité CSS "ch" est également disponible. À mon avis, il s'agit d'une unité indépendante de la police, où "1ch" équivaut à la largeur du caractère 0 (zéro) dans n'importe quelle police donnée.

Ainsi, quelque chose d'aussi simple que le suivant pourrait être utilisé comme fonction de redimensionnement:

     Fonction redimensionnerInput (elem)
     {
        Elem.style.width = elem.value.length + 2 + "ch";
     }

Cet exemple redimensionnerait "elem" à la longueur de la valeur + 2 caractères supplémentaires.

Je pense que vous interprétez mal la propriété CSS de la min-largeur . La largeur minimale est généralement utilisée pour définir une largeur DOM minimale dans une disposition fluide, comme:

 input { width: 30%; min-width: 200px; } 

Cela définirait l'élément d'entrée sur une largeur minimale de 200 pixels. Dans ce contexte, "px" signifie "pixels".

Maintenant, si vous essayez de vérifier pour s'assurer que le champ de saisie contient au moins un caractère lorsqu'un utilisateur le soumet, vous devrez effectuer une validation de formulaire avec JavaScript et PHP. Si c'est vraiment ce que vous essayez de faire, je modifierai cette réponse et je ferai de mon mieux pour vous aider.

J'ai vraiment aimé la réponse de Lyth , mais je l'ai vraiment voulu:

  1. Gérer le recul et supprimer
  2. Vous ne devez pas ajouter manuellement une étiquette adjacente.
  3. Appliquer une largeur min.
  4. Appliquer automatiquement aux éléments avec une classe spécifique

J'ai adapté son JSFiddle et je l'ai trouvé. Une amélioration qui n'est pas présente dans ce violon serait d'utiliser quelque chose comme le jQuery CSS Parser pour lire réellement la largeur initiale de la règle input.textbox-autosize, et l'utiliser comme minWidth. Bien, j'utilise simplement un attribut sur le, ce qui rend une démo compacte mais n'est pas idéal. Car il nécessite un attribut supplémentaire sur chaque entrée. Vous pouvez également vouloir mettre le minWidth comme 100 dans le JavaScript.

HTML:

 <div id='applicationHost'> <div>Name: <input class='textbox-autosize' data-min-width='100' type="text" /></div> <div>Email: <input class='textbox-autosize' data-min-width='100' type="email" /></div> <div>Points: <input class='textbox-autosize' data-min-width='100' type="number" /></div> </div> 

CSS:

 #applicationHost { font-family: courier; white-space: pre; } input.textbox-autosize, span.invisible-autosize-helper { padding:0; font-size:12px; font-family:Sans-serif; white-space:pre; } input.textbox-autosize { width: 100px; /* Initial width of textboxes */ } /* In order for the measurements to work out, your input and the invisible span need to have the same styling. */ 

JavaScript:

 $('#applicationHost').on('keyup', '.textbox-autosize', function(e) { // Add an arbitary buffer of 15 pixels. var whitespaceBuffer = 15; var je = $(this); var minWidth = parseInt(je.attr('data-min-width')); var newVal = je.val(); var sizingSpanClass = 'invisible-autosize-helper'; var $span = je.siblings('span.' + sizingSpanClass).first(); // If this element hasn't been created yet, we'll create it now. if ($span.length === 0) { $span = $('<span/>', { 'class': sizingSpanClass, 'style': 'display: none;' }); je.parent().append($span); } $span = je.siblings('span').first(); $span.text(newVal) ; // the hidden span takes // the value of the input $inputSize = $span.width(); $inputSize += whitespaceBuffer; if($inputSize > minWidth) je.css("width", $inputSize) ; // apply width of the span to the input else je.css("width", minWidth) ; // Ensure we're at the min width }); 

Désolé de vous joindre si tard à cette fête.

Je veux simplement noter une solution plus simple pour le calcul de la largeur – en supposant que vous ne vous occupez pas du style du champ de saisie avec la famille de polices monospace.

La solution de Tahbaza fonctionnera avec la famille de polices monospace.

Même si la solution "invisible span" est définitivement la solution la plus précise, même avec monospace, je considère qu'il s'agit d'une overkill.

Voici une belle directive angularjs qui l'implémente.

Notez que vous devez toujours ajouter "1" caractère à la valeur réelle – sinon vous obtiendrez des tiques ennuyeuses.

C'est le code:

 app.directive("editInline", function(){ return function(scope, element, attr){ var inputW = (element.val().length+1) * 8; element.css('width', inputW + 'px'); element.bind("keyup keydown", function(){ var inputW = (element.val().length+1) * 8; element.css('width', inputW + 'px'); }); } }); <input type="text" style="font-family:monospace" value="hello world" edit-inline> 

Voici une autre façon de résoudre ceci en utilisant un DIV et la propriété «contenteditable»:

HTML:

 <div contenteditable = "true" class = "fluidInput" data-placeholder = ""></div> 

CSS: (pour donner au DIV quelques dimensions et le rendre plus facile à voir)

 .fluidInput { display : inline-block; vertical-align : top; min-width : 1em; height : 1.5em; font-family : Arial, Helvetica, sans-serif; font-size : 0.8em; line-height : 1.5em; padding : 0px 2px 0px 2px; border : 1px solid #aaa; cursor : text; } .fluidInput * { display : inline; } .fluidInput br { display : none; } .fluidInput:empty:before { content : attr(data-placeholder); color : #ccc; } 

Remarque: Si vous prévoyez de l'utiliser dans un élément FORM que vous prévoyez de soumettre, vous devrez utiliser Javascript / jQuery pour attraper l'événement de soumission afin que vous puissiez analyser la «valeur» ( .innerHTML ou .html() Respectivement) de la DIV.

Mieux vaut la onvalue :

 <input id="txt" type="text" onvalue="this.style.width = ((this.value.length + 1) * 8) + 'px';"> 

Cela implique également le collage, la traînée et le décollage, etc.

Je passe juste un peu de temps à comprendre comment le faire.
En fait, la manière la plus simple que j'ai trouvée est de déplacer la valeur d'entrée à la portée juste avant l'entrée, en gardant l'entrée 1 largeur du symbole. Bien que je ne puisse pas être sûr que cela correspond à votre besoin initial.
Peut-être que c'est un code supplémentaire, mais dans l'application réagit + flux, c'est une solution tout à fait naturelle.

Basé sur la réponse de Michael, j'ai créé ma propre version de ceci en utilisant jQuery. Je pense que c'est une version plus propre / plus courte de la plupart des réponses ici et il semble faire le travail.

Je fais la même chose que la plupart des gens ici en utilisant une portée pour écrire le texte d'entrée dans puis obtenir la largeur. Ensuite, je keyup la largeur lorsque les actions de keyup et de blur sont appelés.

Voici un code code actif . Ce codepen montre comment cela peut être utilisé avec plusieurs champs de saisie.

Structure HTML:

 <input type="text" class="plain-field" placeholder="Full Name"> <span style="display: none;"></span> 

JQuery:

 function resizeInputs($text) { var text = $text.val().replace(/\s+/g, ' '), placeholder = $text.attr('placeholder'), span = $text.next('span'); span.text(placeholder); var width = span.width(); if(text !== '') { span.text(text); var width = span.width(); } $text.css('width', width + 5); }; 

La fonction ci-dessus obtient la valeur des entrées, réduit les espaces supplémentaires et définit le texte dans la portée pour obtenir la largeur. S'il n'y a pas de texte, il obtient plutôt l'espace réservé et entre dans la portée à la place. Une fois qu'il entre le texte dans la portée, il définit la largeur de l'entrée. Le + 5 sur la largeur est parce que sans cela, l'entrée est coupée un peu dans le Navigateur Edge.

 $('.plain-field').each(function() { var $text = $(this); resizeInputs($text); }); $('.plain-field').on('keyup blur', function() { var $text = $(this); resizeInputs($text); }); $('.plain-field').on('blur', function() { var $text = $(this).val().replace(/\s+/g, ' '); $(this).val($text); }); 

Si cela pourrait être amélioré, faites-le moi savoir car c'est la solution la plus propre que je pourrais proposer.