How to prevent input elements from affecting a table's columns' widths? - html

When a certain user action is performed I need to add a row to a table which contains an <input> in each cell. I need the <input>s to automatically fill the available space without affecting the column width.
I need to start with this:
And end up with this:
But instead, when I insert the inputs every column stretches to a minimum of ~170px (depending on the browser):
Simplified demo: http://codepen.io/patik/pen/qZXMyL — Click the button at the bottom and note how the original column widths are not preserved once the inputs have been inserted.
I could read the column widths before inserting the inputs and then manually apply max-width to each input, however I want the column to remain fluid (that is, the columns should continue to adjust to fit the plain text data). Other rows may be added or removed to the table and I need the inputs to adjust accordingly.
As you'll see in the demo I've already tried creating a <td><div><input></div></td> structure in the hopes that the <div> would fill the column and the <input> would fill the <div>, but that doesn't seem to be the case.
I'd prefer a CSS solution (even if I need to apply inline styles when the inputs are inserted) but I'd be okay with a JavaScript solution if it's the only choice.

The <input>s must have a size attribute if you want to control their width with CSS:
<td><input size="1"></td>
The value of size doesn't matter (though it does need some value—you can't simply write <input size> and have it work). As long as the attribute is present the element seems to respect any CSS I apply to it. In this case, width: 100% does the trick.
Demo: http://codepen.io/patik/pen/JXrEGX

Try adding this to your CSS code:
input[type="text"] {
width: 100%;
box-sizing: border-box;
}
Meaning:
input[type="text"] Select only the input boxes of the type text.
width: 100% The width occupies 100% of the width available from the parent.
box-sizing: border-box Make the width also count the border.
http://codepen.io/anon/pen/xVLoYq

Related

Can't change width of table data element

I'm posting a screenshot of the element in question. You should be able to see, I am applying element-specific styling removing all margin, padding and setting the width to 0px. No matter what I do, this table data element is abnormally large. I want to significantly reduce its width, but it won't listen to me. I have the feeling this is some obscure HTML algorithm that I know nothing of but can't say. Any ideas?
Update: The answer was that HTML will make sure the table data elements take up the entire width of the table, no matter if you try to narrow individual elements (so in essence, it was some weird HTML algorithm or functionality). That said, I will accept the answer below because it is so thorough it should cover the other possible issues people may run into.
There is some obscurity to how the width of a table cell (<td>) is defined, as official documentation is unclear and allows some behavior to be defined by the browser. But here are a few characteristics that appear stable across the spectrum of browsers.
Managing the Width of HTML Table Cells <td>
Table with Single Cell
In a table that consists of a single cell – in other words, a table with one column and one row – where the width hasn't been explicitly defined in the <table> element, the width can be controlled directly by the <td> element.
This won't work (the td rule will be ignored):
table { width: 100%;}
td {width: 300px;}
The width: 300px fails because the <table> element has a defined width.
However, this will work:
/* table { width: 100%;} */
td {width: 300px;}
DEMO
Table Column with Multiple Cells
To set the width of a table cell in a column with multiple cells the entire column must be adjusted. Any widths assigned to the individual <td>s will be ignored. Simply adjust the width of the table to adjust the width of the <td>s in the column.
DEMO
Table with Multiple Columns and Multiple Rows
To set the width of a table with multiple columns and rows, the Table Column Element (<col>) is ideal because it targets individual columns.
DEMO
The problem described in the question involves a table cell that won't accept a shorter width assignment. The first realization here is that the table cell by default expands to fill 100% of the column width allotted (learn more about <td> default width). The way to reduce the width of this cell is described above.
HOWEVER, I suspect that in some cases the person wanting to reduce the width of a table cell is actually trying to reduce the width of the content inside the cell (like an image or a form input). In these cases, adjusting the table may be unnecessary. All that would be needed is to adjust the width of the content itself, or its container (div, span, figure, etc.).
In this image, the width of the table cells are at 100%, but the width of the input fields vary.
DEMO
colspan
If in fact the need is to reduce the width of a single cell within a column of multiple cells, then you may want to consider the colspan attribute. With colspan, columns can me merged making cells wider. Cells without colspan assigned will be shorter, and appear even shorter when their adjacent cells are hidden.
In this image, display: none has been applied to the bottom right cell of this 2-column table.
DEMO
So, in the case of your table cell that won't budge, consider adjusting the width of the <table> element (if it's a single column table), assign and adjust a <col> element (if it's a multi-column table), adjust the width of the content directly (if that's the only element you want adjusted), or use colspan.
Sorry I can't be more specific about the exact solution in your case. No code was provided for review. But hopefully one of these methods helps you out.

How to make an html table deliberately exceed the width of its container?

Demo
I'm trying to make a table that contains a horizontal scrollbar where the width of any individual row can be set to whatever I want. I've tried two different approaches to achieve this and they each give me problems:
If I assign a width to my table that is larger than its containing div and apply overflow-x: scroll, the table exceeds the width of its container. However, I have no control over the width of my cells. Setting td{width:'x'px;} doesn't do anything.
If instead I apply table-layout:fixed to the table, I can now adjust the width of individual rows but cannot exceed the width of the table container.
How do I get the best of both worlds? I need the table to exceed the width of the container in order to get the scrollbar, while also being able to set the width of different rows to any value.
HTML table and table cells work this way by design - cells will always be confined to within the width of the table. If you want to size them like you do to normal inline-block elements, you can either:
Use <div class="table"> and <div class="cell"> to markup and style tables.
OR
Change the display mode in CSS. {display: block} for tables, {display: inline-block} for cells. You'd probably also need to fiddle with the display modes of other elements like <tr>, <th>, <thead>, <tbody>...
A little note: just in case you are using tables as a means to layout your page content, please stop and strongly reconsider changing your approach. Tables are a nasty crutch for layout, and should really ONLY be used to display actual tabular data.
Set the position: absolute; for the element that you want to exceed it's container width. But also set position: relative; to its parent, so you can adjust the position.

