Input text field with auto width [duplicate] - javascript

Newbie CSS question. I thought width:auto for a display:block element meant 'fill available space'. However for an <input> element this doesn't seem to be the case. For example:
<body>
<form style='background:red'>
<input type='text' style='background:green; display:block; width:auto'>
</form>
</body>
Two questions then:
Is there a definition of exactly what width:auto does mean? The CSS spec seems vague to me, but maybe I missed the relevant section.
Is there a way to achieve my expected behavior for a input field - ie. fill available space like other block level elements do?
Thanks!

An <input>'s width is generated from its size attribute. The default size is what's driving the auto width.
You could try width:100% as illustrated in my example below.
Doesn't fill width:
<form action='' method='post' style='width:200px;background:khaki'>
<input style='width:auto' />
</form>
Fills width:
<form action='' method='post' style='width:200px;background:khaki'>
<input style='width:100%' />
</form>
Smaller size, smaller width:
<form action='' method='post' style='width:200px;background:khaki'>
<input size='5' />
</form>
UPDATE
Here's the best I could do after a few minutes. It's 1px off in FF, Chrome, and Safari, and perfect in IE. (The problem is #^&* IE applies borders differently than everyone else so it's not consistent.)
<div style='padding:30px;width:200px;background:red'>
<form action='' method='post' style='width:200px;background:blue;padding:3px'>
<input size='' style='width:100%;margin:-3px;border:2px inset #eee' />
<br /><br />
<input size='' style='width:100%' />
</form>
</div>

"Is there a definition of exactly what width:auto does mean? The CSS
spec seems vague to me, but maybe I missed the relevant section."
No one actually answered the above part of the original poster's question.
Here's the answer:
http://www.456bereastreet.com/archive/201112/the_difference_between_widthauto_and_width100/
As long as the value of width is auto, the element can have horizontal
margin, padding and border without becoming wider than its container...
On the other hand, if you specify width:100%, the element’s total
width will be 100% of its containing block plus any horizontal margin,
padding and border... This may be what you want, but most likely it isn’t.
To visualise the difference I made an example:
http://www.456bereastreet.com/lab/width-auto/

ORIGINAL answer using Angular: Because input's width is controlled by it's size attribute, this is how I initialize an input width according to its content:
<input type="text" class="form-list-item-name" [size]="myInput.value.length" #myInput>
UPDATE for JavaScript (10/01/2022): My original answer was from the time I was studying Angular. If you need pure, Vanilla JavaScript the solution is even simpler:
<input type="text" oninput="this.size = this.value.length">
Or add an "input" event listener to your input html element and run a code like this:
const myInput = document.querySelector('input');
myInput.addEventListener('input', this.typing);
(...)
typing(e) {
e.target.setAttribute('size', e.target.value.length);
}
Obs: Depending on the browser, input may restore to its default size of something between 150px and 250px if/when size gets the 0 value. In this case, just add +1 to value.length:
<input type="text" oninput="this.size = this.value.length + 1">
OR:
typing(e) {
e.target.setAttribute('size', e.target.value.length + 1);
}

As stated in the other answer, width: auto doesn't work due to the width being generated by the input's size attribute, which cannot be set to "auto" or anything similar.
There are a few workarounds you can use to cause it to play nicely with the box model, but nothing fantastic as far as I know.
First you can set the padding in the field using percentages, making sure that the width adds up to 100%, e.g.:
input {
width: 98%;
padding: 1%;
}
Another thing you might try is using absolute positioning, with left and right set to 0. Using this markup:
<fieldset>
<input type="text" />
</fieldset>
And this CSS:
fieldset {
position: relative;
}
input {
position: absolute;
left: 0;
right: 0;
}
This absolute positioning will cause the input to fill the parent fieldset horizontally, regardless of the input's padding or margin. However a huge downside of this is that you now have to deal with the height of the fieldset, which will be 0 unless you set it. If your inputs are all the same height this will work for you, simply set the fieldset's height to whatever the input's height should be.
Other than this there are some JS solutions, but I don't like applying basic styling with JS.

It may not be exactly what you want, but my workaround is to apply the autowidth styling to a wrapper div - then set your input to 100%.

If you're willing to include a little JavaScript to solve this, you can get exact sizing. This doesn't rely on approximating width with size or ems, doesn't rely on any hardcoded element widths, and works for e.g., type="number", which don't accept a size attribute.
The trick is to get your input sized exactly like a span with the same content, by actually having an invisible span with the same content.
Put your input inside a div along with a span that mirrors the input's value. Give both the input and the span the same styling, give the input 100% width, then hide the span and absolute-position the input to sit on top of the span.
This way, the container (and thus the input) are automatically sized by the visual appearance of the content of the invisible span.
https://codepen.io/spiffytech/pen/abwWRqo
<div id="relative-parent">
<span id="size-calibration"></span>
<input id="autosized-input" />
</div>
<style>
#relative-parent {
position: relative;
/* Have some width if the input is empty */
min-width: 1em;
/* Adjust size to match the span */
width: min-content;
}
#size-calibration {
visibility: hidden;
/* Prevent the span from wrapping the text when input value has multiple words, or collapsing multiple spaces into one */
white-space: pre;
}
#autosized-input {
position: absolute;
left: 0;
width: 100%;
}
#size-calibration, #autosized-input {
/* Normalize styles that the browser sets differently between spans and inputs.
Ideally, use a "CSS reset" here. */
font-family: "Arial";
padding: 0;
/* Demonstrate that this works for input with custom styles */
font-size: 24px;
}
</style>
<script>
function updateSize() {
const span = document.getElementById('size-calibration');
const input = document.getElementById('autosized-input')
span.innerText = input.value;
}
document.addEventListener('DOMContentLoaded', () => {
const input = document.getElementById('autosized-input');
input.oninput = updateSize;
// Provide some initial content
input.value = "I'm sized exactly right!"
updateSize();
})
</script>

