Dopasuj szerokość pola wejściowego do jego wejścia


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

To jest mój kod i nie działa. Czy w HTML, JavaScript, PHP lub CSS jest inny sposób ustawienia minimalnej szerokości?

Chcę mieć pole wprowadzania tekstu z dynamicznie zmieniającą się szerokością, tak aby pole wejściowe było płynne wokół jego zawartości. Każde wejście ma wbudowane dopełnienie 2em, to jest problem, a drugi problemmin-width ogóle nie działa na wejściu.

Jeśli ustawię szerokość większą niż potrzeba, to cały program jest niechlujny, potrzebuję szerokości 1 piksela, więcej tylko wtedy, gdy jest to potrzebne.


Czy to odpowiada na twoje pytanie? Tworzenie
obszaru tekstowego

Odpowiedzi:


96

Wygląda na to, że spodziewasz się, że styl zostanie zastosowany dynamicznie do szerokości pola tekstowego na podstawie zawartości pola tekstowego. Jeśli więc trzeba będzie niektóre js do uruchomienia na zawartość pola tekstowego się zmienia, coś jak to :

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

Uwaga: to rozwiązanie działa tylko wtedy, gdy każdy znak jest dokładnie 8pxszeroki.


41
@Kerc & Tahbaza: tak, ale to zadziała tylko wtedy, gdy szerokość każdego znaku wynosi dokładnie 8 pikseli.
Marcel Korpel,

6
Zgadzam się, Marcel (a wysłany kod nie jest czymś, do czego naprawdę widzę zastosowanie), ale wykazuje pożądane zachowanie. Czy wiesz, jak obliczyć rzeczywistą szerokość renderowanego tekstu, biorąc pod uwagę czcionkę, rozmiar, grubość, kerning itp.? Jeśli tak, podziel się nim, ponieważ okazjonalnie uważam, że ten fragment kodu jest przydatny.
Tahbaza

1
- Już myślałem, że to tylko przykład. Nie jest jednak trudno obliczyć szerokość wejścia. Spójrz na moją odpowiedź.
Marcel Korpel

Jednostki em to szerokość znaku „m”. Byłoby to przydatne do obliczania szerokości łańcucha. Widziałem problemy z różnymi przeglądarkami z jednostkami em zastosowanymi do niektórych atrybutów, więc przetestuj to.
Archonic

7
zapomniałeś o wydarzeniu PASTE przyjacielu;) powinieneś zmienić to naonInput
vsync

114

W nowoczesnych wersjach przeglądarek chdostępna jest również jednostka CSS . W moim rozumieniu jest to jednostka niezależna od czcionki, gdzie 1chjest równa szerokości znaku0 (zero) w dowolnej czcionce.

Tak więc coś tak prostego, jak poniższe, może być użyte jako funkcja zmiany rozmiaru:

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>

Ten przykład zmieni rozmiar elementu „elem” na długość wartości + 2 dodatkowe znaki.


13
Dziwię się, że ten komentarz nie został oceniony wyżej, ponieważ jest to świetne rozwiązanie i około 95% ( 1 ) przeglądarek to obsługuje.
Husky

8
To nie jest dobra odpowiedź na wszystko, ponieważ pomiar nie jest dokładny i nie uwzględnia stylów, które mogą wystąpić na inputelement, na przykład font-style, letter-spacingi tak dalej. Poprawiłem odpowiedź za pomocą demonstracji na żywo.
vsync

5
Działa świetnie, jeśli używasz czcionki o stałej szerokości. W przypadku innych czcionek przebieg może się różnić, ponieważ najwyraźniej wykorzystuje szerokość znaku 0.
Jilles van Gurp

2
To jest naprawdę świetne. Chociaż zauważ, że czasami powoduje błędy / nie działa zgodnie z oczekiwaniami, gdy .zostanie napotkany.
Rishav

