Header

Dijit has a tremendous wealth of high quality and feature-rich form elements providing key functionality including validation, time calculation, spinner controls, calendars, and much more. Furthermore, Dijit gives you a set of themes to choose from: Tundra, Soria, Noir, and Nihilo.

Widgets that make it into the official set of Dijits have a very high bar to reach in terms of feature requirements, including full accessibility support, and they still have to work in the dreaded Internet Explorer 6. As a result, using the widgets “out of the box” does not always provide the desired visual result. The functionality that these form elements achieve requires some complexity in their structure. It is rare that you will be happy with the default layout, especially when you’ve received a design specification that requests that the form needs to “look like this”.

In this post, I’ll show you how to set up your form with the proper style sheets, and do some minimalist CSS targeting to adjust each form so they’ll all be the proper size. The result will be a style sheet base that you can use and modify to create custom Dijit forms.

Below is an image of the form style that is our target:

FinalForm

I chose each of these form elements on purpose—they each have a unique structure that makes them display in different sizes and also makes them difficult to style.

First, set up your HTML page with a reference to Dojo, insert your requires statements, and the HTML form. For brevity, and because it’s pretty standard, I’m not including that code here. The link to the actual HTML is provided at the end of the post.

Now for the style sheets. We know we need the “base” sheets, dojo.css, which resets standard HTML elements to something consistent across browsers, and dijit.css because we are… well, we’re using Dijits!

Which style sheets to include for our individual widgets can sometimes be tricky. We don’t want to use dijit/themes/tundra/tundra.css because that imports all of the Dijit style sheets. Fortunately, it’s really not difficult to determine which style sheets we need, as they are laid out in the same directory structure as the widgets. We are using the Tundra theme, so we start in dijit/themes/tundra, and we are using dijit.form, so we look in the form folder. The only file that matches our widgets is Button.css, so we include that – and we also include Common.css, which contains much of the styling for forms. The Calendar.css is not in form, it’s above that in tundra, since technically, the form element isn’t using the style sheet, the calendar widget that pops up is. The result is a standard set of style sheets that handles most form widgets:

<link href="dojotoolkit/dojo/resources/dojo.css" rel="stylesheet" />
<link href="dojotoolkit/dijit/themes/dijit.css" rel="stylesheet" />
<link href="dojotoolkit/dijit/themes/tundra/form/Button.css" rel="stylesheet" />
<link href="dojotoolkit/dijit/themes/tundra/Calendar.css" rel="stylesheet" />
<link href="dojotoolkit/dijit/themes/tundra/form/Common.css" rel="stylesheet" />

If you included everything correctly, you should now be able to view the page and see the default layout of our widgets:

FormDefault

Note I’m using line breaks between some of the elements for formatting purposes, or they would all be in line. Another important thing to note: spinner widgets and drop-down widgets have buttons in them—so even if you don’t have a button in your page, you need to include the Button.css file, or you’ll pull your hair out wondering where the little arrows are.

Now that we have our widgets inserted and functional, we need to style them. Create a new style sheet, called form.css and link that to the page. Make sure to use a link tag and not an @import so that you can use ReCSS.

Our goal is to have the form to look like the image near the top of this page. We want the top six elements to be roughly 300 pixels (it will end up closer to 325, but we are going for uniformity over accuracy), the next three widgets to fit on one line, and the buttons to be on the next line and about 150 pixels wide. We need some space in between the elements and we also want to use some padding to give the text some breathing room. The padding is the tricky part, since increasing the padding adds to the width (this doesn’t sound right to me, but I didn’t write the CSS box model recommendation).

We need to specifically target the form elements to override the Dijit CSS, but we want to avoid any drastic, generic targeting of HTML elements like: .tundra .dijit input, as this will inevitably bring unwanted results somewhere down the line. You will note in the HTML, I’ve used the class myField for each of the HTML form elements. When Dojo scans the page for dojoType attributes for which to create widgets, it reads in the classes that you set and applies them to the root node of the newly parsed widget, along with the classes that Dijit uses to make the widgets display properly. This is where Firebug comes in very handy, as it shows you exactly what the final class names are of our widgets:

FBClassnames

The full class name of the ValidationTextBox is: dijit dijitReset dijitInlineTable dijitLeft myField dijitTextBox. At first, seeing myField stuck in the middle of the class chain may be unexpected. It would seem that having it at the end or even the beginning would make more sense. However, they are applied in a logical order, and in fact, makes for more succinct targeting: myField dijitTextBox will override Dijit! I also sniffed out the other widgets, and with a little trial and error, came up with our padding target:

.myField.dijitTextBox,						
.myField.dijitSpinner .dijitInputField,		
.myField.dijitTextBox.dijitTimeTextBox,		
.dijitTextArea.myField				
{
	padding:5px;
}

