“Recreating the button” in GWT

On 3 Februari 2009 Google launched their new “custom buttons” in Gmail. The idea and creation process behind these buttons were described in the blog post Recreating the button at stopdesign.com, who were part of the process to develop these buttons. The buttons were designed for the following reason:

The buttons are designed to look very similar to basic HTML input buttons. But they can handle multiple interactions with one basic design. The buttons we’re using are imageless, and they’re created entirely using HTML and CSS, plus some JavaScript to manage the behavior. They’re also easily skinnable with a few lines of CSS, which was a key factor now that Gmail has themes.

Unfortunately, as with many UI widgets created by Google, these are not made publicly available via their GWT framework. Therefor I decided to recreate the button in GWT. I’ll describe some of the JavaScript and CSS issue I faced and how these were solved. If you want to go straight to the button and demo here are the relevant links: download, demo. Javadoc: Button and ButtonBar

Example of using the button in GWT

Design

The Button widget has been designed to look as close as possible to the look and feel of the Google button (read: pixel perfect). To make the usage of button easy it has same class interface as the PushButton widget from the GWT library, this makes it easy to replace existing buttons with the new Button widget. Additional there are several methods to easily change the color, size or text/button ratio. For the color I added a method that based on a hue and saturation value calculates all colors needed. This makes it easy to change the color of the button.

The button is constructed with nested <div> element’s. You can easily see this when you view the button with your favorite browser code inspector tool. Eventually I ended up with one <div> element less than in the Google button, which didn’t effect the layout as far as I my tests concluded.

JavaScript and CSS issues and fixes

After the basic reverse engineering I fixed the specific browser support issues, mainly related to the inline-block support. In the process the free browser testing service browsershots.org was of great help. But service only helps you with layout issues, not if the effects and actions work correctly. The Internet Explorer Application Compatibility VPC Image make it possible to test different versions of Internet Explorer. In the end I only didn’t fix IE 6 issues yet. Here are some details regarding the major issues:

DOCTYPE

It turned out that to display the button correctly in Internet Explorer 7 you need to set a DOCTYPE. It doesn’t matter which one, you just need one. So don’t forget to set one!

display:inline-block

What is interesting about the google button, is the use of the display property value inline-block. This property can be used to position block elements horizontally without having to float them. Because browser support has been very poor and using it is was not recommended. But newer browsers do support it and it won’t be long before you can safely use this property value.

Of the major browsers, support in Internet Explorer 7 can be achieved via the hasLayout trick, used in the button widget by setting display:inline and zoom:1 instead of display:inline-block. In the cobogw library there is a method CSS#setInlineBlock that will take care of different browser implementations.

Unselectable button text

If you check the Google button you will see that’s it’s not possible to select the text. Making text unselectable is normally not considered good practice, but in this case a normal button is also not selectable. But making something unselectable differs almost is all browsers. In the cobogw library there is a method CSS#setSelectable to take care of different browsers.

A small related issue is with Opera. In Opera when a user selects an element with a tab index it gets a different background color. For Opera 9.5 and later this can be removed via the CSS3 pseudo element ::selection. However, I didn’t find any way to set this via JavaScript, which means you need to set this in your own CSS file. This is documented in the Button JavaDoc.

Fire click event

A <button> element triggers a click event in case the user hits the space bar or the return key. However, a <div> element doesn’t have this behavior so programmatically a click event must triggered when the user hits one of those keys. It turns out this is also browser specific. IE does support the JavaScript method click() on the <div>. In the other browsers you need to do somewhat more. In short, you need to create a MouseEvents and call the dispatchEvent method on the <div> element with the a click event object.

For most other use cases it should not be needed to fire events that are normally only triggered by user interaction. If you find yourself doing such and are not creating ‘low’ level widgets like buttons you probably should reconsider your code. A method fireClickEvent that takes care of different browser implementations is available in the cobowg library to fire a mouse click event.

This entry was posted in gwt, widget and tagged , . Bookmark the permalink.

8 Responses to “Recreating the button” in GWT

  1. Thomas Broyer says:

    As far as “setting a DOCTYPE” is concerned, you should really read:
    http://msdn.microsoft.com/en-us/library/bb250395.aspx#cssenhancements_topic2
    and
    http://hsivonen.iki.fi/doctype/#handling

    It *does* matter which DOCTYPE you use. If you want some guidelines on the choice of a DOCTYPE to activate a given mode, see:
    http://hsivonen.iki.fi/doctype/#sniffing

  2. Nick says:

    This was a very cool write up and example.
    Google fires me up as well with some of the features/widgets they’ll come up with and then keep them private.

  3. SamMax says:

    Wow! They look very similar with google’s Thank you!

  4. Joe says:

    This is amazing. Well done.

  5. Hilbrand says:

    @Thomas,

    That’s very useful information. I was somewhat sloppy on the DOCTYPE part. It certainly does matter what DOCTYPE you use. So people so determine (and read the sites mentioned) what works best for them.

    What I should have mentioned is that the Button class doesn’t work correctly in “quirks mode” in IE7 (and in IE6, but that’s another story, because it doesn’t work in IE6 in other modes either…) and that you need to specify another mode than “quircks mode” (which is what you get when you among others leave the DOCTYPE out of your page).

  6. Jerome says:

    Thank you very much. The Button widgets you created look and work great on the example page. They are amazing.
    Unfortunately when I implement the Button or ButtonBar widget in my existing project, I only get a regular looking button (default browser button style). Any idea what I could be doing wrong? (Note: DOCTYPE is defined, I’ve added the same CSS attributes than the ones defined in the example page).

  7. Jerome says:

    I resolved my problem…..
    When using the ButtonBar, make sure that your import section does’nt include somewhere the original GWT Button widget “import com.google.gwt.user.client.ui.Button;”

    Thanks again for the great widgets.

  8. Thanks, dude!

    That’s amazing piece of code. I was almost on writing this but fortunatly i’ve found your blog. Thank you very much!