After tried methods all above and failed, I workaround by modifying   width property in style by unit em:
tgt.style.width = `${(tgt.value.length + 1) / 2}em`

The only option I can think of is using width:100%. If you want to have a padding on the input field too, than just place a container label around it, move the formatting to that label instead, while also specify the padding to the label. Input fields are rigid.

Answer 1 - "response" gave a nice answer/link for it. To put it in short, "auto" is the default, so it is like removing any changes in the width of an element
Answer 2 - use width: 100% instead. It will fill the 100% of the parent container, in this case, the "form".

Using JQuery
$(document).on('input', '.input-fit-width', (e) => {
$(e.currentTarget).attr('size',e.currentTarget.value.length);
})

Nowdays, flex or grid makes it much easier , it overrides default style/behaviors of https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input#size which has a default value set at 20 see : https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input#size
Giving you 2 plain CSS options without requiring JavaScript nor setting width to 100% and deal with box-sizing.
flex/flex-grow
<form style='background:red;display:flex;'>
<input type='text' style='background:green; flex-grow:1'>
</form>
grid
<form style='background:red;display:grid;'>
<input type='text' style='background:green;'>
</form>

Jquery way of adjusting size of input automatically.
In general:
$('#my_input_id').width( ($('#my_input_id').val().length) + "ch" );
On text input:
$(document).on("input", '#my_input_id', function () {
$(this).width( ($(this).val().length) + "ch" );
});

I think the simplest solution is to set parent element's width:
form{
width: 100%!important;
}

Related

How to check if 2 elements displayed on the same row?

