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

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

Ceci est mon code et cela ne fonctionne pas. Existe-t-il un autre moyen en HTML, JavaScript, PHP ou CSS de définir une largeur minimale?

Je veux un champ de saisie de texte avec une largeur qui change dynamiquement, de sorte que le champ de saisie fluide autour de son contenu. Chaque entrée a un remplissage intégré de 2em, c'est le problème et le deuxième problème est que cela min-widthne fonctionne pas du tout sur l'entrée.

Si je règle la largeur plus que nécessaire que tout le programme est désordonné, j'ai besoin de la largeur de 1px, plus seulement si c'est nécessaire.

Kerc
la source
Est-ce que cela répond à votre question? Création d'une zone de texte avec redimensionnement automatique
DreamTeK

Réponses:

96

Il semble que vous vous attendiez à ce que le style soit appliqué dynamiquement à la largeur de la zone de texte en fonction du contenu de la zone de texte. Si c'est le cas, vous aurez besoin de quelques js pour fonctionner sur le contenu de la zone de texte changeant, 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 chaque caractère est exactement 8pxlarge.

Tahbaza
la source
41
@Kerc & Tahbaza: oui, mais cela ne fonctionnera que si la largeur de chaque caractère est exactement de 8 pixels.
Marcel Korpel
6
Je suis d'accord, Marcel (et le code affiché n'est pas quelque chose dont je vois vraiment une utilité) mais il présente le comportement souhaité. Savez-vous comment calculer la largeur réelle du texte rendu en tenant compte de la police, de la taille, du poids, du crénage, etc.? Si tel est le cas, partagez-le car je trouverais ce morceau de code utile à l'occasion.
Tahbaza
1
- Je pensais déjà que ce n'était qu'un exemple. Cependant, il n'est pas si difficile de calculer la largeur de l'entrée. Jetez un œil à ma réponse.
Marcel Korpel
Les unités em sont la largeur du caractère "m". Cela serait utile pour calculer la largeur d'une chaîne. J'ai vu des problèmes entre navigateurs avec les unités em appliquées à certains attributs, alors testez-le.
Archonic
7
vous avez oublié l' événement PASTE mon ami;) vous devriez le changer enonInput
vsync
114

Dans les versions de navigateur modernes, l'unité CSS chest également disponible. À ma compréhension, il s'agit d'une unité indépendante de la police, où 1chest égale à la largeur du caractère 0(zéro) dans une police donnée.

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

var input = document.querySelector('input'); // get the input element
input.addEventListener('input', resizeInput); // bind the "resizeInput" callback on "input" event
resizeInput.call(input); // immediately call the function

function resizeInput() {
  this.style.width = this.value.length + "ch";
}
input{ font-size:1.3em; padding:.5em; }
<input>

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

Jani Jalkala
la source
13
Je suis surpris que ce commentaire ne soit pas voté plus haut, car c'est une excellente solution et environ 95% ( 1 ) des navigateurs le supportent.
Husky
8
Ce n'est pas du tout une bonne réponse, car la mesure n'est pas précise et ne prend pas en compte les styles qui pourraient apparaître sur l' inputélément, tels que font-style, letter-spacingetc. J'ai édité la réponse avec une démo en direct.
vsync
5
Fonctionne très bien si vous utilisez une police à espacement fixe. Avec d'autres polices, votre kilométrage peut varier car il utilise apparemment la largeur du caractère 0.
Jilles van Gurp
2
C'est vraiment génial. Notez cependant que cela bogue parfois / ne fonctionne pas comme je m'y attendais lorsqu'un .est rencontré.
Rishav
1
Cela fonctionne parfaitement si vous définissez le dimensionnement de la boîte sur l'entrée sur 'content-box'. De cette façon, il ignore le remplissage lorsque vous définissez la taille.
Hypersapien
65

Pour calculer la largeur de l'entrée actuelle, vous devrez l'intégrer dans un spanélément temporaire , attacher cette chose au DOM, obtenir la largeur calculée (en pixels) à l'aide de la scrollWidthpropriété et supprimer à spannouveau. Bien sûr, vous devrez vous assurer que la même famille de police, la même taille de police, etc., est utilisée dans inputainsi que dans l' spanélément. C'est pourquoi je leur ai assigné la même classe.

