Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get placeholder text to shrink to fit within its text input element and show its entire value? [duplicate]

I have the following HTML:

<form>
    <table border="1">
        <tr>
            <td>Traveler's name:</td>
            <td>
                <input type="text" id="travelername" placeholder="Last Name, First Name, Middle Initial"/>
            </td>
        </tr>
        <tr>
            <td>Traveler's E-mail:</td>
            <td>
                <input type="email" id="traveleremail"/>
            </td>
        </tr>
    </table>
</form>

I want the placeholder val to be fully visible at all times, but it's not:

enter image description here

I tried adding this CSS:

input[placeholder] {
    font-size: 0.6em;
}

...but, while this reduces the size of the font admirably, the text is truncated:

enter image description here

I tried adding to the CSS like so:

input[placeholder] {
    font-size: 0.6em;
    width: 500;
}

...but it does nothing to expand/widen the placeholder's text area within the input text (the input text is wide enough to hold the reduced text, but it is still squished into a too-small area within itself).

How can this be accomplished?

like image 275
B. Clay Shannon-B. Crow Raven Avatar asked Jul 30 '15 16:07

B. Clay Shannon-B. Crow Raven


1 Answers

Original Reply - July 2015

What about doing something like this? I used jQuery to demonstrate it. If you want it to be more 'exact' in terms of width of the text, you can look at a way to get the text's width and then setting the width in jquery's CSS to the value returned from the function that gets the text's width (in which case you will likely have to create an element, set its html to the placeholder's content, get the text's width and then delete the element). In any case, the code below is what I would do to accomplish what you are asking.

I decided to use setInterval because getting changes to input fields are not black and white. each loops through the input elements. The code then checks to see if input is empty, if it is, is downscales the font-size (to 10px as I hardcoded it), otherwise it sets it to the default (let's say you want 14px, it gets 14px).

setInterval(function() {
    $('input').each(function(){
        if($(this).val() === ''){
            $(this).css({
                "width":$(this).width()+"px",
                "height":$(this).height()+"px"
            });
            if(parseFloat($(this).css('font-size'))<=14){
                $(this).animate({
                    "font-size":10+"px"
                });
            }
        }
        else {
            $(this).finish().clearQueue().css({
                "font-size":14+"px"
            });
        }
    });
}, 100);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form>
    <table border="1">
        <tr>
            <td>Traveler's name:</td>
            <td>
                <input type="text" id="travelername" placeholder="Last Name, First Name, Middle Initial"/>
            </td>
        </tr>
        <tr>
            <td>Traveler's E-mail:</td>
            <td>
                <input type="email" id="traveleremail"/>
            </td>
        </tr>
    </table>
</form>

If you want, you can lower or increase the interval for the setInterval function to allow it to execute faster or slower (keep in mind performance and different computing speeds)



EDIT - May 2017

Seeing that this question has been viewed over a thousand times, I felt I should update my answer to be a little more useful and be less reliant on manual input.

The code below works as follows:

  • Create your CSS style for both the input fields and their associated clones (this logic can be customized to your needs, but for simplicity purposes, I've given all input element clones the same class)
  • Loops over all input elements and creates a clone
  • Gets the clone's width and compares its width to the input element's width while reducing the font-size on each iteration by the step
  • Once the clone's width is less than or equal to the input element's width, we delete the clone element and set the input's font-size.
  • Upon user input inside the input element, we undo our changes to font-size

Note: When "undoing" our changes to the input element, we are in fact removing the inline property and value. Any styles for these elements should be done in CSS (or you'll have to try to find a way around this, such as creating a hidden element with id, accessing it, pulling the style and applying it back to the input element).

When testing the code below, I, personally, found that a step of 0.1 was sufficient and that a value smaller (of say 0.01) impacted performance. You can, however, play with this value as you wish.

// Step is used to reduce font-size by value X
var step = 0.1;

setInterval(function() {
  // Loop over input elements
  $('input').each(function() {
    // Only change font-size if input value is empty (font-size should only affect placeholder)
    if ($(this).val() === '') {
      // Create clone
      $clone = $('<span></span>')
        .appendTo('body')
        .addClass('inputClone')
        .text($(this).attr('placeholder'));
      // Adjust font-size of clone
      var fontSize = $(this).css('font-size');
      do {
        fontSize = parseFloat($clone.css('font-size')) - step;
        $clone.css({
          'font-size': fontSize
        });
      } while ($clone.width() > $(this).width());
      // Maintain input field size
      $(this).css({
        "width": $(this).width() + "px",
        "height": $(this).height() + "px"
      });
      // Change input font-size
      $(this).animate({
        'font-size': fontSize
      });
      // Delete clone
      $clone.remove();
    } else {
      // Default input field back to normal
      $(this)
        .finish()
        .clearQueue()
        .attr('style', function(i, style) {
          // Remove inline style for font-size
          return style.replace(/font-size[^;]+;?/g, '');
        });
    }
  });
}, 100);
input,
.inputClone {
  font-family: "Arial", Helvetica, sans-serif;
  font-size: 14px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
  <table border="1">
    <tr>
      <td>Traveler's name:</td>
      <td>
        <input type="text" id="travelername" placeholder="Last Name, First Name, Middle Initial" />
      </td>
    </tr>
    <tr>
      <td>Traveler's E-mail:</td>
      <td>
        <input type="email" id="traveleremail" />
      </td>
    </tr>
  </table>
</form>
like image 123
ctwheels Avatar answered Oct 22 '22 09:10

ctwheels