Like its Mac and Windows cousins, Safari for iPhone provides some of the best CSS support of all Web browsers. As you develop iPhone Web applications, you can utilize CSS to make powerful user interfaces.
Safari offers support for CSS 2.1 as well as CSS 3. However, Safari also supports some properties technically called "experimental CSS 3" that are not currently part of the World Wide Web Consortium (W3C) CSS standard but will be supported by Apple going forward. (A -webkit-
prefix is added to the names of these properties.) For a normal Web application, developers typically stay away from these experimental properties or at least do not rely on them for their application's design. However, because you know that an iPhone and iPod touch user will be using Safari/WebKit, you can safely use these more advanced styles as you create your UI.
Many would contend that the real power of CSS is not so much in the properties that you can apply but in CSS's ability to select the exact elements within a Document Object Model (DOM) that you want to work with. If you have worked with CSS before, you are probably quite familiar with the standard type, class, and ID selectors. However, Safari's support for selectors includes many new selectors that are part of the CSS3 specification. Table 5-1 lists a set of CSS selectors that Safari supports, and Table 5-2 lists the set of pseudoclasses and pseudoelements that Safari works with.
Note that the following CSS3 selectors are not supported with Safari:
Table 5-1. Safari CSS Selectors
Selector | Definition |
---|---|
| Type selector |
Class selector | |
ID selector | |
| Universal selector (all elements) |
Descendant selector | |
| Child selector |
Adjacent sibling selector | |
| Indirect adjacent selector[a] |
| |
| |
| One of many attribute value selectors[b] |
| |
[a] New to CSS3 [b] Case sensitive, even when unnecessary |
Table 5-2. Safari Pseudoclasses and Pseudoelements
Pseudoclass/ Pseudoelement | Definition |
---|---|
Unvisited link | |
Visited link | |
| Selector content uses the language code specified |
Content before an element | |
| Content before an element (new double-colon notation in CSS3)[a] |
Content after an element | |
Content after an element (new double-colon notation in CSS3)[a] | |
First letter of element | |
First letter of element (new double-colon notation in CSS3)[a] | |
First line of element | |
First line of element (new double-colon notation in CSS3)[a] | |
First child[b] | |
Root[a] | |
Negation[a] | |
Target[a] | |
Enabled state[a] | |
Disabled state[a] | |
Checked state[b] | |
[a] New to CSS3 [b] When new first child/child of type is created programmatically using JavaScript, the previous child maintains the : |
When you are styling text inside your iPhone Web applications, keep in mind three text-related styles that are important to effective UI design: -webkit-text-size-adjust
, text-overflow
, and text-shadow
. These properties are explained in this section.
When a page is rendered, Safari automatically sizes the page's text based on the width of the text block. However, by using the -webkit-text-size-adjust
property, you can override this setting. The none
option turns off auto-sizing of text:
body { -webkit-text-size-adjust: none; }
Or, you can specify a specific multiplier:
body { -webkit-text-size-adjust: 140%; }
Finally, you can set it to the default value of auto
:
body { -webkit-text-size-adjust: auto; }
Figures 5-1, 5-2, and 5-3 show the results of these three options on the same page.
For a normal Web site, -webkit-text-size-adjust: auto
is recommended for improving the readability of text. However, if you are developing an application, you will almost always want to use -webkit-text-size-adjust: none
to maintain precise control over the text sizing, particularly when you go between portrait and landscape modes.
Because the width of the viewport in Safari is either 320 (portrait) or 480 (landscape) pixels, effectively managing the physical length of dynamic text on UI elements can be tricky. This is particularly important for headings or button text in which a fixed amount of real estate is available. The best example of the need to handle text overflow is in the top toolbar that is a standard part of the iPhone application interface. By default, any content that does not fit inside the container box of the element is clipped, which can potentially lead to confusion, such as the back button example shown in Figure 5-4. Because there is not enough space to display the text iProspector
, only iProspect
is shown.
To prevent this situation from happening, you can provide a visual hint that the text has been clipped. Fortunately, the text-overflow
property enables developers to specify what they want to have done when the text runs on. The two values are ellipsis
and clip
. The ellipsis
value trims the content and adds an ellipsis character (. . .) to the end. Suppose you assign the following property to the toolbar's button and heading element:
text-overflow: ellipsis;
Now, when text overflows, an ellipsis is added, as shown in Figure 5-5.
The text-overflow
property is particularly useful for iPhone Web apps because a heading that displays fully in landscape mode may need to be clipped in the much thinner portrait mode.
The use of text-overflow
may require specifying additional CSS properties to display as intended. The following code, for example, needs to have overflow
and white-space
properties set to ensure that the text-overflow
property works:
<html> <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0;"> <style> .ellipsis { text-overflow: ellipsis; width: 200px; white-space: nowrap; overflow: hidden; } .ellipsisBroken1 { text-overflow: ellipsis; width: 200px; /* white-space: nowrap; */ overflow: hidden; } .ellipsisBroken2 { text-overflow: ellipsis; width: 200px; white-space: nowrap; /* overflow: hidden; */ } </style> <body> <div class="ellipsis"> this is a test this is a test this is a test this is a test this is a test this is a test this is a test </div> <br><br> <div class="ellipsisBroken1"> this is a test this is a test this is a test this is a test this is a test this is a test this is a test </div> <br><br> <div class="ellipsisBroken2"> this is a test this is a test this is a test this is a test this is a test this is a test this is a test </div> </body> </html>
In the iPhone UI, Apple makes subtle use of text shadows, particularly on buttons and larger heading text. Besides lending to aesthetics, text shadows are useful in making text more readable by increasing its contrast with the background.
You can add drop shadows to your text through the text-shadow
property. The basic declaration is as follows:
text-shadow: color offsetX offsetY blurRadius;
The first value is the color of the shadow. The next two give the shadow's offset position — the second value being the x-coordinate and the third being the y-coordinate. (Negative values move the shadow left and up.) The fourth parameter indicates the shadow's Gaussian blur radius. So, in the following example, a gray shadow is added 1px above the element's text with no blur:
text-shadow: #666666 0px −1px 0;
However, text shadows can be distracting and look tacky if they are too noticeable. Therefore, an rgba
(red, green, blue, alpha) color value can be used in place of a solid color value to define the transparency value of the shadow. (See the "Setting Transparencies" section later in this chapter.) Therefore, the following declaration defines a white shadow with a 0.7
alpha value (0.0
is fully transparent, whereas 1.0 is fully opaque) that is positioned 1 pixel under the element's text:
text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0;
You can quickly apply several styles to block elements to transform their appearance and go beyond ordinary CSS styles that you may have used on traditional Web sites. These include three so-called experimental properties (-webkit-border-image
, -webkit-border-radius
, and -webkit-appearance
) and a CSS3 enhancement of the background
property. These are described in this section.
The -webkit-border-image
property enables you to use an image to specify the border rather than the border-style
properties. The image appears behind the content of the element, but on top of the background. For example:
-webkit-border-image: url(image.png) 7 7 7 7;
The four numbers that follow the image URL represent the number of pixels in the image that should be used as the border. The first number indicates the height of the top (both the corners and edge) of the image used. Per CSS conventions, the remaining three numbers indicate the right, bottom, and left sides. Pixel is the default unit, although you can specify percentages.
If the image URL you provide cannot be located or the style is set to none
, border-style
properties are used instead.
Optionally, you can specify one or two keywords at the end of the declaration. These keywords determine how the images for the sides and the middle are scaled and tiled. The valid keywords are stretch
or round
. If stretch
is used as the first keyword, the top, middle, and bottom parts of the image are scaled to the same width as the element's padding box. Far less common for iPhone use, round
can also be used as the first keyword. When this setting is present, the top, middle, and bottom images are reduced in width so that a whole number of the images fits in the width of the padding box. The second keyword acts on the height of the left, middle, and right images. If both keywords are omitted, stretch stretch
is implied.
When rendered, Safari looks at the -webkit-border-image
property and divides the image based on the four numbers specified.
The -webkit-border-image
property plays an important role in creating CSS-based iPhone buttons, which is explained later in this chapter.
The -webkit-border-radius
specifies the radius of the corners of an element. Using this property, you can easily create rounded corners on your elements rather than resorting to image-based corners. For example:
-webkit-border-radius: 10px;
This declaration specifies a 10px radius for the element, which is the standard radius value for the Rounded Rectangle design for destination pages. You can also specify the radius of each corner using the following properties:
-webkit-border-top-left-radius -webkit-border-top-right-radius -webkit-border-bottom-left-radius -webkit-border-bottom-right-radius
If, for example, you wanted to create a div
with rounded top corners but square bottom corners, the style code would look like the following:
div.roundedTopBox { -webkit-border-top-left-radius: 10px; -webkit-border-top-right-radius: 10px; -webkit-border-bottom-left-radius: 0px; -webkit-border-bottom-right-radius: 0px; }
Results are shown in the text box shown in Figure 5-6.
The -webkit-appearance
property is designed to transform the appearance of an element into a variety of different controls. Safari for iPhone supports just two of the possible values: push-button
and button
. The push-button
property holds the most promise for iPhone application developers. Suppose, for example, you would like to turn a link element into a gradient push button. You could do it with an image, but -webkit-appearance: push-button
allows you to do it entirely within CSS. To demonstrate, begin with a link assigned to a class named special
:
<a href="tel:202-555-1212" class="special">Call Headquarters</a>
Then define the a.special
style:
a.special { display: block; width: 246px; font-family: Helvetica; font-size: 20px; font-weight: bold; color: #000000; text-decoration: none; text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0; text-align: center; line-height: 36px; margin: 15px auto; -webkit-border-radius:10px; -webkit-appearance: push-button; }
The display:block
and width:246px
properties give the link a wide rectangular block shape. The -webkit-appearance: push-button
property transforms the appearance to a gradient gray push button. The -webkit-border-radius
rounds the edges using the standard 10px value. Although the shape of the push button is now set, the text needs to be tweaked using not just standard text formatting properties, but also a line-height
property of 36px, which vertically centers the 20px text in the middle of the push button. If you add a simple background-color: #999999
style to the body
tag, you get the result shown in Figure 5-7.
In earlier versions of CSS, there was always a 1:1 correspondence between an element and a background image. Although that capability worked for most purposes, some page designs could not work effectively with a single background image defined. So, to get around the 1:1 limitation, designers would resort to adding extra div
tags here or there just to achieve the intended visual design.
CSS3 addresses this issue by allowing you to define multiple background images for a given element. Most browsers don't support this feature yet, but fortunately for iPhone Web application developers, Safari/WebKit does.
You define a set of background images by listing them in order after the background
property name declaration. Images are rendered with the first one declared on top, the second image behind the first, and so on. You can also specify the background-repeat
and background-position
values for each of the images. If background-color
is defined, this color is painted below all the images. For example:
div.banner { background: url(header_top.png) top left no-repeat, url(banner_main.png) top 6px no-repeat,
url(header_bottom.png) bottom left no-repeat, url(middle.png) left repeat-y; }
In this code, header_top.png
serves as the background image aligned to the top-left portion of the div
element. banner_main.png
is positioned 6px from the top, whereas header_bottom.png
is positioned at the bottom of the div
. Finally, middle.png
is treated as a repeating background.
Developers have long used rgb
to specify an RGB color value for text and backgrounds. CSS3 adds the ability to set an alpha value when specifying an RGB color with the new rgba
declaration. Using the rgba
declaration, you can add translucent color overlays without transparent PNGs or GIFs. The syntax follows:
rgba(r, g, b, alpha)
The r
, g
, and b
values are integers between 0 and 255 that represent the red, green, and blue values. alpha
is a value between 0 and 1. (0.0 is fully transparent, whereas 1.0 is fully opaque). For example, to set a red background with a 50 percent transparency, you would use the following:
background: rgba(255, 0, 0, 0.5);
Keep in mind that the alpha value in the rgba
declaration is not the same as the opacity
property. rgba
sets the opacity value only for the current element, whereas opacity
sets the value for the element and its descendants.
The following example shows five div
elements, each with a different alpha
value for the black background:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>RGBA Declaration</title> <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> <style type="text/css" media="screen"> div.colorBlock { width: 50px; height: 50px; float: left; margin-bottom: 10px; font-family: Helvetica; font-size: 20px; text-align:center; color:white; text-shadow: rgba(0,0, 0, 0.7) 0 1px 0; line-height: 46px; }
</style> </head> <body> <div style="margin: 10px 0 0 30px;"> <div class="colorBlock" style="background: rgba(0, 0, 0, 0.2);"><span >20%</span></div> <div class="colorBlock" style="background: rgba(0, 0, 0, 0.4);"><span>40%</span></div> <div class="colorBlock" style="background: rgba(0, 0, 0, 0.6);"><span>60%</span></div> <div class="colorBlock" style="background: rgba(0, 0, 0, 0.8);"><span>80%</span></div> <div class="colorBlock" style="background: rgba(0, 0, 0, 1.0) ;"><span>100%</span></div> </div> </body> </html>
Figure 5-8 shows the page in Safari.
Using -webkit-border-image
, you can create push buttons that closely emulate Apple's standard push button design. This technique, inspired by developer Matthew Krivanek, involves using a pill-shaped button image (available for download at www.wrox.com
), stretching the middle of the button image, but ensuring that the left and right sides of the button are not distorted in the process.
Begin by defining a normal link with a fullSizedButton
class:
<a href="mailto:[email protected]" class="fullSizedButton">Send to Client</a>
Next, define the a.fullSizedButton
style:
a.fullSizedButton { font-family: Helvetica; font-size: 20px; display: block; width: 246px; line-height: 46px; margin: 15px auto; text-align:center; text-decoration: none; font-weight: bold; color: #000000; text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0; border-width: 0 14px 0 14px; -webkit-border-image: url(images/whiteButton.png) 0 14 0 14; }
In the preceding code, the display
property is set to block
and the width is set to 246px, the width of the buttons Apple uses. The line-height
is set to 46px, which gives the block element the standard height and vertically centers the button text. A border-width
property sets the left and right borders to 14px and eliminates the borders for the top and bottom by defining their values as 0
.
Now that everything else is set up, look at the -webkit-border-image
property definition. In this example, 0 pixels are used from whiteButton.png
on the top and bottom. However, the first 14 pixels of the image are used for the left border of the element, whereas the 14 rightmost pixels are used for the right border. Because the whiteButton.png
image is 29 pixels in width, a 1-pixel section is used as the middle section. This middle section is then repeated over and over to fill the width of the element. Figure 5-9 shows how -webkit-border-image
divides the image.
Figure 5-10 shows the button when rendered by Safari.
Here is the full source code for this example:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Basic Button/title> <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> <style type="text/css" media="screen"> a.fullSizedButton { font-family: Helvetica; font-size: 20px; display: block; width: 246px; margin: 15px auto; text-align:center; text-decoration: none; line-height: 46px; font-weight: bold; color: #000000; text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0; border-width: 0 14px 0 14px; -webkit-border-image: url(images/whiteButton.png) 0 14 0 14; } body
{ background-color: black; } </style> </head> <body> <a href="mailto:[email protected]" class="fullSizedButton">Send to Client</a> </body> </html>
Although Safari for iPhone is closely related to its Mac and Windows counterparts, it is not identical in terms of CSS support. The latest versions of Safari for Mac and Windows support most of the newer CSS3 and experimental properties (prefixed with -webkit-
). Safari for iPhone, however, provides limited support of several properties.
The following CSS properties are not supported (or have limited support) in Mobile Safari:
In this chapter, I walked you through the details of styling your iPhone Web apps using CSS. I began by exploring the selectors that are supported by Safari on iPhone. Next, the chapter explored text styles, focusing on the issues that you'll encounter designing for the iPhone viewport, particularly text sizing and text shadows. I continued on with a discussion on styling block elements, showing how to use image-based borders, rounded corners, and transparencies to create an attractive user interface. Finally, I showed you how to create 3-D style buttons using CSS alone that emulate iPhone conventions.