Search code examples
htmlcsscss-tables

Why does adding a small image after an input box in a CSS table affect the height of the row so badly?


I'm trying to set up a form thing using CSS tables, and I'm in a really weird situation that is best described by a fiddle:

http://jsfiddle.net/GdgV4/6/

See the third row? It's height (on Chrome and Firefox anyway) is affected pretty badly by adding an image whose height is LESS than the height of the input box itself... if I remove the <img> tag however, it lines up fine. Surely the <img>, being less than the height of the input box, should slot neatly along-side it?

I'm sure it's something really simple, but any help would be appreciated.

Update: to clarify - I do not want to adjust the height of the image, it must stay the same height. What I am trying to achieve is this: if you draw 2 lines across the screen that touch the top and bottom of the input box, the image should appear within them, and I want the input box to have the same amount of spacing above and below as the other input boxes in the form. I want to achieve this WITHOUT using any positioning hacks like position: relative; top: 2px or anything.


Solution

  • Here is an example to help explain how inline images affect the overall line height of a text line.

    Consider the following HTML snippet:

    <form>
        <div class="field-wrap ex1">
            <label for="ex1">Text</label>
            <input type="text" id="ex1" name="ex1" 
                   value="Example 1.............................">
            <img src="http://placehold.it/50x32">
        </div>
        <div class="field-wrap ex2">
            <label for="ex2">Text</label>
            <input type="text" id="ex2" name="ex1" 
                   value="Example 2.............................">
            <img src="http://placehold.it/50x50">
        </div>
        <div class="field-wrap ex3">
            <label for="ex3">Text</label>
            <input type="text" id="ex3" name="ex1" 
                   value="Example 3.............................">
            <img src="http://placehold.it/50x64">
        </div>
        <div class="field-wrap ex4">
            <label for="ex4">Text</label>
            <input type="text" id="ex4" name="ex1" 
                   value="Example 4.............................">
            <img src="http://placehold.it/50x64">
        </div>
    </form>
    

    Basically, each input field has an associated label field and an img tag, all wrapped in a block element .field-wrap.

    For the CSS:

    form {
        font-size: 25px;
        line-height: 2;
        font-family: sans-serif;
    }
    .field-wrap {
        background-color: yellow;
        margin: 10px 0;
        vertical-align: middle;
    }
    .field-wrap input {
        font-size: inherit;
    }
    .field-wrap input, .field-wrap label, .field-wrap img {
        vertical-align: inherit;
    }
    .ex4.field-wrap {
        vertical-align: baseline;
    }
    

    which gives the following result:

    vertical alignment example

    In all cases, I picked a font size of 25px and made the line-height 2 times as tall as the font size.

    I also set vertical-align: middle for all the child elements (input, label and img). This is important.

    By default, the height of the input field is controlled by the font-size and any padding that may be applied. However, you can also specify the height, which in this case I set to 30px. Note that the input box has a 1px border, so the overall height is actually 32px.

    In Example 1, I chose an image with height 32px to match the height of the input box, and the vertical alignment is as nicely centered.

    In Example 2, I increase the height of the image to 50px, and the image now fits right in the parent element which has a height of 50px (due to line-height 2 times the font size of 25px).

    In Example 3, I made the image 64px tall, and in this case, the parent element's height increases to accommodate the image. This is correct rendering according to the CSS specification.

    Finally, in Example 4, I set the vertical alignment to the default of baseline and in this case, the bottom of the image lines up with the bottom of the text, and this forces the parent block to be even taller to accommodate the image height and the text/input fields.

    This should give a clear illustration of how vertical alignment works.

    Other Comments:
    To get the image to center exactly, make sure that there is no transparent space around the edges, which is apparent if the image is opened in an image editing program.

    You could also wrap the image in an inline-block, specify a height, and then set the image height to 100%, which will force oddly sized images to fit to a specific height.

    See the code at jsFiddle