J'ai attaché la fonction à l' keyupévénement, car le keypresscaractère d'entrée n'est pas encore ajouté à l'entrée value, ce qui entraînera une largeur incorrecte. Malheureusement, je ne sais pas comment me débarrasser du défilement du champ de saisie (lors de l'ajout de caractères à la fin du champ); il défile, car le caractère est ajouté et affiché avant d' adjustWidthOfInput()être appelé. Et, comme dit, je ne peux pas faire cela dans l'autre sens car vous aurez alors la valeur du champ de saisie avant que le caractère pressé soit inséré. J'essaierai de résoudre ce problème plus tard.

BTW, je n'ai testé cela que dans Firefox (3.6.8), mais vous comprendrez, 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>
Marcel Korpel
la source
J'ai aimé votre réponse et je l'ai même implémentée en utilisant jQuery / Underscore: gist.github.com/3745941 . Cependant, je pourrais faire certaines hypothèses: (1) la largeur de tout caractère n'est pas supérieure à 14 px, (2) il est acceptable que l'élément d'entrée s'étende de 14 px au-delà de la valeur de l'élément. Je l'ai attaché à un événement keydown et ça marche très bien!
Nathan
11
Vous devez ajouter white-space: pre;en css cette façon: .tmp-element{ visibility: hidden; white-space: pre;}. Sinon, les espaces blancs sont combinés et le calcul de la largeur échoue. <input>et <span>se comporte différemment en ce qui concerne la gestion <input>des espaces blancs , conserve les espaces blancs et <span>combine les espaces blancs séquentiels en un seul s'il white-space: pre;n'est pas ajouté.
Timo Kähkönen
2
tmp.getBoundingClientRect().widthest mieux que tmp.scrollWidth, car cela renvoie parfois 0
lisak
@lisak Merci, j'ai ajusté ma réponse, mais il y a déjà de meilleures réponses ici.
Marcel Korpel
Mieux? Je ne le dirais pas. La réponse marquée manque de précision, d'autres (+ ici 1 et ici 2 ) utilisent jQuery - je ne le fais pas à cause de React. Canvas ne peut pas vous donner une hauteur de texte AFAIK. Idée: le problème des espaces pourrait également être résolu avec:.replace(/ /g, "&nbsp;")
Milan Jaros
30

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

  • Effacement
  • Initialisation
  • Espaces réservés

Il permet également un nombre illimité 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>

Michael
la source
Salut michael. Votre code fonctionne très bien mais j'ai un problème. Un de mes champs est un champ de saisie semi-automatique Google Place. Et lorsque je choisis la bonne adresse dans un menu déroulant, la largeur du champ de saisie n'est pas modifiée en fonction de la longueur de l'adresse choisie. Y a-t-il une solution simple pour cela?
Maxence
2
@Maxence écouter l' événement changeou inputsuffirait
yarwest
J'ai eu des problèmes avec l'affichage du span: aucun style car il a enregistré le span comme ayant une largeur de 0. Mieux vaut utiliser le positionnement absolu avec visibilité: caché pour la travée.
jayt
Salut @yarwest, merci pour le tuyau. Par hasard, sauriez-vous comment modifier le script original avec cette configuration? (mes connaissances en Js / jquery sont très très limitées)
Maxence
21

Voici une solution sans police monospace nécessaire, avec seulement de très petits morceaux de code de javascript , pas besoin de calculer les styles calculés , et, même supporte ime , supporte les textes rtl .

// 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>

Utilisez le span.textpour ajuster la largeur du texte et laissez l'entrée avoir la même taille que position: absolutele conteneur. Copiez la valeur de l'entrée à spanchaque fois qu'elle a changé (vous pouvez facilement changer ce morceau de code en vanilla js). Ainsi, l'entrée "s'adaptera" simplement à la taille de son contenu.

tsh
la source
18

POUR UN MEILLEUR LOOK & FEEL

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

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

Vous trouverez ci-dessous un JS vanille qui écoute l' inputévénement d'un <input>élément et définit un spanfrère pour avoir la même valeur de texte afin de le mesurer.

document.querySelector('input').addEventListener('input', onInput)

function onInput(){
    var spanElm = this.nextElementSibling;
    spanElm.textContent = this.value; // the hidden span takes the value of the input; 
    this.style.width = spanElm.offsetWidth + 'px'; // apply width of the span to the input
};
/* it's important the input and its span have same styling */
input, .measure {
    padding: 5px;
    font-size: 2.3rem;
    font-family: Sans-serif;
    white-space: pre; /* white-spaces will work effectively */
}

.measure{  
  position: absolute;
  left: -9999px;
  top: -9999px;
}
<input type="text" />
<span class='measure'></span>