1
Działa to doskonale, jeśli ustawisz rozmiar pola na wejściu na „content-box”. W ten sposób ignoruje wypełnienie podczas ustawiania rozmiaru.
Hypersapien

65

Aby obliczyć szerokość bieżącego wejścia, będziesz musiał osadzić go w tymczasowym spanelemencie, dołączyć go do DOM, uzyskać obliczoną szerokość (w pikselach) za pomocą scrollWidthwłaściwości i spanponownie usunąć . Oczywiście musisz upewnić się, że ta sama rodzina czcionek, rozmiar czcionki itp. Jest używana inputzarówno wspan elemencie, elemencie. Dlatego przypisałem im tę samą klasę.

Dołączyłem funkcję do keyupzdarzenia, gdyż na keypresswejściu znak nie jest jeszcze dodawany do wejścia value, przez co będzie skutkował złą szerokością. Niestety nie wiem jak się pozbyć przewijania pola wejściowego (przy dodawaniu znaków na końcu pola); przewija się, ponieważ znak jest dodawany i wyświetlany przed adjustWidthOfInput()wywołaniem. I, jak powiedziałem, nie mogę tego zrobić w drugą stronę, ponieważ wtedy będziesz mieć wartość pola wejściowego przed wstawieniem wciśniętego znaku. Spróbuję później rozwiązać ten problem.

BTW, testowałem to tylko w Firefoksie (3.6.8), ale mam nadzieję, że zrozumiesz, o co chodzi.

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

Podobała mi się twoja odpowiedź, a nawet zaimplementowałem ją za pomocą jQuery / Underscore: gist.github.com/3745941 . Mógłbym jednak przyjąć pewne założenia: (1) szerokość dowolnego znaku nie przekracza 14px, (2) dopuszczalne jest, aby element wejściowy wystawał o 14px poza wartość elementu. Mam to dołączone do wydarzenia keydown i działa świetnie!
Nathan

11
Należy dodać white-space: pre;do css ten sposób: .tmp-element{ visibility: hidden; white-space: pre;}. W przeciwnym razie spacje są łączone, a obliczenie szerokości kończy się niepowodzeniem. <input>i <span>zachowuje się inaczej w odniesieniu do obsługi <input>białych znaków , zachowuje odstępy i <span>łączy kolejne odstępy w jeden, jeśli white-space: pre;nie jest dodawany.
Timo Kähkönen

2
tmp.getBoundingClientRect().widthjest lepsze niż tmp.scrollWidth, ponieważ czasami zwraca 0
lisak

@lisak Dzięki, poprawiłem odpowiedź, ale tutaj są już lepsze odpowiedzi.
Marcel Korpel

Lepszy? Nie powiedziałbym tego. Zaznaczona odpowiedź nie jest precyzyjna, inni (+ tu 1 i tu 2 ) używają jQuery - ja tego nie robię z powodu Reacta. Canvas nie może podać wysokości tekstu AFAIK. Pomysł: problem ze spacjami można również rozwiązać za pomocą:.replace(/ /g, "&nbsp;")
Milan Jaros

30

Oto modyfikacja odpowiedzi Lytha, która uwzględnia:

  • Usunięcie
  • Inicjalizacja
  • Symbole zastępcze

Pozwala również na dowolną liczbę pól wejściowych! Aby zobaczyć to w akcji: http://jsfiddle.net/4Qsa8/

Scenariusz:

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

Styl:

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


Cześć Michał. Twój kod działa świetnie, ale mam problem. Jedno z moich pól to pole autouzupełniania miejsca Google. A kiedy wybieram właściwy adres z rozwijanego menu, szerokość pola wejściowego nie zmienia się zgodnie z długością wybranego adresu. Czy jest na to prosta poprawka?
Maxence,

2
@Maxence słuchanie changelub inputwydarzenia wystarczyłoby
yarwest

Wystąpiły problemy z wyświetlaniem zakresu: brak stylizacji, ponieważ zarejestrowano rozpiętość jako mającą 0 szerokości. Lepiej jest używać pozycjonowania bezwzględnego z widocznością: ukryte dla rozpiętości.
jayt