Laying out input elements using display:table-cell

I'm trying to write a CSS class that allows me to sit form elements (mixed button and text inputs) in a line so that they abut. I'm using display:table on a parent, and wrapping each element in a container with display:table-cell, and it works fine except for one bug that I can't figure out a way around.
So for example, parent is control-group, the element wrappers are control-group-item, and the elements themselves are control-group-input.
.control-group
.control-group-item
.control-group-input{type: "text"}
.control-group-item
.control-group-input{type: "submit"}
CSS of this (I've normalized font size/line height/padding/browser weirdness and all form elements are inline-blocked etc.):
.control-group {
display: table;
.control-group-item {
display:table-cell;
}
gives this, which is OK:
However, I ideally need it to fill a grid column of undetermined size, rather than the browser deciding how big my elements should be. If apply width:100% on .control-group, this happens:
The orange is a background colour applied to the table cell control-group-item. The issue seems to be with the 'submit' input: the submit stays the size it should be but browsers universally add extra space next to it within the table cell. So if I apply width:100% to each .control-group-input, I get this:
Which is OK, but stretches the ‘submit’ button. I can live with that, but is there any way to get it like the second image (but without the random space) using my current approach, or should I sack that off & try something different?
Edit I do not know the sizes of the inputs in advance: I can't set a width on them, which effectively rules out most inline block/float methods. I ideally need IE 8/9 support, which is why display:table was tried.
Edit 2: here are versions on Codepen: http://codepen.io/DanielCouper/pen/knDmC
After rewriting the code there, I realise my question is: how is the width of the table cells being calculated? It's specifically the cell with the submit button that has the extra space. The extra space seems random.
Here's a working version in codepen: http://codepen.io/mkleene/pen/ldqDH
The summary is that you need to remove the width: 100% on the submit button and then give the second table cell element width: 100%. You also need to make the textbox take up its entire parent with a 100% width.
You also need to make sure that the table element is using an auto table layout.
nm, spoke too soon. Thought I had solved it, hadn't, was getting effects from some other CSS.

Two Column Input with Flex Box Model

I am trying to create an input mechanism using the flex box model. I know it's not supported by all browsers, but that doesn't matter in this case. It really only needs to work on web-kit browsers.
I am trying to build a nice two column layout without needing to use specific widths. I have the flex property set to one on both the label and the input. However, as you can see, when the label element gets long, it messes up the width of the input that is next to it.
I want both label and input to be the same width down the column, but I want them to grow and shrink as the size of the window/device changes.
Is there a way to do this without having to set a width on either of the elements?
Update
I can set a max-width on the label elements to 5% and I basically get the desired effect. However, I'm still wondering if there is a way to do this without setting any width and using purely the flex box?
Here is a working jsFiddle.
The example you provided doesn't have columns at all, just the appearance that there are columns. Without actual columns you will have to set widths to make these 3 unreleated blocks look they are joined in some way.
You should be using the new CSS3 Flexible Box syntax, which is now 'flex' rather than 'box'. See the spec: http://www.w3.org/TR/css3-flexbox/ With this you can set the elements to have a <grow> <shrink> <default width> of 1 1 50%, so they will grow and shrink at the same rate and will each take up 50% of available width (you can adjust this or make it 60/40 or whatever).
Example JSFiddle: http://jsfiddle.net/XTa98/4/
Otherwise, if you want actual columns so that you don't have to set widths, you need to wrap all of the labels in their own "column" div and all of the inputs in their own "column" div.
JSFiddle: http://jsfiddle.net/XTa98/5/
This has actual columns and no widths set, but it does not degrade gracefully anymore since the elements are not in their own rows. To alleviate this you could always provide text-overflow: ellipses to truncate the text.
In any case, you have a trade-off. If you want the appearance of columns without actually using columns, you will need to set some type of width. Otherwise, you can use real columns but the elements are no longer joined as rows and you will need to account for the overflow when shrinking the browser width.
You don't have to wrap the elements in column divs to avoid setting widths. Just set each label and input to flex:1, and you'll get them dividing up the width equally. However, this is effectively just the same as setting each to be 50% wide, in this case, so I'm not sure what advantage it really has.

how to change the width on an html cell

I have a html table which I would like to control the sizes of the cell manually. I am getting confused about how its supposed to work.
First of all, there is a css attribute "table-layout" which is supposed to control whether or not the cell size is automatically set to the largest content in the column or to a fixed size. I tried setting the css width for the td elements using both table-layout=auto and =fixed, and both times the content shrinked from its original size. The problem is that it didn't shrink to the size I wanted to using either value for table-layout.
Here is my css code:
table {table-layout:fixed;}
tr, td {border-style:solid;
border-width:2px;}
.coursename{width:50px;}
.startdate {width:5px;}
.isbn{width:10px;}
.author {width:20px;}
.booktitle{width:10px;}
Second of all, what exactly are the rules for a automatic table layout? If the content of all the table cells together go past the size of the page, are there certain columns which will shrink first? Will they shrink at all?
One idea that might help is, if you have a link in each cell for example, set the link like this:
a { display: block; width: 30px; }
Do this for every cell in the table row and you will have table cells with fixed widths. Provided that you fixed the width of the table as well... :)
I am still unsure what your problem is, but you could try
{table-layout:inherit;}
This should get the size from the parent element.
Also, you could insert the css element into the html and have it override any other elements by preceding it with a !
{class="!width:300px;"}
Hope this helps.