Lyth
la source
1
Cela a l'air sympa, mais cela ne prend pas en compte le retour arrière et la suppression.
Marcel Korpel
Oui, pour cela, vous avez besoin d'un événement keydown. Vous pouvez ajouter une gestion spécifique pour le retour arrière et supprimer en faisant cela (par exemple === 46 pour supprimer, e.which === 8 pour retour arrière). Mais vous avez toujours besoin d'un événement keypress pour avoir accès à e.charCode pour le reste.
Lyth
Si vous ne supportez pas IE8, vous pouvez utiliser l'événement oninput au lieu de vérifier e.which: developer.mozilla.org/en-US/docs/Web/Events/input
Frinsh
1
J'ai modifié votre réponse pour éliminer jQuery et n'utiliser que du JS vanilla. sachez que cette solution est loin d'être optimale car vous voulez une solution générique qui n'implique pas de coder manuellement a spanet css pour elle.
vsync
17

C'est une réponse spécifique à Angular, mais cela a fonctionné pour moi et a été très satisfaisant en termes de simplicité et de facilité d'utilisation:

<input [style.width.ch]="value.length" [(ngModel)]="value" />

Il se met automatiquement à jour via les unités de caractères dans la réponse de Jani .

Chris Vandevelde
la source
3
Ce. Est. Épique.
Daniel Flippance
Sérieusement. Magique.
DongBin Kim
13

Voici une autre façon de résoudre ce problème en utilisant un DIV et la propriété 'contenteditable':

HTML:

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

CSS: (pour donner des dimensions à la DIV et la 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 d'utiliser ceci à l'intérieur d'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» ( .innerHTMLou .html()respectivement) du DIV.

logique8
la source
1
Cela mérite plus de votes positifs. C'est élégant et simple (tant que l'utilisation de JS pour les validations de formulaires n'est pas un problème pour vous)
Daniel Bonnell
3
Mais ce n'est pas une entrée!
Toni Michel Caubet
8

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

Une entrée peut 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

Brendan
la source
7

Tu pourrais 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();
  });
});

Cravates
la source
Si vous augmentez la taille lors de la saisie, cela entraînera un comportement laid. L'entrée doit augmenter sa taille juste avant que le personnage n'entre dedans pour plus de confort.
Lyth
5

Il suffit d'ajouter d'autres réponses.

J'ai remarqué que de nos jours, dans certains navigateurs, le champ de saisie a un scrollWidth. Ce qui signifie:

this.style.width = this.scrollWidth + 'px';

devrait bien fonctionner. testé dans chrome, firefox et safari.

Pour la prise en charge de la suppression, vous pouvez d'abord ajouter «= 0», puis réajuster.

this.style.width = 0; this.style.width = this.scrollWidth + 'px';
mec mograbi
la source
3
Veuillez également ajouter le code pertinent ici - le lien pourrait être mort à l'avenir et cet article est alors inutile.
Uooo
3
Cela fonctionne très bien, merci! Je ne sais pas pourquoi cette réponse n'a pas plus de votes positifs. C'est de loin la solution (js) la plus simple et la moins artificielle.
Formulaire du
4

Voici un JS simple et un plugin jQuery que j'ai écrit qui gérera le redimensionnement d'un élément d'entrée à l'aide d'un canevas et de la taille / famille de police pour déterminer la longueur réelle de la chaîne lors du rendu. (ne fonctionne que dans> IE9, chrome, safari, firefox, opera et la plupart des autres principaux navigateurs qui ont implémenté l'élément canvas).

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'));

Plugin jQuery:

$.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 transformations de texte, l'interligne et l'espacement des lettres, et probablement d'autres propriétés de modification de la taille du texte. Pour gérer le jeu de propriétés de transformation de texte et ajuster la valeur du texte pour correspondre à cette propriété. Les autres sont probablement assez simples. Je mettrai en œuvre si cela commence à gagner du terrain ...

newms87
la source
4

Il convient de noter qu'un redimensionnement agréable peut être effectué lorsque la police est monospace, afin que nous puissions parfaitement redimensionner l' inputélément à l'aide de l' chunité.

Également dans cette approche, nous pouvons mettre à jour la largeur du champ en mettant simplement à jour une variable CSS ( propriété personnalisée ) sur l' inputévénement et nous devrions également prendre en charge les entrées déjà pré-remplies sur l' DOMContentLoadedévénement

Démo Codepen