There’s a total of seven different widgets, but we only need four target classes. Since Dijit widgets share a common structure, the first target covers TextBox, ValidationTextBox, and DateBox. Things won’t always be this easy, but it’s a good start. Looking at the next image, we can see that the padding has been applied uniformly. However, the extra height has messed up the spinner buttons:

FormPadding

Again Firebug comes in handy in order to fix the button height. Upon inspection we see that the buttons are held in a div a few levels deep:

FBSpinner

Through more trial and error, I discovered that the height of this div was being controlled by the line-height property. I was able to access that div as a relatively direct target:

.myField .dijitSpinnerButtonContainer
{
	line-height:23px;
}

I decided to keep the width and margin target together, and separate from the padding target. As mentioned earlier, the padding adds to the width, and in the case of the spinner widgets, we can’t apply the padding to the outer-most div, because that will add padding around the buttons. We are going to apply it to an inner div, but in doing so we don’t maintain the same width as the other widgets. This is because the width of that inner div is captured (by the outer div) and in this case, the padding doesn’t add to the width, it subtracts from the content. (I know. It sounds like homework). So the spinners will need their own width targets. The result now looks like this:

.tundra .myField.dijitTextBox,			 
.tundra .myField.dijitSpinner,			
.myField.dijitTextBox.dijitTimeTextBox,
.tundra .dijitTextArea.myField
{
	width:311px;
	margin:5px 0 0 0;
}

.tundra .myField.dijitSpinner
{
	width:321px;
}

.myField.dijitTextBox,						
.myField.dijitSpinner .dijitInputField,		
.myField.dijitTextBox.dijitTimeTextBox,		
.tundra .dijitTextArea.myField
{
	padding:5px;
}

.myField .dijitSpinnerButtonContainer
{
	line-height:23px;
}

In case you’re wondering why I chose 311 and 321 as widths, it just turned out that those were the numbers that worked out for the three inline boxes, which are set at 100 pixels each (plus margins). The inline boxes have the .myField class, so they use all of the settings above, and I’ve added a .third class (because the width is in thirds) so that their widths can be targeted:

.tundra .myField.third.dijitSpinner,
.tundra .myField.third.dijitTextBox.dijitTimeTextBox
{
	width:100px;
}

Finally, we can size our buttons, which is really quite easy. I’ve added the .myButton class, and a .save class so the Save Form button can be slightly different than the Cancel button (including a tweak to the margin because the edges didn’t quite line up). The -2px right margin is because Dijit buttons line up differently than the input elements:

.myButton.dijitButton .dijitButtonNode
{
	width:151px;
	margin:3px 0px 0px -2px;
	line-height:30px;
}

.myButton.dijitButton.save .dijitButtonNode
{
	margin-left:-1px;
	font-weight:bold;
}

And we’re done! No we’re not. We have to look at it in Internet Explorer. Hey, maybe we’ll get lucky and everything will work, right?

FormIE6

Ah, the best laid plans. But, it’s not actually as bad as it looks. The reason every other width is wrong is because Internet Explorer 6 is so bad at what it is we are trying to do here—use class names to target specific HTML elements. Surprisingly, all it took was several !important statements to get the browser to listen to me (!important sure looks funny to a JavaScript engineer — it looks like “not important”. But I didn’t write that part of the CSS recommendation either).

That fixed the widths, but there is still the extra padding. What is happening here, is the .myField.dijitSpinner .dijitInputField 5px padding is being inherited by the INPUT element, and the div that contains buttons, even though it is a block float, is inheriting the line-height and padding from the INPUT. It’s the typical Internet Explorer hairball, but I did get it to work. I zeroed out the top padding on the spinner container (the left padding didn’t break anything), and changed the line-height to get my vertical spacing. The following is the key fix:

.dj_ie6 .dijitInputLayoutContainer{
	padding:0px 0px 0px 5px;
}
.dj_ie6 .dijitInputLayoutContainer .dijitInputField input{
	padding:0px;
	line-height:22px;
	overflow-y:visible;
}

You’ll notice that the first class name in the targets above is .dj_ie6. This is an excellent Dojo feature for designers that avoids the need for CSS hacks. Browser information is inserted as a class in the root <html> tag, so targeting browsers is as simple as writing another style definition.

After getting the code to work in Internet Explorer 6, I did a follow-up in Internet Explorer 7 to make sure everything still looked good there. A quick look at Safari showed that it sizes a few things the same way Internet Explorer does, so I added a few tweaks.

The demo can be seen here. You can view the source there, or you can look at the text-based HTML source code here. And of course, here is the link to the CSS base styles that you may download, modify, and build upon to make styling Dijit form elements easier than ever.