Chapter Fourteen. Buttons

Buttons are ubiquitous in websites and application interfaces—to submit data and initiate actions in toolbars, forms, and navigation controls—and designers frequently customize their appearance. We typically design custom-styled buttons for projects that must:

• Match the branding and presentation of the overall site or application

• Use color, texture, and dimension to convey button hierarchy—for instance, visually distinguishing primary and secondary actions

• Include icons to make them more uniquely identifiable and easier to scan, or compact, icon-only buttons, like those used in text-editing toolbars

• Introduce custom interaction states to provide better feedback, like a pressed state for touch-screen buttons

Virtually any HTML element can be made to look and behave like a button with a bit of CSS and JavaScript—for example, Google’s Gmail web application uses div-based buttons throughout the interface. But relying on JavaScript events to handle form submission is risky; when scripting is disabled or not fully supported, all related functionality is rendered unusable.

For foundation markup that reliably works everywhere, we need to start with either an input element with a type of button, or the button element. Which of these elements to choose depends on the styling and functionality needs of the particular situation.

In this chapter, we’ll walk through two target designs and discuss the criteria for deciding when to use input or button elements in the foundation markup, and then review how to transform them into richly formatted buttons in the enhanced experience.

X-ray perspective

Let’s say we have a social networking site with a page that lists friend invitations, which can be accepted or ignored. Our design introduces a visual hierarchy for the buttons that emphasizes the positive Add Friend action over the negative Ignore action. Let’s consider two possible target designs that illustrate the key factors that will help us decide which native element to use: a simpler one with buttons styled distinctly to show a difference in emphasis:

Figure 14-1 The target button design has a visual style that distinguishes primary and secondary buttons.

image

...or a more complex design that calls for icons inside each button and mixed font weights for the text formatting (the Add John is bold):

Figure 14-2 Target design with complex button formatting

image

There are two native elements we could use to code the foundation markup for our custom buttons: an input element with its type attribute set to submit, reset, or image, or a button element. Of the two markup options, the input element has been part of the HTML specification longer than button (input was included in the HTML3 specification circa 1996, vs. the button’s inclusion in the HTML4 specification around late 1999), and tends to work correctly in a broader range of older and mobile browsers. Because it’s universally functional, an input is our first choice for creating buttons in the foundation markup.

Designers have traditionally avoided using standard input-based buttons when a design calls for a styled button; there’s a common misperception that the input can’t be styled reliably with CSS. We tested this idea and were surprised to find it’s possible to consistently style input-based buttons in all mainstream browsers (even Internet Explorer 5!) with various type styles, background images, borders, rounded corners, custom dimensions, margins, and padding.

There is, however, a key limitation with an input: this element consists of a single self-closing tag, so it can’t contain another HTML element—like an image, span, em, strong, or any other HTML tag. This prevents us from using the input for complex text formatting, layering several background images, or adding multiple icons.

The button element, by contrast, has both opening and closing tags and can contain additional HTML elements. This allows us to accommodate all the design features of our more complex target design—we can wrap the Add John text in a strong tag for emphasis and add a span tag to apply the icon. However, the button has its own drawback: since it was absent from the earliest HTML specifications, some older browsers and mobile platforms don’t recognize it, and will either fail to display the button at all or won’t properly submit the form when it’s clicked.

For this reason, we recommend that our foundation button markup always be an input, and that we use button elements only in the enhanced experience. For the first, simpler design, we’ll style the input for the enhanced experience as we would any other element; for the more complex design with formatted text and icons, we’ll “transform” the input into a button to achieve advanced formatting and retain the ability to natively submit form data.

We’ll start by reviewing how to style an input-based button. Then, we’ll walk through how to transform an input into a button element in the enhanced experience to accommodate the additional icons and text formatting of the second example.

Styling input-based buttons

We’ll construct our first design with input-based buttons and style them with CSS for both the basic and enhanced experiences. The design (as shown in Figure 14-1 above) is simple enough for this approach to work in a wide range of browsers.

To apply a visual hierarchy between the primary and secondary buttons, we’ll distinguish them in the markup with descriptive classes assigned to the input elements (btn-primary and btn-secondary) in the foundation markup. To be safe, we’ll reserve much of the visual styling, such as the light-on-dark text of the Add button, for the enhanced experience, since older browsers may support styling only the text color (and not the background image or color), which may result in unreadable text.

