Make image buttons a part of input fields

November 26, 2008

If you ever saw how products like Microsoft CRM look like you probably noticed there are input fields that have “embedded” image buttons inside them. If your clients saw that, there is a probability that they will want to have it in their applications.

Whether you agree or not, here is how you can do it easily. So easily that you will have to add just a few lines of code and enable this feature in entire application.

Download source code  View live demo

If you want to add some functionality to some input field (like adding a calendar icon that will popup some calendar), you would probably do it like on the image below.

outside_the_box  

The code could look like this:

<fieldset id="sampleForm">
    <label for="txtName">Full name</label>
    <input id="txtName" type="text" />
    <label for ="txtDOB">Date of birth</label>
    <input id="txtDOB" type="text" class="inputWithImge" />
    <img src="calendar.png" alt="Click to popup the clendar!" onclick="alert('Popup some calendar here!');" />
    <label for="txtCity">City</label>
    <input id="txtCity" type="text" />
    <label for="txtPostCode">Post code</label>
    <input id="txtPostCode" type="text" />
    <label for="txtCountry">Country</label>
    <input id="txtCountry" type="text" />
    <label for="txtBank">Bank</label>
    <input id="txtBank" type="text" class="inputWithImge" />
    <img src="bank.png" alt="Click to popup the bank window!" onclick="alert('Popup some window here!');" />
</fieldset>
<button id="btnNothingToDo">Do nothing</button>

And we could have CSS classes like these:

body { font-family: Arial, Helvetica, Sans-serif; font-size:13px;}
#sampleForm label { display:block; margin-top:10px;}
#sampleForm input[type="text"] { width:200px; border:solid 1px #000; padding:3px 0px;}
#sampleForm img { vertical-align:middle; cursor:pointer; }

However, your clients want it to be like on the image below. Image button has to be a part of an input field and everything has to be aligned.

inside_the_box

So what could you do? You can wrap input field and image button in some div and set black border to that wrapper div. You will also have to remove border form input field, and make it a little bit shorter, so that image can fit inside the wrapper div.

schema

But if you work on applications that have tens of forms, there is a probability you will have to do this tens or even hundreds of times. Insane, really.

But, remember jQuery?

You can add just one line of the code to make it work on all of your pages. Ok, here is the explanation so pay attention because this might sounds tricky.

We want to find a set of two elements (input field and image) that repeats in the fieldset and wrap it inside the div. How to find these sets? This is what jQuery will do. We’ll assign a class to each input field that we want to wrap. That class will also remove border form input field. So, here is the HTML code:

<fieldset id="sampleForm">
    <label for="txtName">Full name</label>
    <input id="txtName" type="text" />
    <label for ="txtDOB">Date of birth</label>
    <input id="txtDOB" type="text" class="inputWithImge" />
    <img src="calendar.png" alt="Click to popup the clendar!" onclick="alert('Popup some calendar here!');" />
    <label for="txtCity">City</label>
    <input id="txtCity" type="text" />
    <label for="txtPostCode">Post code</label>
    <input id="txtPostCode" type="text" />
    <label for="txtCountry">Country</label>
    <input id="txtCountry" type="text" />
    <label for="txtBank">Bank</label>
    <input id="txtBank" type="text" class="inputWithImge" />
    <img src="bank.png" alt="Click to popup the bank window!" onclick="alert('Popup some window here!');" />
</fieldset>
<button id="btnNothingToDo">Do nothing</button>

and this is what jQuery has to do:

$(document).ready(function() {
    $(".inputWithImge").each(function(){
        $(this).add($(this).next()).wrapAll('<div class="imageInputWrapper"></div>');
    });
});

All that is left to do is to add two more classes that will define styles for our wrapper div and input field that will be wrapped.