Cześć @yarwest, dzięki za wskazówkę. Czy wiesz, jak zmodyfikować oryginalny skrypt za pomocą tej konfiguracji? (moja wiedza na temat Js / jquery jest bardzo ograniczona)
Maxence

21

Oto rozwiązanie bez potrzebnej czcionki o stałej szerokości , z bardzo małym kodem javascript , nie wymagające obliczania obliczonych stylów , a nawet obsługujące ime , obsługujące teksty 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>

Użyj, span.textaby dopasować szerokość tekstu i pozwól, aby dane wejściowe miały ten sam rozmiar position: absolutedo kontenera. Kopiuj wartość wejścia do the za spankażdym razem, gdy się zmieniła (możesz łatwo zmienić ten fragment kodu na vanilla js). Tak więc dane wejściowe po prostu „dopasują się” do rozmiaru zawartości.


18

DLA NICERSKIEGO WYGLĄDU I POCZUCIA

Należy użyć zdarzenia keypress () jQuery w połączeniu z String.fromCharCode (e.which), aby uzyskać wciśnięty znak. W związku z tym możesz obliczyć, jaka będzie twoja szerokość . Czemu? Ponieważ będzie wyglądać o wiele bardziej seksownie :)

Oto plik jsfiddle, który daje ładne zachowanie w porównaniu do rozwiązań wykorzystujących zdarzenie keyup: http://jsfiddle.net/G4FKW/3/

Poniżej znajduje się waniliowy JS, który nasłuchuje inputzdarzenia <input>elementu i ustawia element spansiostrzany tak, aby miał tę samą wartość tekstową, aby go zmierzyć.

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>


1
Wygląda ładnie, ale nie bierze pod uwagę Backspace i Delete.
Marcel Korpel

Tak, do tego potrzebujesz keydown event. Możesz dodać specyficzną obsługę dla backspace i usunąć, robiąc to (np. === 46 dla delete, e.which === 8 dla backspace). Ale nadal potrzebujesz zdarzenia keypress, aby mieć dostęp do e.charCode dla reszty.
Lyth

Jeśli nie obsługujesz IE8, możesz użyć zdarzenia oninput zamiast sprawdzania e.which: developer.mozilla.org/en-US/docs/Web/Events/input
piątek,

1
Zredagowałem twoją odpowiedź, aby wyeliminować jQuery i używać tylko zwykłego JS. Pamiętaj, że to rozwiązanie jest dalekie od optymalnego, ponieważ potrzebujesz ogólnego rozwiązania, które nie wymaga ręcznego kodowania spandla niego a i css.
vsync

17

To jest odpowiedź specyficzna dla Angulara, ale zadziałało to dla mnie i było bardzo satysfakcjonujące pod względem prostoty i łatwości użycia:

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

Automatycznie aktualizuje się za pośrednictwem jednostek postaci w odpowiedzi Jani .


3
To. Jest. Epicki.
Daniel Flippance

Poważnie. Magiczny.
DongBin Kim

13

Oto alternatywny sposób rozwiązania tego problemu za pomocą funkcji DIV i właściwości „contenteditable”:

HTML:

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

CSS: (aby nadać DIV pewne wymiary i ułatwić jej zobaczenie)

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

}

Uwaga: jeśli planujesz użyć tego w elemencie FORM, który planujesz przesłać, musisz użyć Javascript / jQuery do przechwycenia zdarzenia przesyłania, aby można było przeanalizować „wartość” ( .innerHTMLlub .html()odpowiednio) DIV.


1
To zasługuje na więcej głosów. Jest elegancki i prosty (o ile używanie JS do walidacji formularzy nie stanowi dla Ciebie problemu).
Daniel Bonnell,

3
Ale to nie jest wkład!
Toni Michel Caubet

8