We can, however, show visual emphasis in the basic experience by setting the font weight of the primary button to bold. (Though this style property is generally well supported, it may be ignored by some browsers when applied to an input.) In even very primitive browsers, our hint of primary and alternate actions will be communicated in the basic experience (as shown in Figure 14-2 above).

Foundation markup and style

The foundation markup for our social networking site starts with a form tag; within the form is a fieldset that contains a legend, a paragraph with the location and count of common friends, and two submit input elements for adding and ignoring friend requests:

image

We’ll add a class to each input element to identify its role as either primary or secondary:

image

Our foundation markup now provides a usable experience on any device that supports basic HTML:

Figure 14-3 Unstyled foundation markup

image

The form is perfectly usable, but could use some visual polish, so we’ll add a few safe CSS rules to the basic style sheet.

One style property that has a big impact on look and feel is font-family. Most elements on a page inherit font-family properties from their parent elements, but form controls are often an exception; many browsers specify a monospaced font for form controls regardless of other font styles set on the page. To fix this, we’ll point our font-family rule at the body and input elements:

body, input { font-family: "Segoe UI", Arial, sans-serif; }

This simple rule makes our form look a lot better already!

Figure 14-4 Foundation markup with font style applied

image

To improve the form’s legibility, we’ll remove the fieldset’s border and adjust its margins, style the legend to be bold and green, and adjust the margins on the paragraph inside:

image

Now the form block in the basic experience looks even closer to our target design:

Figure 14-5 Foundation markup with fieldset, legend, and paragraph styles applied.

image

Finally, we’ll style the primary button with bold text and specify that the secondary button should have normal (not bold) text, to ensure a shift in visual emphasis in the basic experience:

.btn-primary { font-weight: bold; }
.btn-secondary { font-weight: normal; }

With these styles in place, the Add button takes visual precedence:

Figure 14-6 Foundation markup with bold text on the primary button for visual emphasis

image

Now that our foundation markup and styles are complete, we’ll tackle the enhanced markup and styles that are applied to the page when the browser passes the capabilities test.

Enhanced markup and style

The buttons in our target design share a number of styles, so in our enhanced style sheet we’ll write a single rule against both button selectors to apply shared styles. These rules define padding, font formatting and alignment, and set the cursor style to be the clickable hand icon over the input:

image

Note

The buttons’ font weight is inherited from the primary and secondary classes we wrote into the basic style sheet, so they don’t need to be defined again in the enhanced style sheet.

Figure 14-7 Common styles applied to the input elements

image

Tip

When setting button styles, using em units instead of pixels for properties like padding and margin, to ensure that the button (and the space it occupies) will expand and contract relative to its font size.

Older versions of Internet Explorer add extra width to input and button elements that can’t be set with padding or margin values, but there is a fix: specify a width property and set the overflow property to visible. If the button doesn’t require a specific width, you can set the value to auto:

image

To give the buttons rounded corners, we’ll apply the CSS3 border-radius property. At the time of this writing, only Mozilla- and Webkit-based browsers support the border-radius property (using vendor-specific property names), but it’s still safe to use, because browsers that don’t support it will simply display the buttons with square corners. We’ll also append the standard border-radius property specified by the W3C, so that any browsers that implement this feature in the future will show rounded corners as well (both Opera and Internet Explorer have committed to supporting this property at the time of writing):

image

Figure 14-8 Basic button styles with rounded corners

image

The primary and secondary button classes in the basic styles specify background images (green and silver, respectively), and text and border colors to match the design:

image

To help the text stand out against the background image, the text-shadow property adds a drop shadow on the button text. Like the border-radius property, text-shadow is supported by only a handful of browsers at this time (specifically, Firefox 3.5+, Safari 1.1+, and Opera 9.5+), but is harmless to include as long as the text has good contrast without the shadow.

image

Figure 14-9 Button styles applied

image

To provide good visual feedback when the user interacts with the button, a hover state is defined for each button type. Ideally, we would do this using the :hover pseudo-class, but Internet Explorer versions 6 and earlier don’t support this on elements other than anchors (a). To remedy this, we’ll use JavaScript to add and remove a hover class when the user moves the cursor onto or off of a button:

image

Figure 14-10 Secondary button hover state

image

Lastly, we’ll add font-size rules to the legend and paragraph to create appropriate visual weight for each:

legend { font-size:1.5em; }
fieldset p { font-size:1.3em; }

With these styles applied, the enhanced markup looks exactly like our target design:

Figure 14-12 Final enhanced styles

image

Enhanced hover state script

The scripting required for the input-based button is minimal: we’ll use JavaScript to apply the hover class to the buttons when the user places their cursor over a button. This approach ensures that proper hover-state feedback will be displayed in all browsers that pass the capabilities test.

To start, we’ll create two variables that capture our input elements, one each for all of the primary and secondary buttons on the page:

image

Then we’ll add the hover class by binding a function to the input’s mouseover event, and remove it using the mouseout event. As a convenience, jQuery provides a single hover method that lets you pass in functions for both the mouseover and mouseout events. The following example shows how to apply this hover-state toggle to primary buttons:

image

For secondary buttons, we’d construct a similar hover method that acts on the secondaryButtons variable, and use it to toggle the btn-secondary-hover class on and off.

Our input buttons now support the behavior and visual appearance specified in our initial target design. Next, we’ll review how buttons with more complex visual formatting can be transformed from an input into a button in the enhanced experience.

Creating buttons with complex visual formatting

Our second target design builds on the first example, with a couple of additional features: icons for the Add and Ignore action buttons, and varying font weights to emphasize a portion of the primary button text.

Figure 14-13 Target design with complex button formatting

image

In this case we can’t style the input element to match the target design, so we’ll use an input element in the foundation markup, which we know will work reliably in all browsers and devices. In the enhanced experience, we’ll run a script that replaces the input with a styled button element for a richer experience.

When swapping the input element with the button, we’ll copy all of the input element’s attributes and JavaScript events over to the button to ensure that the new element is a one-to-one match. The new button will completely replace all of the functionality of the input element, so when the script is complete, we’ll remove the input from the page entirely.

Foundation markup and style

Like the first example, we’ll start with input elements and assign primary and secondary classes, but we’ll add an additional class to each input to identify the purpose of the buttons (action-add and action-ignore). These classes will be transferred to the button elements in the enhanced experience to apply specific icons to the buttons:

image

To identify the button text that should be styled with bold, we’ll use an HMTL character as a delimiter; the script will look for this delimiter and apply the bold style to the words that precede it. A good choice for a delimiter is a punctuation mark or special character that makes sense when displayed in the basic experience and is unique enough to be detected by the script. In this button, there isn’t a visible character that would read correctly, so the best choice for a delimiter is a non-breaking space character ( ), which is invisible in the basic experience:

image

The basic styles we created for the first example also apply here, with one slight modification: we’ll add button to the font-family selector so that it inherits the correct font style:

body, input, button { font-family: "Segoe UI", Arial, sans-serif; }

With foundation markup and basic styles in place, we’ll tackle the enhanced markup and styles that are applied to the page when the browser passes the capabilities test.

Enhanced markup and style

When the browser passes the capabilities test, we’ll use JavaScript to replace each input with a button element that has the same attributes and JavaScript events:

image

Our enhancement script will remove the delimiter we inserted in the foundation markup—a non-breaking space ( )—and wrap the text that precedes it in a strong element:

image

To apply an icon, the script will insert a span element with a class of icon to the markup, before the button text:

image

As we did with the basic CSS, we’ll build upon the enhanced CSS we created to style an input to specify styles required for the enhanced button element.

In our target design, a portion of the primary button’s text is bold, while the rest is normal font weight. The btn-primary class applies a bold font-weight property to all primary buttons, so we’ll need to make an exception for this particular primary button. We’ll write a new style rule against the action-add class, specifically for the primary button in our target design; that way other primary buttons in the page will remain bold:

button.action-add { font-weight: normal; }

The input-to-button script will wrap strong tags around the emphasized text, Add John. By default, most browsers apply a bold font style to strong elements, but to ensure that the proper formatting is applied, we’ll reinforce this style with a simple rule:

button strong { font-weight: bold; }

We’ll also add styles for the icon spans that apply an inline-block property and dimension:

image

Finally, we’ll set a background image for each icon span, based on the parent element’s class:

image

Now that our CSS supports complex button formatting, we’ll move on to scripting the input-to-button conversion.

Enhanced input-to-button script

Our goal is to replace specific input elements in the foundation markup with custom-styled button elements when a browser passes the capabilities test. To start, we’ll create a buttoninputs variable to store an array of references to all of the button-like input elements on the page:

var buttoninputs = $('input.btn-primary, input.btn-secondary'),