Balisage

<input type="text" value="space mono font" class="selfadapt" />

CSS

:root { --size: 0; }

.selfadapt {
   padding: 5px;
   min-width: 10ch;
   font-family: "space mono";
   font-size: 1.5rem;
   width: calc(var(--size) * 1ch);
}

En tant que variable racine, nous définissons --size: 0: cette variable contiendra la longueur de l'entrée et elle sera multipliée par 1chà l'intérieur de l' calc()expression. Par défaut, nous pourrions également définir une largeur minimale, par exemple10ch

La partie Javascript lit la longueur de la valeur insérée et met à jour la variable --size:

JS

let input = document.querySelector('.selfadapt');
let root  = document.documentElement.style;

/* on input event auto resize the field */
input.addEventListener('input', function() {
   root.setProperty('--size', this.value.length );
});

/* resize the field if it is pre-populated */
document.addEventListener("DOMContentLoaded", function() {
   root.setProperty('--size', input.value.length);
});

Bien sûr, cela fonctionne toujours même si vous n'utilisez pas de police à espacement fixe, mais dans ce cas, vous devrez changer la calc()formule en multipliant la --sizevariable par une autre valeur (dont elle dépend strictement de font-familyet font-size) différente de 1ch.

Fabrizio Calderan
la source
3

Cette réponse fournit l'une des méthodes les plus précises de récupération de la largeur du texte disponible dans le navigateur et est plus précise que la réponse acceptée. Il utilise l'élément canvas html5 et, contrairement à d'autres réponses, n'ajoute pas l'élément dans le DOM et évite ainsi tout problème de redistribution causé par l'ajout excessif d'éléments au DOM.

En savoir plus sur l'élément Canvas ici en ce qui concerne la largeur du texte.

REMARQUE: selon MDN, les versions abrégées de la getPropertyValue()méthode telles que la police peuvent ne pas être fiables. Je recommanderais d'obtenir les valeurs individuellement pour améliorer la compatibilité. Je ne l'ai utilisé ici que pour la vitesse.

/**
 * returns the width of child text of any DOM node as a float
 */
function getTextWidth(el) {
  // uses a cached canvas if available
  var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
  var context = canvas.getContext("2d");
  // get the full font style property
  var font = window.getComputedStyle(el, null).getPropertyValue('font');
  var text = el.value;
  // set the font attr for the canvas text
  context.font = font;
  var textMeasurement = context.measureText(text);
  return textMeasurement.width;
}

var input = document.getElementById('myInput');
// listen for any input on the input field
input.addEventListener('input', function(e) {
  var width = Math.floor(getTextWidth(e.target));
  // add 10 px to pad the input.
  var widthInPx = (width + 10) + "px";
  e.target.style.width = widthInPx;
}, false);
#myInput {
  font: normal normal 400 normal 18px / normal Roboto, sans-serif;
  min-width: 40px;
}
<input id="myInput" />

Matthieu Brent
la source
2

Vous pouvez le faire encore plus simplement dans angularjs en utilisant le style ng intégré directive .

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; }

Ajustez le charWidth pour correspondre à la largeur de votre police. Il semble être 7 avec une taille de police de 12 px;

Michieljoris
la source
3
C'est cool et pratique à savoir, mais l'ajout d'angularjs à une application pour redimensionner dynamiquement un élément d'entrée est vraiment excessif, surtout quand OP a demandé des solutions "HTML, JavaScript, PHP ou CSS". On pourrait dire que jQuery est excessif pour cela aussi, mais - contrairement à Angular - être une boîte à outils de manipulation DOM est au cœur de l'objectif de jQuery.
vlasits
Comment suis-je censé connaître la largeur du caractère saisi? Il n'est pas facile de supposer qu'il s'agit d'une police de taille unique.
Ethan
1
Vous ne pouvez pas exiger une police à espacement fixe et vous n'avez pas besoin d'Angular. La réponse de brendan fait essentiellement la même chose.
Dan Dascalescu
2

Si vous utilisez Bootstrap, cela pourrait être fait très facilement:

<div contenteditable="true" class="form-control" style="display: inline"></div>

Vous aurez juste besoin de récupérer le contenu de div et de le mettre dans une entrée masquée avant de soumettre le formulaire.

Alexey Kosov
la source
1