.imageInputWrapper{ width:200px; border:solid 1px #000;  }
#sampleForm input.inputWithImge { width:175px; border:none; margin-right:5px;}

Download source code  View live demo

Pretty simple, eh? Maybe. Maybe this could be done even simpler. Any ideas?

Let's discuss this on twitter.

22 Comments

  • Muhammad Mosa (November 26, 2008)

    Finally found a detailed post to explain how to do that! I love this UI feature, but never tied to implement it. Thank you Janko the detailed post.

  • Marco (November 26, 2008)

    I’m with Muhammad Mosa on this one, especially the "Click to pop-up" feature is good! Thanks for sharing & keep up the good work :) .

  • Johan (November 26, 2008)

    Why not position:relative; left:-20px; on the image and then padding-left:20px on input?

  • Johan (November 26, 2008)

    padding-right of course

  • Janko (November 26, 2008)

    Muhammad & Marco: thanks!

    Johan: Yeah, just padding-right:20px. It’s better than fixing the size in pixels. But you would only have to find the a way to align fields.

  • Thejesh Gn (November 26, 2008)

    Loved the trick. Thanks.

  • Davide Espertini (November 26, 2008)

    I Think that is a really useful technique. Good thing! Thanks Janko!

  • Johan (November 26, 2008)

    I´m not sure what you are meaning Janko. But try this:

    #sampleForm input.inputWithImge {padding-right:25px; width:175px;}
    #sampleForm img {cursor:pointer; left:-25px; position:relative; vertical-align:middle;}

    Then you don´t need any jQuery or extra markup.

    Why make it more complicated then that?

  • Calvin Froedge (November 26, 2008)

    I’ve been implementing this and a lot of other jQuery functions into my web designs recently. It really amps up the sites a lot, and we really don’t ever have to worry that someone is going to turn off javascript anymore. Who actually does that?

  • Johan (November 26, 2008)

    What happend to my last comment?

  • Janko (November 26, 2008)

    Thejesh, Davide: Thanks.

    Johan: I wasn’t online and your comment waited for moderation. At first I thought you wanted to use it with jQuery, but after I read your comment again I realized what you tried to say. Yes, that is quit simple, but I am using jQuery on my project because I have a complex logic that is determines the behavior of UI so I extracted this sample from there. And, more important, I just love using jQuery for everything. Really everything Smile

    Calvin: Agree, I also don’t care if someone turns off JavaScript. If they do that, probably more than a half of websites they visit will not work in full.

  • Max (November 27, 2008)

    Nice technique, i love reading about jquery because im still experimenting with it myself. also adding images to input fields is a nice touch.

  • MrDungX (November 27, 2008)

    Janko maybe you knew this already but this messed up in IE6.

    Also Johan’s way doesn’t even required a wrapper div. :)

  • Johan (November 27, 2008)

    But why jQuery then? Just add the wrapper div in the markup instead. Of course your webbpage will break if you turn off javascript if you´re using javascript in this way. Use javascript for stuff you can´t do without it.

    In some browsers you can´t style the input fields. So you can´t hide the borders. Some have turnd off styling for forms.

    Anyway my solution is simpler and works without extra markup, jQuery and in most browsers :)

  • Johan (November 27, 2008)

    I hope you realize that if you adding markup to the dom with javascript your page will be much slower too.

  • Janko (November 27, 2008)

    Johan, doing it with CSS is simpler of course, you don’t have to prove it.

    Why jQuery? Like I said, the applications that I develop have very complex logic and I need that wrapper div for some other functionality. I don’t want to add wrapper div in my HTML markup because I need to do it dynamically. So changing it unobtrusively with jQuery is perfect for me.

    To be honest, I don’t care if someone turns off JavaScript. It’s like you want to see website in sliverlight and you don’t want to install the sliverlight. Than it’s your problem. Anyway those are intranet apps so I don’t have to worry about it.

  • Janko (November 27, 2008)

    Max, thanks. Yes, jQuery really rocks!

    MrDungX: I guess it doesn’t work in IE6. Another reason for IE6 users to use something newer.

  • Andrew Pryde (December 7, 2008)

    I hope you realise Johan that the real beauty of using javascritpt to add the button to the from is that if the user has not got javascript enabled there will not be a button with absolutely no function in the interface.

    <a href=http://www.pryde-design.co.uk">Andrew</a>

  • Janko (December 8, 2008)

    Andrew: I agree, I really don’t see the point of NOT using JS just because someone can turn it off. Then we shouldn’t use CSS, because someone can turn it off too!?
    Many people take this as an argument in debates, but I don’t see their point. Do they create websites without a line of JS code? What about complex web applications?

  • Tony Oravet (December 9, 2008)

    Great Idea! Thanks for the tip. I think that integrating some of the images with some slick AJAX solutions will be nice too! Example: Set the calendar icon in the date field, so when clicked it pops up AJAX Date Picker or something cool like that.

    As for people turning CSS off, the basic user, who we design for is not going to be turning their css off. The only reason you need to worry about css issues with stuff like this, is when you are designing for mobile applications that do not present the web like the iPhone.

    Great post!

  • Alejandro (August 7, 2009)

    The bad side is google chrome put a yellow border when focus the input, and is visible the trick. that’s not so beauty but is a great idea :D

  • Alexander Bukev (October 15, 2009)

    Hello.

    Johan’s solution trully seems more elegant and simple than the jQuery way offered.

    Janko, take into consideration the fact that our affinities can lead us to being "Brand Slaves". This can easily worsen our productivity "just because you love one thing even though it’s obvious that another solution would be way better".

    Enough offtopic, Johan’s solution has an ugly flaw under Internet Explorer: Even in IE8, if you set right padding to an input field greater than 1em, when you start typing and reach the right end of the input field, the cursor goes on AFTER it should stop right at the padding line. Then, when you reach the end of the field itself, the text and cursor are pushed back to the padding line. Using an icon or a text link above the padding zone will cause the text go behind it as you type.
    Of course, under Firefox this bug doesn’t exist.
    This leads to the conclusion that Janko’s solution is better in this case despite adding greater overhead to the page.
    Some day, in a fully CSS compliant browsers’ world, the CSS-only solution would be better :)