Możesz również ustawić szerokość wejścia za pomocą atrybutu rozmiaru . Rozmiar wejścia określa jego szerokość w znakach.

Wejście może dynamicznie dostosowywać swój rozmiar, nasłuchując kluczowych zdarzeń.

Na przykład

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

JsFiddle tutaj


7

Można zrobić coś jak to

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

Wcześniejsze

Wcześniejsze


Jeśli zwiększysz rozmiar po naciśnięciu klawisza, spowoduje to brzydkie zachowanie. Wejście musi zwiększyć swój rozmiar tuż przed wejściem postaci, aby zapewnić większy komfort.
Lyth

5

Po prostu dodając inne odpowiedzi.

Zauważyłem, że obecnie w niektórych przeglądarkach pole wprowadzania ma scrollWidth. Co znaczy:

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

powinno ładnie działać. przetestowany w Chrome, Firefoxie i Safari.

Aby uzyskać obsługę usuwania, możesz najpierw dodać „= 0”, a następnie ponownie dostosować.

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

3
Dodaj tutaj również odpowiedni kod - link może być w przyszłości martwy, a wtedy ten post będzie bezużyteczny.
Uooo,

3
To działa świetnie, dzięki! Nie wiem, dlaczego ta odpowiedź nie ma więcej głosów pozytywnych. To zdecydowanie najprostsze, mniej wymyślne rozwiązanie (js).
Formularz

4

Oto prosty JS i wtyczka jQuery, którą napisałem, która poradzi sobie ze zmianą rozmiaru elementu wejściowego za pomocą płótna i rozmiaru / rodziny czcionki, aby określić rzeczywistą długość ciągu podczas renderowania. (działa tylko w> IE9, chrome, safari, firefox, opera i większości innych głównych przeglądarek, w których zaimplementowano element 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'));

Wtyczka 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();

Uwaga: to nie będzie obsługiwać przekształceń tekstu, odstępów między wierszami i odstępów między literami oraz prawdopodobnie innych właściwości zmieniających rozmiar tekstu. Aby obsłużyć transformację tekstu, ustaw i dostosuj wartość tekstu, aby pasowała do tej właściwości. Pozostałe są prawdopodobnie dość proste. Wdrożę, jeśli to zacznie nabierać trakcji ...


4

Warto zaznaczyć, że ładnie wyglądającą zmianę rozmiaru można zrobić, gdy czcionka jest nieproporcjonalna, dzięki czemu możemy doskonale zmienić rozmiar inputelementu za pomocą chjednostki.

Również w tym podejściu możemy zaktualizować szerokość pola, po prostu aktualizując zmienną CSS ( właściwość niestandardową ) na inputzdarzeniu, a także powinniśmy zadbać o już wstępnie wypełnione dane wejściowe w DOMContentLoadedzdarzeniu

Codepen demo


Narzut

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

Jako zmienną główną ustawiliśmy --size: 0: ta zmienna będzie zawierać długość wejścia i zostanie pomnożona przez 1chwewnątrz calc()wyrażenia. Domyślnie możemy też ustawić minimalną szerokość, np10ch

Część Javascript odczytuje długość wstawionej wartości i aktualizuje zmienną --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);
});

oczywiście to nadal działa, nawet jeśli nie używasz czcionki o stałej szerokości, ale w takim przypadku będziesz musiał zmienić calc()formułę, mnożąc --sizezmienną przez inną wartość (która jest ściśle zależna od font-familyi font-size) inną niż 1ch.


3

Ta odpowiedź stanowi jedną z najdokładniejszych metod pobierania szerokości tekstu dostępnych w przeglądarce i jest dokładniejsza niż zaakceptowana odpowiedź. Używa elementu canvas html5 iw przeciwieństwie do innych odpowiedzi nie dodaje elementu do DOM, a tym samym unika problemów z ponownym przepływem spowodowanych nadmiernym dodawaniem elementów do DOM.

Czytaj więcej o elemencie Canvas tutaj w stosunku do szerokości tekstu.