Je pense que vous interprétez mal la propriété CSS min-width . min-width est généralement utilisé pour définir une largeur minimale du DOM dans une mise en page 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 que ce champ de saisie contient au moins un caractère lorsqu'un utilisateur le soumet, vous devrez faire une validation de formulaire avec JavaScript et PHP. Si c'est effectivement ce que vous essayez de faire, je modifierai cette réponse et ferai de mon mieux pour vous aider.

Peterjmag
la source
Je sais ce que signifie px et je sais que javascript a une fonction pour min-width, mais cela ne fonctionne pas pour le texte d'entrée.
Kerc
1
@Kerc: «javascript a une fonction pour min-width» - laquelle? Que voulez-vous dire? - «ça ne marche pas» n'est jamais une bonne description d'un problème. Essayez d'élaborer sur le comportement prévu.
Marcel Korpel
Avez-vous même essayé mon exemple, puis vous voyez que ce n'est pas 1 px et le vôtre ne l'est pas aussi. Cela ne fonctionnera pas, peu importe si je l'écris en html, css
Kerc
Peut-être qu'il y a une fonction php pour cela, tout le monde le sait?
Kerc
J'ai essayé votre exemple, mais j'ai supposé qu'un champ d'entrée de 1 pixel de large n'était pas ce que vous recherchiez. Si c'est le cas, essayez<input type="text" value="1" style="width:1px;" />
peterjmag
1

J'ai vraiment aimé la réponse de Lyth , mais je voulais aussi qu'elle:

  1. Gérer le retour arrière et supprimer
  2. Pas besoin d'ajouter manuellement une balise adjacente.
  3. Appliquer une largeur minimale.
  4. S'applique automatiquement aux éléments avec une classe spécifique

J'ai adapté son JSFiddle et j'ai trouvé ça . Une amélioration non présente dans ce violon serait d'utiliser quelque chose comme l' analyseur CSS jQuery pour lire réellement la largeur initiale à partir de la règle input.textbox-autosize, et l'utiliser comme minWidth. Bon, j'utilise simplement un attribut sur le, ce qui en fait une démo compacte mais n'est pas idéale. car il nécessite un attribut supplémentaire sur chaque entrée. Vous pouvez également simplement mettre le minWidth à 100 directement 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
});
Josh
la source
1

Mieux vaut onvalue:

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

Cela implique également le collage, le glisser-déposer, etc.

Łukasz Polowczyk
la source
1

Voici mes 2 cents. Créez un div invisible vide. Remplissez-le avec le contenu d'entrée et renvoyez la largeur au champ d'entrée. Faites correspondre les styles de texte entre chaque boîte.

$(".answers_number").keyup(function(){
    $( "#number_box" ).html( $( this ).val() );
    $( this ).animate({
        width: $( "#number_box" ).width()+20
        }, 300, function() {
    });
});
#number_box {
   position: absolute;
   visibility: hidden;
   height: auto;
   width: auto;
   white-space: nowrap;
   padding:0 4px;
   /*Your font styles to match input*/
   font-family:Arial;
   font-size: 30px; 
}
    