Assuming I have 2 elements on a responsive design like this:
<div id="container">
<div class="first"></div>
<div class="second"></div>
</div>
both of them with style contains:
width: auto;
display: inline-block;
float: left;
And because I'm expecting different screen sizes to view page, so, according to screen size, sometimes they will be rendered/displayed on the same row, and sometimes they will not!, the second DIV will be moved to a separate row.
So, I'm wondering, how can I check if they are on the same line with JavaScript?
Thank you
"on the same line" would require inline elements or floating block elements of the exact same height. DIVs are block elements by default. So either use <span> tags instead of <div>, or add display: inline-block;to the CSS rule of those DIVs
ADDITION after EDIT OF QUESTION:
width: auto for a <div> means 100% of the parent element (in this case full width). As I wrote: If you have blocks, use display: inline-block; in their CSS. If you want them to have the same height, put them into a common container DIV (which you already have) and apply the following CSS:
#container {
display: table;
}
.first, .second {
display: table-cell;
width: 50%;
}
Aha (edited question), Javascript: Well, read out the DIV widths, add them and compare the result to the (read-out) container width.
You can use the element bounding boxes and check for overlap:
var rect1 = $('.first')[0].getBoundingClientRect();
var rect2 = $('.second')[0].getBoundingClientRect();
var overlaps = rect1.top <= rect2.bottom && rect2.top <= rect1.bottom;
This checks for any overlap which will probably be sufficient for your use. I used jQuery to get the elements but you can use pure js in the same way, it would just be a bit more verbose.
There is no concept of line on a page. You can check the x and y position of any element in the window and then decide if that meets whatever criteria you have for "on the same line".
By default, a div is the full width of a window so the two divs inside your container in this HTML:
<div id="container">
<div class="first"></div>
<div class="second"></div>
</div>
will be one above the other unless there is some other CSS you have not disclosed that controls the layout to allow them to be in the same row. If they are indeed width: auto and don't have any other layout rules affecting this, then they will each be full width and thus first will be above second in the layout stream. They would never be "on the same line" by any typical definition of that phrase.
Feel free to try it out here: https://jsfiddle.net/jfriend00/y0k7hLr8/ by resizing the right pane to any width you want. In all cases, the first will stay on top of the second.
If, on the other hand, you allow the div elements to have a different type of layout such as let them be display: inline-block and define a width for them, then the layout engine will fit as many on a given row as possible like here: https://jsfiddle.net/jfriend00/229rs97p/
Something tells me display: flex might help you in this. Read https://css-tricks.com/snippets/css/a-guide-to-flexbox/ for more info.

Changing position of Google Places Autocomplete result box

On a page I'm working on, the results of the Google Places Autocomplete is showing up 70px below where it should, leaving a gap between the search box and the beginning of the results container.
The height of the gap happens to be the exact height of Chrome's autofill feature, so I'm suspicious that the Autocomplete library is for some reason taking that height into account when calculating the position, even though I've managed to disable that feature on my search box.
I'm able to fix the problem by overriding the value of the top attribute of the .pac-container class (replacing the value of 1234px which the API has calculated with 1164px), but I would rather have a way to do this dynamically or just based on an offset than have to hard-code that number.
Is there a way, with CSS or JavaScript/jQuery, to move the Autocomplete results container up by a certain amount?
A list of the CSS classes involved in the Autocomplete box can be found in Google's documentation.
I have tried many approaches and the best thing so far that worked for me is the good old (negative) margin.
I wanted the resulting menu to be shown on top and I did this:
<style type="text/css">
.pac-container{
margin-top: -210px;
}
</style>
Yes, you can style the Autocomplete
https://google-developers.appspot.com/maps/documentation/javascript/places-autocomplete#style_autocomplete
However, lets look at WHY the "gap" is happening.
Double check your HTML and BODY tags, see if they have margin/padding added to them
So, the way Autocomplete detects it's position is by calculating the X/Y from the top/left of the BODY tag. I had this same problem (autocomplete had a big gap between the result box and the field), I discovered that my CMS system was adding a 30px margin to the BODY tag for the admin bar, this pushed the Autocomplete box down by 30 pixals... (the real problem)
html, body{margin:0 0 0 0;}
and the autocomplete vertical position was proper and the gap was gone without any odd JS scripting...
The below snippet worked for me.
In this initially, it will remove the previous pac-container div anywhere in the DOM. Later on, It tries to find the pac-container div element inside autocomplete object and it will place pac-container the div element inside another div in this case it is "book-billing-address"
$(".pac-container").remove();
autocomplete = new google.maps.places.Autocomplete(input);
if(id_val == 'payment-address'){
setTimeout(function(){
if(autocomplete.gm_accessors_ != undefined){
var container_val = autocomplete.gm_accessors_.place.qe.gm_accessors_.input.qe.H
autocomplete.gm_accessors_.place.qe.gm_accessors_.input.qe.H.remove();
$('#book-billing-address').append(container_val);
}
}, 100);
}
and applied the following CSS, when div element moved inside book-billing-address div.
#book-billing-address .pac-container{
position: absolute !important;
left: 0px !important;
top: 36px !important;
}
please check parent element of searchbox, if parent element has margin-top, then convert it into padding-top
example code
`
.parent_element {
/* margin-top: 70px; */
padding-top: 70px;
}
</style>
<div class="parent_element">
<input type="text" class="autocomplete">
</div>`
I hope will work for you :)
It's perfectly work for me , no issue with position bug when scroll
function initAutocomplete() {
//....codes...
//....add this code just before close function...
setTimeout(function(){
$(".pac-container").prependTo("#mapMoveHere");
}, 300);
}
https://codepen.io/gmkhussain/pen/qPpryg
Add css on body tag with position: relative
It worked.