UWAGA: Według MDN skrócone wersje getPropertyValue()metody, takie jak czcionka, mogą być zawodne. Zalecałbym pobieranie wartości pojedynczo, aby poprawić zgodność. Użyłem go tutaj tylko dla szybkości.

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


2

Możesz to zrobić jeszcze prościej w angularjs, używając wbudowanej dyrektywy ng-style .

W Twoim html:

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

W kontrolerze:

 $scope.testdata = "whatever";

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

W twoim css:

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

Dostosuj charWidth, aby dopasować szerokość czcionki. Wydaje się, że jest to 7 przy rozmiarze czcionki 12 pikseli;


3
Jest to fajne i przydatne, ale dodanie angularjs do aplikacji w celu dynamicznej zmiany rozmiaru elementu wejściowego jest naprawdę poważną przesadą, zwłaszcza gdy OP poprosił o rozwiązania „HTML, JavaScript, PHP lub CSS”. Można by argumentować, że jQuery również jest przesadą, ale - w przeciwieństwie do Angulara - bycie zestawem narzędzi do manipulacji DOM jest podstawą działania jQuery.
vlasits

Skąd mam znać szerokość wpisywanego znaku? Nie jest łatwo założyć, że jest to czcionka o jednym rozmiarze.
Ethan

1
Nie możesz wymagać czcionki o stałej szerokości i nie ma potrzeby używania Angulara. odpowiedź Brendana jest zasadniczo taka sama.
Dan Dascalescu

2

Jeśli używasz Bootstrap, można to zrobić bardzo łatwo:

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

Wystarczy pobrać zawartość div i umieścić ją w ukrytym miejscu przed wysłaniem formularza.


1

Myślę, że błędnie interpretujesz właściwość CSS min-width . min-width jest zwykle używana do definiowania minimalnej szerokości DOM w układzie płynnym, na przykład:

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

To ustawiłoby element wejściowy na minimalną szerokość 200 pikseli. W tym kontekście „px” oznacza „piksele”.

Teraz, jeśli próbujesz sprawdzić, czy pole wejściowe zawiera co najmniej jeden znak, gdy użytkownik je przesyła, musisz przeprowadzić walidację formularza za pomocą JavaScript i PHP. Jeśli rzeczywiście próbujesz to zrobić, poprawię tę odpowiedź i dołożę wszelkich starań, aby Ci pomóc.


Wiem, co oznacza px i wiem, że javascript ma funkcję dla min-width, ale nie działa dla tekstu wejściowego.
Kerc

1
@Kerc: „javascript ma funkcję dla min-width” - która z nich? Co masz na myśli? - „to nie działa” nigdy nie jest dobrym opisem problemu. Spróbuj szczegółowo opisać zamierzone zachowanie.
Marcel Korpel

Czy nawet wypróbowałeś mój przykład, niż widzisz, że to nie jest 1 piksel, a twój też nie. To nie zadziała bez względu na to, czy napiszę to w html, css
Kerc

Może jest do tego funkcja php, ktoś wie?
Kerc

Wypróbowałem twój przykład, ale założyłem, że pole wejściowe o szerokości 1 piksela nie jest tym, czego szukałeś. Jeśli tak, spróbuj<input type="text" value="1" style="width:1px;" />
peterjmag

1

Bardzo podobała mi się odpowiedź Lytha , ale bardzo chciałem, żeby:

  1. Obsługuj klawisz Backspace i usuń
  2. Nie wymaga ręcznego dodawania sąsiedniego tagu.
  3. Wymuś minimalną szerokość.
  4. Automatycznie stosowane do elementów z określoną klasą