We’ll loop through each item in the array using jQuery’s each method and replace it with a new button element, including all of the input element’s attributes and event bindings. The each method accepts an argument—a function—to execute on each item in the buttoninputs array:

image

In this function, we’ll write the logic that grabs all of the input’s attributes and events, assigns them to a new button element, and replaces the input.

First, we’ll create a variable that acts as a template for the button markup, and use the input element’s value for the button element’s text label:

image

Note

Within the function we pass to the each method, the this keyword refers to the current input element. By wrapping this in parentheses and preceding it with a dollar sign, we turn it into a jQuery object reference, which allows us to apply jQuery methods to manipulate the element. For example, the statement $(this).val(); returns the value of the input.

Next, we’ll get all of the input element’s attribute name/value pairs (nodeName and nodeValue, technically) and apply them to the new button using the setAttribute method:

image

Note

At the time of writing, jQuery’s attr method causes an error when it’s used to set the type attribute in Internet Explorer 8. To avoid a conflict with Internet Explorer, we used the native JavaScript setAttribute method rather than jQuery’s shortcut attr method; as with all native JavaScript attributes, setAttribute must reference the button variable using array notation, button[0].

Now that we’ve reassigned the input element’s attributes to the button, we’ll do the same for all JavaScript events bound to the input element. Events bound using jQuery are stored in memory via the data method, which can be used to both get and set data values. We’ll pass a single argument to that method—in this case, events—to retrieve all of the events tied to our input. And because each event, like onload or onclick, can have more than one binding, or function, associated with it, we’ll also loop through those bindings to make sure we get them all:

image

At this point, we’ve created custom buttons using the original input elements’ attributes and events. Now we can safely remove the input elements from the markup. jQuery’s replaceWith method gives us a tidy way to remove the input element and insert the new button element simultaneously:

image

We’ve now converted the inputs to button elements; next, we’ll add the text formatting (strong tags) and icon spans. We’ll reset the inner HTML of the action-add button by splitting its text at the non-breaking space character, and wrapping the first portion in a strong element:

image

Finally, we’ll add the icon span elements to all buttons using jQuery’s prepend method, which inserts HTML at the beginning of an element:

$('button').prepend('<span class="icon"></span>'),

Using the input-to-button script

The code that accompanies this book (available at www.filamentgroup/dwpe) includes a jQuery plugin that packages the principles shown in this chapter—specifically, in the second example—into a reusable script for use in your projects. To use the code, simply include all the files referenced in the button demo page, and call the inputToButton method on any input elements you’d like to convert to a button.

$('input#submitForm').inputToButton();

The inputToButton plugin will automatically transfer over any classes and events and apply hover classes to the buttons. You can safely call the inputToButton method on all input elements, as the script will make sure to not convert any non-button input types, like text, radio, or checkbox.

$('input').inputToButton();

To add the icon spans and non-breaking space-delimited text bolding (as we did for the Add button in this chapter), you can direct additional logic to look for the non-breaking space and inject the icon span:

image

Taking the button further

In addition to submitting data, buttons are commonly used in applications as toggles for settings or preferences. Toggle buttons typically have an additional “pressed” state to make it appear selected.

Toggle buttons can either act alone, as a single on/off switch, or as part of a set that allows one selection at a time. If you think this sounds similar to another kind of HTML element, you’re right—toggle buttons behave exactly like checkbox and radio button inputs.

For a detailed example of how to style checkbox and radio inputs like toggle buttons, check out Chapter 15, “Checkboxes, radio buttons, and star rating.” The code that accompanies this book also includes a demo page with toggle buttons that resemble those shown in this chapter. Check out toggle-buttons.html in the accompanying code’s checkbox-radiobutton folder.

* * *

Custom-styled buttons can deliver enhanced visual sophistication and improve the usability of a site. When creating your own buttons, keep the following rules in mind to ensure a usable experience for all:

• Start with a universally functional input element with minimal, safe styles to ensure that all users have access to key functionality.

• For simpler button designs (without text formatting or icons), use the input element for both the basic and enhanced experience, and apply enhanced styles when the capabilities test passes.

• For more complex designs, convert each input element to a button to add style and visual feedback for capable browsers and devices.

• Style the button font size and padding with ems rather than pixels to preserve text-size scaling.

• To minimize server requests, use image sprites for button backgrounds. Just be sure that the image sprite is wide enough to accommodate your longest button at an enlarged font size.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.59.180.145