HTML / CSS inline textarea set width to same as input

I'm not sure if this is possible by CSS alone, but I'm attempting to create an inline textarea element where the text is selectable but still looks like part of a sentence. It looks fine when the number of characters are known (cols="11") by:
<p>To run nload for your device run <textarea readonly cols="11">nload p3p1</textarea> in your terminal.</p>
and the CSS:
textarea {
display: inline;
border:none;
resize: none;
}
Is there a way of doing this dynamically, without specifying the columns for each textarea in CSS? So each textarea is inline and looks unobtrusively part of a normal paragraph but selectable? Failing a CSS solution, is there a (pure) JavaScript one?
You will need to render the input text and calculate the width of the input submitted text based on that render.
A possible sollution is to copy the text into a hidden span and check it's width as illustrated:
jQuery('input').on('input', function()
{
var $this = jQuery(this);
// Create a widthSpan if we haven't already.
document.$widthSpan = document.$widthSpan || jQuery('<span style="display: none" />').appendTo(document.body);
document.$widthSpan.text($this.val());
$this.css('width', document.$widthSpan.width() + 5);
}).trigger('input');
A working fiddle: http://jsfiddle.net/687uew37/.
Do note this is an example which updates as soon as the input's content is changed. Depending on the implementation and usage if this you might need to implement changes accordingly.
You can use JavaScript to dynamically set the width of your textarea depending on the number of characters inside your textarea.
HTML:
<p>To run load for your device run <textarea class="tx" readonly>nload p3p1</textarea> in your terminal.</p>
<p>Here is another example which follows the same pattern <textarea class="tx" readonly>your textarea query you can add lots of text. </textarea>You can add a lot of other stuff after it and it will still look like part of your text.</p>
CSS:
p{
line-height:1.5em;
font-size:14px;
}
textarea {
margin-bottom:-0.3em;
border:none;
overflow:hidden;
height:14px;
display:inline;
white-space: nowrap;
}
Jquery:
$(document).ready(function(){
$('textarea').each(function(){
//Width of a character:
var chars = 8;
//Find out how many characters are in the text area:
var txLength = $(this).val().length;
//Calculate the width:
var txWidth = chars * txLength;
//Set the width:
$(this).css({'width':txWidth,'resize':'none'});
});
});
You start by taking each textarea one at the time. The idea is that you already have a font-family predefined and you know the average width of the characters in your font-family. You can find your font-family average character width online or you can estimate if you don't know it (I took a guess here).
In this case the variable chars holds the average width value of the character. You then compute the desired textarea width by multiplying the number of characters with the average character width and insert that in your CSS using jQuery's .css() function.
Working fiddle here: http://jsfiddle.net/ys2Lfrt8/5/
Drawbacks: Not responsive but can be fixed using #media-queries

align div next to input