Dostosowałem jego JSFiddle i wymyśliłem to . Jednym z ulepszeń nieobecnych w tych skrzypcach byłoby użycie czegoś takiego jak parser jQuery CSS, aby faktycznie odczytać początkową szerokość z reguły input.textbox-autosize i użyć tego jako minWidth. Tak, po prostu używam atrybutu na stronie, co daje kompaktowe demo, ale nie jest idealne. ponieważ wymaga dodatkowego atrybutu na każdym wejściu. Możesz także po prostu umieścić minWidth jako 100 bezpośrednio w 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
});

1

Lepiej jest onvalue:

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

Obejmuje również wklejanie, przeciąganie i upuszczanie itp.


1

Oto moje 2 centy. Utwórz pusty, niewidoczny element DIV. Wypełnij go treścią wejściową i zwróć szerokość do pola wejściowego. Dopasuj style tekstu w każdym polu.

$(".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>


1

Całkiem proste:

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

Gdzie N jest liczbą (w tym przykładzie 2, 17 na czymś, co rozwijam), która jest określana eksperymentalnie.

Odejmowanie N zapobiega gromadzeniu się tej dziwnej, nadmiernej przestrzeni na długo przed końcem pola tekstowego.

Porównać. Zwróć szczególną uwagę, jak zmienia się rozmiar nawet po pierwszym znaku.

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


Nie testowałem tego szczegółowo, ale możesz po prostu zmienić oninput='this.style.width = (this.scrollWidth-2) + "px";', oninput='this.style.width = 0; this.style.width = this.scrollWidth + "px";'aby pozbyć się gromadzącej się przestrzeni
MaxCloutier

0

Po prostu spędzam trochę czasu zastanawiając się, jak to zrobić.
Właściwie najprostszym sposobem, jaki znalazłem, jest przesunięcie wartości wejściowej do zakresu tuż przed wejściem, zachowując szerokość symbolu wejścia 1. Chociaż nie jestem pewien, czy pasuje do twoich początkowych potrzeb.
Może to jakiś dodatkowy kod, ale w aplikacji opartej na reakcji + flux jest to całkiem naturalne rozwiązanie.


0

W oparciu o odpowiedź Michaela stworzyłem własną wersję tego przy użyciu jQuery. Myślę, że jest to czystsza / krótsza wersja większości odpowiedzi tutaj i wydaje się, że wykonuje swoje zadanie.

Robię to samo, co większość ludzi tutaj, używając rozpiętości, aby wpisać tekst wejściowy, a następnie uzyskać szerokość. Następnie ustawiam szerokość, gdy akcje keyupiblur wywoływania .

Oto działający kod . Ten kod pokazuje, jak można go używać z wieloma polami wejściowymi.

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

Powyższa funkcja pobiera wartość wejściową, przycina dodatkowe spacje i ustawia tekst w zakresie, aby uzyskać szerokość. Jeśli nie ma tekstu, zamiast tego pobiera symbol zastępczy i zamiast tego wprowadza go do zakresu. Po wprowadzeniu tekstu do zakresu ustawia szerokość wejścia. + 5Szerokości dlatego bez że wejście zostanie odcięty odrobinę w przeglądarce krawędzi.

$('.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);
});

Jeśli można to poprawić, daj mi znać, ponieważ jest to najczystsze rozwiązanie, jakie mogłem wymyślić.


0

Dlaczego nie używać tylko 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;
}

ten kod został wprowadzony przez @Iain Todd do i pomyślałem, że powinienem się nim podzielić


To nie tylko css. To po prostu kolejna metoda js. Ciekawe.
vatavale

0

Kuloodporny, ogólny sposób musi:

  1. Weź pod uwagę wszystkie możliwe style mierzonego inputelementu
  2. Umiejętność zastosowania pomiaru na dowolnym wejściu bez modyfikowania kodu HTML lub

Codepen demo

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


0

Możesz po prostu ustawić sizeatrybut. Jeśli używasz jednego z reaktywnych frameworków, wystarczy:

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

ale jeśli używasz czystego js, ​​powinieneś ustawić programy obsługi zdarzeń, takie jak:

<input oninput="this.setAttribute('size', this.value.length)" />
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.