.answers_number {
   font-size: 30px; 
   font-family:Arial;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" class="answers_number" />
<div id="number_box">
</div>

Thomas Byy
la source
1

Assez facile:

oninput='this.style.width = (this.scrollWidth - N) + "px";'

Où N est un nombre (2 dans l'exemple, 17 sur quelque chose que je développe) qui est déterminé expérimentalement.

La soustraction de N empêche cet étrange espace exténuant de s'accumuler bien avant que le texte n'atteigne la fin de la zone de texte.

Comparer. Faites très attention à la façon dont la taille change après le premier caractère.

<p>Subtracting N:</p>    
<input type="text" placeholder="enter lots of text here" oninput='this.style.width = (this.scrollWidth-2) + "px";'>

<p>Not Subtracting N:</p>    
<input type="text" placeholder="enter lots of text here" oninput='this.style.width = (this.scrollWidth) + "px";'>

Dan T
la source
Je ne l' ai pas testé intensivement avec cela, mais vous pouvez simplement changer oninput='this.style.width = (this.scrollWidth-2) + "px";'par oninput='this.style.width = 0; this.style.width = this.scrollWidth + "px";'se débarrasser de l'espace accumulant
MaxCloutier
0

Je passe juste un peu de temps à trouver comment le faire.
En fait, le moyen le plus simple que j'ai trouvé est de déplacer la valeur d'entrée pour s'étendre juste avant l'entrée, en conservant la largeur du symbole d'entrée 1. Bien que je ne puisse pas être sûr qu'il correspond à votre besoin initial.
Peut-être que c'est un code supplémentaire, mais dans une application basée sur react + flux, c'est une solution tout à fait naturelle.

freele
la source
0

Sur la base de 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 que le travail soit fait.

Je fais la même chose que la plupart des gens ici en utilisant une étendue pour écrire le texte d'entrée puis en obtenant la largeur. Ensuite, je règle la largeur lorsque les actions keyupetblur sont appelées.

Voici un codepen fonctionnel . Ce codepen montre comment cela peut être utilisé avec plusieurs champs d'entrée.

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, coupe les espaces supplémentaires et définit le texte dans la plage pour obtenir la largeur. S'il n'y a pas de texte, il obtient à la place l'espace réservé et l'insère à la place dans la plage. Une fois qu'il entre le texte dans la plage, il définit la largeur de l'entrée. Le + 5sur la largeur est parce que sans cela, l'entrée est coupée un tout petit 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 pouvait être amélioré, veuillez me le faire savoir car c'est la solution la plus propre que je puisse trouver.

Matthieu
la source
0

Pourquoi ne pas utiliser uniquement le CSS?

<div id="wrapper">
  <input onkeyup="keyup(event)">
  <div id="ghost"></div>
</div>

function keyup(e) {
	document.getElementById('ghost').innerText = e.target.value;
}
#wrapper {
  position: relative;
  min-width: 30px;
  display: inline-block;
}

input {
  position: absolute;
  left:0;
  right:0;
  border:1px solid blue;
  width: 100%;
}

#ghost {
  color: transparent;
}
<div id="wrapper">
  <input onkeyup="keyup(event)">
  <div id="ghost"></div>
</div>

wrapper {
  position: relative;
  min-width: 30px;
  border: 1px solid red;
  display: inline-block;
}

input {
  position: absolute;
  left:0;
  right:0;
  width: 100%;
}

#ghost {
  color: transparent;
}

ce code a été introduit par @Iain Todd et j'ai pensé que je devrais le partager

Milad
la source
Ce n'est pas que du CSS. C'est juste une autre méthode js. Intéressant.
vatavale le
0

Un moyen générique à toute épreuve doit:

  1. Tenez compte de tous les styles possibles de l' inputélément mesuré
  2. Être capable d'appliquer la mesure sur n'importe quelle entrée sans modifier le HTML ou

Démo Codepen

var getInputValueWidth = (function(){
  // https://stackoverflow.com/a/49982135/104380
  function copyNodeStyle(sourceNode, targetNode) {
    var computedStyle = window.getComputedStyle(sourceNode);
    Array.from(computedStyle).forEach(key => targetNode.style.setProperty(key, computedStyle.getPropertyValue(key), computedStyle.getPropertyPriority(key)))
  }
  
  function createInputMeassureElm( inputelm ){
    // create a dummy input element for measurements
    var meassureElm = document.createElement('span');
    // copy the read input's styles to the dummy input
    copyNodeStyle(inputelm, meassureElm);
    
    // set hard-coded styles needed for propper meassuring 
    meassureElm.style.width = 'auto';
    meassureElm.style.position = 'absolute';
    meassureElm.style.left = '-9999px';
    meassureElm.style.top = '-9999px';
    meassureElm.style.whiteSpace = 'pre';
    
    meassureElm.textContent = inputelm.value || '';
    
    // add the meassure element to the body
    document.body.appendChild(meassureElm);
    
    return meassureElm;
  }
  
  return function(){
    return createInputMeassureElm(this).offsetWidth;
  }
})();


// delegated event binding
document.body.addEventListener('input', onInputDelegate)

function onInputDelegate(e){
  if( e.target.classList.contains('autoSize') )
    e.target.style.width = getInputValueWidth.call(e.target) + 'px';
}
input{ 
  font-size:1.3em; 
  padding:5px; 
  margin-bottom: 1em;
}

input.type2{
  font-size: 2.5em;
  letter-spacing: 4px;
  font-style: italic;
}
<input class='autoSize' value="type something">
<br>
<input class='autoSize type2' value="here too">

vsync
la source
0

Vous pouvez simplement définir l' sizeattribut. Si vous utilisez l'un des frameworks réactifs, ce qui suit sera suffisant:

<input size="{{ yourValue.length }}" [value]="yourValue" />

mais si vous utilisez pur js, vous devez définir des gestionnaires d'événements, comme:

<input oninput="this.setAttribute('size', this.value.length)" />
Akim Lyubchenko
la source