I'm using Jorn Zaefferer's Autocomplete query plugin, http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/ and I wanted to add a button that will load all the elements the same as combobox.
So, I created a method that puts a div with image as background next to an input text:
var createDownArrow = function (input, request, options) {
var defaults = {
downArrowClass: 'autocomplete_DownArrow'
};
options = $.extend({}, defaults, options);
var offset = $(input).offset();
var width = typeof options.width == 'string' || options.width > 0 ? options.width : $(input).width();
var element = $('<div/>').addClass(options.downArrowClass).appendTo(document.body).
css({ position: 'absolute', top: offset.top, left: offset.left + width}).click(function () {
if (request && typeof request == 'function') {
request();
}
});
};
the input text has the following css:
border: 1px solid #888888;
height:15px;
font-weight: normal;
font-size: 12px;
font-family: Arial (Hebrew);
padding:0px;
margin:0xp;
this is the div css:
background-image:url(drop.jpg);
background-position:top right;
height:17px;
width:17px;
cursor:pointer;
and using this function on the input in the html:
<br /><br /><br /><br />
<input type="text" id="test" />
I get the result:
Which you can see is not the desire result.
How can I align the div next to the input? (I am using direction:rtl)
try enclosing in label tag
<label for="in"><img src=" " /><input name="in" /></label>
Write up your example that statically includes the arrow at all times in the html. When that works, replace the arrow's html by javascript that can generate it, and you'll be fine.
In more detail, I think you've got a problematic approach; you should use the right tool for the right job. So while it's possible to do what you want by manual positioning, you really don't want to be getting into this quagmire: Javascript is a poor tool for this. You probably can't get around using some javascript, but your life will be much easier if you do as much as possible in HTML+CSS - tools explicitly made for layout. In particular, that means making your arrow button statically first, and then adding exactly the html that works to the DOM-tree, rather that trying to manually control layout by computing width+height+position of the input; which you're almost certainly going to get wrong (not to mention when things get tricky, e.g. with overflow:scroll and the like).
Oh, and you could get rid of the <br/> tags and simply make the input display:block with a margin-top.
One possible CSS approach would be to follow the button by width-0 span (inline element) containing a position absolute (don't affect layout) block that shows whatever you want. E.g.: http://jsfiddle.net/emn13/nvY2F/
To get this to work as a plugin, you'd write javascript to create the span and div in the html; preferably the css would be in a linked stylesheet, but you could use inline styles too, of course. The CSS transitions are just for fun, of course.
In order to solve this, I canceled the absolute position and added display:inline-block to the div. Then I just inserted in before the input and thats all.

Auto fit CSS attribute to textarea

I am working on web application.
I wanted to apply auto height to textarea using CSS, dont want to use any script, jquery plugin and other stuff.
After applying class ( i.e. style property ) to textarea, it should automatically increase it's height not width as per content present it in.
In this case width should be fixed i.e. width: 98%; (In my case) only height needs to grow. So scroll bars should exist for text area.
I simply needed one CSS so that after applying to textarea, it should be auto grow like <DIV>.
Please folks do sugggest, is this possible using CSS. If this is not possible, then m okey if i get javascript statments to acheives my requirement.
Thanks,
Pravin
It's sort of semi-doable in html/CSS. There are, however, the usual caveats of browser support and, since it uses html5's contenteditable, it requires a fairly modern browser.
That said, the following works (in Chrome/Ubuntu 10.04):
<div id="wrap">
<div id="editThis" contenteditable>
</div>
</div>
With the following CSS:
div#editThis {
min-height: 4em;
height: auto;
width: 50%;
margin: 0 auto;
}
div#editThis:hover,
div#editThis:focus {
border: 1px solid #000;
}
Demo posted at jsbin
If you're only displaying text in a textarea and not using it to get more content input from the user then consider using a div and styling it to look like a textarea.
the other thing i have seen is an auto expanding textarea that grown in height as you type.
see here: http://james.padolsey.com/javascript/jquery-plugin-autoresize/
This is not possible with pure CSS, you will need to use JavaScript

Categories