0

I'm trying to make a table with 2 cells in a row with the second one containing a 1-row textarea so that the text is aligned vertically to the same level as the text in the first cell: picture of desirable result I've noticed that the CSS that worked well enough for FF fails in Chrome (actually, it also depends on the browser zoom level) and I need a consistent way to implement this.

To give an MCVE, I've created this html:

td, td textarea {
 font-family: serif;
 font-size: 15px;
}
table, tr, td, textarea {
 border: none;
}
td {
 padding-left: 0.5em;
 padding-right: 0.5em;
}
<table><tbody><tr>
    <td>text</td>
    <td><textarea>editable text</textarea></td>
</tr></tbody></table>

<script>
// in the real case, this code is inside a handler of the input event
// which is meant to adjust height when the number of lines is changed
var txt = document.querySelector('textarea');
txt.style.height = '1px';
txt.style.height = txt.scrollHeight+'px';
</script>

As you can see, it doesn't quite work as desired but there's also not that much CSS so various paddings are browser-dependent. Now, here's what I can think of to "fix" this: specify vertical padding and vertical-align for cells, remove padding-top for textarea.. And the following snippet works well for me in a separate html:

td, td textarea {
 font-family: serif;
 font-size: 15px;
}
table, tr, td, textarea {
 border: none;
}
td {
 padding: 0 0.5em;
 vertical-align: middle;
}
textarea {
 padding: 0;
}
<table><tbody><tr>
    <td>text</td>
    <td><textarea>editable text</textarea></td>
</tr></tbody></table>

<script>
// in the real case, this code is inside a handler of the input event
// which is meant to adjust height when the number of lines is changed
var txt = document.querySelector('textarea');
txt.style.height = '1px';
txt.style.height = txt.scrollHeight+'px';
</script>

..but it doesn't work in my initial context and also it doesn't work inside SO snippet! Right, setting display: block for textarea fixes this in SO snippet:

td, td textarea {
 font-family: serif;
 font-size: 15px;
}
table, tr, td, textarea {
 border: none;
}
td {
 padding: 0 0.5em;
 vertical-align: middle;
}
textarea {
 padding: 0;
 display: block;
}
<table><tbody><tr>
    <td>text</td>
    <td><textarea>editable text</textarea></td>
</tr></tbody></table>

<script>
// in the real case, this code is inside a handler of the input event
// which is meant to adjust height when the number of lines is changed
var txt = document.querySelector('textarea');
txt.style.height = '1px';
txt.style.height = txt.scrollHeight+'px';
</script>

But still! This gives perfect alignment here at SO (and vertical "padding" is same on top and on bottom):

enter image description here

but in my original context it is not that good:

enter image description here

I'm puzzled, what else can I be missing?

YakovL
  • 7,557
  • 12
  • 62
  • 102

1 Answers1

0

Ok, writing this up helped me to concentrate on what I have tried and what I haven't. After several iterations (that you can see above) I've made another screenshot and edited text in textarea for that. Height of textarea got adjusted.. and that's all: the only missing piece was the height of textarea should be equal to its scrollHeight, after that the alignment is perfect:

enter image description here

Horay!

PS in fact, since my textarea doesn't have border, the vertical-align: middle; bit and nullifying vertical padding of cells are not necessary once the height is adjusted.

PPS Better yet: instead of nullifying padding (I'm using coloring background on hover so zero padding doesn't look nice), the input handler can be improved to take padding into account: my initial handler was

var adjustHeightToContent = function()
{
    var defaultHeight = 10;
    var maxHeight = 150;
    jQuery(this).height(defaultHeight); // needed to descrease the height
    jQuery(this).height(Math.min(this.scrollHeight , maxHeight));
};
jQuery('.dataEditor').on('input',adjustHeightToContent);

but using this suggestion we can go instead:

var adjustHeightToContent = function()
{
    var defaultHeight = 10,
        maxHeight = 150;
    // take padding into account:
    var computedStyle = window.getComputedStyle(this, null),
        paddingTop = computedStyle.getPropertyValue('padding-top'),
        paddingBottom = computedStyle.getPropertyValue('padding-bottom'),
        padding = parseFloat(paddingTop) + parseFloat(paddingBottom);

    jQuery(this).height(defaultHeight); // needed to descrease the height
    var effectiveHeight = this.scrollHeight - padding;
    jQuery(this).height(Math.min(effectiveHeight, maxHeight));
};

and with this, non-zero padding can be used as well.

YakovL
  • 7,557
  • 12
  • 62
  • 102