Force an input to display inline with automatic width - css

I have a readonly HTML <input> that I'd like to display just like a <span>.
However, applying the following CSS causes it to stay as inline-block in Chrome v34 on Windows.
input[readonly] {
background:none; color:inherit; /* normal colors */
border:0; margin:0; padding:0; /* no special sizing */
width:auto; display:inline; /* try to make it inline and auto-size */
}
Demo: http://jsfiddle.net/52vL3/
How can I make the input stop requiring an explicit size, using CSS?

There are a bunch of things happening here, but inline-block is not your problem. This can be shown by adding
-webkit-appearance: none
You'll now have an inline input that's still not resizing itself. The problem is that inputs don't automatically size themselves to their value, even when inline.
If it were a type="text" input, you could set size="2" (default is 20) on the input and it would resize it accordingly (albeit with a bit of extra space).
Unfortunately, type="number" ignores the size attribute.
So, you could try using a pattern instead of type="number"
<input value="64" type="text" pattern="\d*" size="2" readonly>
You may want to increase the size when you make it editable though, because the input won't automatically expand to fit wider values.
See this question for an approach to auto-sizing an input as you type.
Or, depending on how you're using it, you might like to consider <span contenteditable="true">

Related

CSS to wrap contents in stylized container?

I have a stylesheet that specifies a style for <LABEL>.
But some <LABEL>s are special: Currently I inline style them like this:
<LABEL style="text-align:right; line-height:15pt">
<div style="padding-right:20px">My Label Text</div>
</LABEL>
I suspect there's a way to specify a CSS class, perhaps called rightlabel, to render the preceding using something simple like this:
<LABEL class="rightlabel">My Label Text</LABEL>
What would the correct way be to do that? I.e., is there a way to define rightlabel in CSS to produce the overridden <LABEL> while automatically wrapping its children in a padded child container (because the style doesn't work correctly unless that is done, and it doesn't seem proper to depend on the coder to implement two elements to get the style right)?
Amendment: I can get most of the way there using a child selector – as shown in this fiddle with this CSS:
.rightLabel {text-align: right}
.rightLabel > * {padding-right: 20px}
But I can't find a way to apply the padding to the label contents without explicitly wrapping the contents in some container. I.e., the above CSS works correctly on
<LABEL class="rightLabel">
<div>This is what we wanted!</div>
</LABEL>
but not on
<LABEL class="rightLabel">Why am I not padded?</LABEL>
Is it possible to apply a style to the <LABEL> contents without explicitly coding them inside another HTML element (child)?
Define your styles like so:
<style>
.rightLabel
{
text-align:right;
}
.rightLabel div
{
padding-right:20px;
}
</style>
Update to updated question: you can't add a div using CSS, you'll need JavaScript. You can add pseudo elements using :before and :after.
Here's a fiddle https://jsfiddle.net/c3h9a2b9/1/
.rightLabel:before {
display:block;
content:' ';
width:20px;
float:right;
}
This fakes the padding by using the :before or :after pseudo element on your label. It needs a display of block (inline-block would also do) and some dimensions, the width here being 20px (the "padding" that you need) and floated in the direction you want padding....
If I understood correctly your question the answer is this CSS:
label{
//Your general label style
}
label.rightlabel{
text-align: right;
line-height: 15pt;
}
label.rightlabel div{
padding-right: 20px;
}
With this HTML should act as you wish
<label>a normal label</label>
</label class="right label"><div>the special label</div></label>
This works because more specific CSS overrides less specific one by default :)

Position :before pseudoclass in-between parent and child CSS

(Basically I'm trying to style a text field beyond its normal capabilities, including filler text which doesn't interact directly with the cursor.)
I wonder if it's possible to position (using z-index if possible) a :before element behind the child elements of the container element, but in front of the container background. (Maybe you'd understand in a bit)
HTML:
<div class="field" data-title="John">
<input type="text" name="firstname">
</div>
CSS:
.field{
background-color:white;
border:1px solid gray;
}
.field:before{
content:attr(data-title);
}
input[type="text"]{
background-color:transparent;
border:none;
outline:none;
}
This displays correctly:
However, I'm concerned because you cannot focus the text field if your cursor is over the :before content (in this case, is the word "John").
I do understand that the :before can be styled with pointer-events:none, however, the "pointer-events" tag is not yet entirely cross-browser compatible.
Hopefully I made myself clear. Any help at all would be very much appreciated. Thank you for your time.

Alignment of <input type="submit"> in Chrome changes if value=""

I have a simple HTML form with only two elements -- a text box and a submit button -- that need to be horizontally aligned.
The button has a background image, and I would like to set its value="".
In Safari and Firefox, the alignment is maintained if I set the line-height on the elements.
In Chrome, however, this is not enough. I have to set the value=" " (note the space), or give it another text value. Otherwise, the elements shift.
This is the HTML and css
<form>
<input type="text" id="email" class="textBox" />
<input type="submit" id="submitSubscribe" class="submitButton" value="" />
</form>
.submitButton{
width:30px;
line-height:30px;
background:url('');
}
.textBox{
line-height:30px;
}
#email{
width:146px;
}
Here is my jsfiddle:
http://jsfiddle.net/EmCQJ/5/
Does anybody know why Chrome calculates the alignment differently with the text in the value attribute than when the value is blank? Leaving that space in the value feels like a hack solution to me, but I've tried all the obvious css fixes and still can't get it working. Any input is greatly appreciated. Thanks!
This should do it: http://jsfiddle.net/EmCQJ/38/
The key here was
vertical-align: text-top;
It seems the input-text and input-image elements have different baselines (the default setting for vertical-align) but the same text-top line.
You should manually set the margin, padding, and border of the input-text element because different browsers have different defaults. When doing this, remember height is the size of the element less the margin, padding, and border so if you want a total height of 30px make sure to subtract 1px from the top and 1px from the bottom giving you a CSS height of 28px.

width:auto for <input> fields

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

CSS padding on input element breaks ie6 ie7

After a bunch of googling and searching, I can't seem to find any info on this.
The problem:
In ie6 and ie7, the text entered into a styled input is displayed "cut in half", with some of the text clipped off in the middle and the remainder hidden underneath the bottom of the input.
Picture the word FOOBAR inside the input. You would only be able to see the top-half of the word, with the bottom-half hidden by the bottom-part of the input.
The input element:
<input name="email" size="40" type="text" id="email" class="input" />
The styling:
input, select, textarea {
font: 13px Verdana, Geneva, sans-serif;
}
input.input, textarea.textarea {
padding: 10px;
}
When I adjust the padding between 0-2px, everything is fine. Increasing the padding pushes the text further south.
All other mainstream browsers work fine, just ie6 and ie7 are giving me headaches.
There are no other styles in play.
This only happens in Quirks mode, so fix your doctype.
It looks like IE isn't able to change the height of an input in quirks mode, causing the padding to just move the text out of view due to the top padding.

Resources