Fixing the Hover event on the iPad/iPhone/iPod

In truth it’s not a fix as the iPad doesn’t have the ability to hover.

Apple has developed extra events to replace hover on it’s mobile touch devices. I’ve recently been working a lot on the iPad and came across the problem of hovered navigation not showing up. It’s a css :hover event that fires through a CSS selector on an <a> element with no href attribute.

To emulate the hover we simply add an event listener to the element we want to have a hover event. In jQuery we do this (make sure you insert it into document.ready):

//ipad and iphone fix
if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i))) {
    $(".menu li a").click(function(){
        //we just need to attach a click event listener to provoke iPhone/iPod/iPad's hover event

That should enable the element to be touched, and stimulate and iPad hover event.

If you’re having problems getting hovered elements to fire you could also try using touchstart or touchend which is probably a better method depending on what you’re trying to accomplish:

if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i))) {
    $(".menu li a").bind('touchstart', function(){
        console.log("touch started");

    $(".menu li a").bind('touchend', function(){
        console.log("touch ended");



Posted in Uncategorized | Leave a comment

CSS3 only Native iPhone App. No images!

My challenge to myself today was to create the native look of an iPhone application using only CSS. No images. I did it. When developing for the iPhone, one only has to consider a single browser. This made the challenge somewhat easy.  The fun part was creating the page background, buttons and navigation bar without the use of image. Linear gradients came to the rescue.  Now that Safari 5 supports inset shadows, the buttons were a cinch.  Check it out (on iPhone or Safari 5 only)!

And, since I like to share, here are the important parts of the code:

        background-image: -webkit-gradient(linear, 0% 0%, 0% 50%, from(rgba(176, 188, 205, 1)), to(rgba(129, 149, 175, 1)));
 	padding: 7px 10px;
	background-color: rgb(109, 132, 162);
	border-bottom-color:1px solid rgb(45, 54, 66);
	border-top:1px solid rgb(109, 132, 162);
	display: block;
	height: 31px;
	line-height: 30px;
	display: block;
	border-bottom: 1px solid #2C3542;
	border-top: 1px solid #CDD5DF;

#theBodyBackgroundImage {
      background-image: -webkit-gradient(linear, left top, right top, from(#C5CCD4), to(#CBD2D8), color-stop(0.6, #C5CCD4), color-stop(0.6, #CBD2D8));
     -webkit-background-size:7px 7px;
     background-repeat: repeat;

Feel free to right click on the iframe above and look at the code. For detailed explanations of everything… you may have to wait for my book. The page on it’s own is here, but is only decent on iPhone or Safari 5 (and perhaps chrome).


Posted in Uncategorized | 2 Comments

Web Development for the iPhone: Targeting the iPhone Safari browser

Developing for the iPhone

Also check out Creating native looking iPhone web apps with CSS3 (no images). That works on the iPhone and Safari 5 only. Also see CSS, XHTML and JS support in the iPhone. It’s way more relevant than this article, which is about v1.

  • The Safari iPhone user agent string is:Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+
    (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3
  • Platform string: (iPhone; U; CPU like Mac OS X; en)
  • Version string: Version/3.0 Mobile/1A543a Safari/419.3

To target the iPhone with CSS, use:

<!--[if !IE]>–>
<link media=”only screen and (max-device-width: 480px)”
    href=”iPhone.css” type=”text/css” rel=”stylesheet” />

The logic of this is that only browsers that understand screen understand only, and of these, only the iphone has a max-device-width of 480px. The reason for the anti-IE comments is that some versions of IE render CSS regadless of media type declarations.

To target the iPhone server-side with PHP you can use:

if (stripos($_SERVER['HTTP_USER_AGENT'], ‘iPhone’)) {}

:hover pseudoclass on the iPhone

Please see hover pseudoclass for the iPhone to learn how to simulate hover effects on the iphone

iPhone Viewport Orientation

The iPhone supports both landscape and portrait views. You can specify CSS based on viewport orientation which you determine via javascript and update the orient attribute of the body element. Target the browser with body[orient="landscape"] or body[orient="portrait"]

iPhone ViewPort Orientation JavaScript

The following javascript snippet detects and sets the iPhone’s viewport orientation by evaluating the innerWidth property of the window object and setting the orient attribute of the body element at regular intervals:

var updateLayout = function() {
  if (window.innerWidth != currentWidth) {
    currentWidth = window.innerWidth;
    var orient = (currentWidth == 320) ? "profile" : "landscape";
    document.body.setAttribute("orient", orient);
    window.scrollTo(0, 1);

setInterval(updateLayout, 500);

Hiding the iPhone toolbar

With one line of JavaScript you can hide the big toolbar: window.scrollTo(0, 1); . Include this line of code to your snippet of detecting the phone’s orientation, as the toolbar will reappear when the orientation is changed. Remove it from the snippet above if you want the toolbar to show.

iPhone Viewport Meta Tag

The viewport meta tag properties include width, height, initial-scale, user-scalable, minimum-scale and maximum-scale. The height is calculated based on the width and aspect ratio. The initial-scale is the scale to render when the page first loads; with the default to fit the screen. Unless user scalable is set to no, th user can change the scale through pinching and double tapping of the iPhone.

Property Default Value Minimum Value Maximum Value
width 980 200 10000
height based on aspect ratio 223 10000
inital-scale fit to screen minimum-scale maximum-scale
user-scalable yes no yes
minimum-scale 0.25 > 0 10
maximum-scale 1.6 >0 10


<meta name="viewport" content="initial-scale=2.3, user-scalable=no" />
<meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />

The iPhone automatically adjusts font size for readability. This feature can be overridden with -webkit-text-size-adjust. The values for -webkit-text-size-adjust are none (default) | auto | %value.

Note that if you have a web page designed for the desktop that is wider than 980px, you will always have scrolling on the iPhone. The solution? For example, if your the site is 1060px wide, iPhone’s Safari only scales up to 980px: this will cause a small amount of zooming. In this scenario, the simple fix of <meta name="viewport" content="width=1060" /> will fix it all.

Comparisons of Safari on the desktop versus the iPhone.

Safari on iPhone supports:

  • Safari supports cookies on both
  • Safari on iPhone allows up to 8 user initiated browser pages to be open at once.
  • Default user preference is set to block pop-up windows.
  • Safari on iPhone supports many MIME types and rich media, including PDF and media file types
  • Images: Safari supports .gif, .jpg, .png, and .tiff
  • Fonts: The iPhone comes with American Typewriter, Arial, Arial Rounded MT Bold, Courier, Courier New,Georgia, Helvetica, Helvetica New, Marker Felt, Times New Roman, Trebuchet MS, Verdana, and Zapfino; so that’s what Safari on the iPhone supports.
  • Other than the :hover pseudoclass which isn’t supported on the iPhone since mouseover effects aren’t supported, Safari on the iPhone supports CSS1, CSS2 and several selectors and attributes of CSS3. If you do want to include a hover pseudo class, check out: hover pseudoclass for the iPhone.

Safari on iPhone does not support:

  • Events: mouseover and mouseout, including :hover styles and tool tips, (but it does support onclick and event listeners). Safari on the iPhone does not support the document events of onkeydown, onkeypress and onkeyup, the form-field events of ondblclick, onmouseenter, onmouseleave, onmousemove, and onSelect, and the window events of onresize and onScroll. This is not an exhaustive list, so test your event handlers before listening to me.
  • window.showModalDialog()
  • Plug-ins: Flash or Java, and plug-in installations. Do not ask users to download Flash.
  • File-size: Non-streaming files of over 10MB. CSS, JavaScript and HTML files are limited to 10MB per file. JavaScript is limited to 5 seconds of execution time. Safari for the iPhone does support gzip compression, so compress!
  • The iPhone does not support gifs, png or tiffs over 8 MB and jpgs over 128 MB (but does support larger streaming media files).
  • You can use iFrames, but avoid framesets.

Other iPhone Safari features

Phone numbers are automatically converted to phone links. You should convert them instead of letting Safari control it for you.

<a href="tel:4155551212">415.555.1212</a>.


Posted in Uncategorized | Leave a comment

iPhone CSS—tips for building iPhone websites

iPhone CSS—tips for building iPhone websites

With the rapid rise in mobile browsers, it has probably never been more important to ensure your sites can be handled on these platforms. By far one of the most popular such browsers is Mobile Safari on the iPhone—this is one of the easiest browsers to develop for: it runs on Webkit (meaning a lot of rich CSS3 support) and it’s only ever on one resolution and on one OS.

N.B. This article addresses iPhone development and iPhone development only. There is no reason why you cannot or should not develop for other mobile devices and platforms, Apple or otherwise. This just happens to be an iPhone only post.

The practical upshot of this is that you need to do no cross-browser testing, and can use all the CSS3 you like. This post will show you some of the basics of developing and designing websites for the iPhone and Mobile Safari.

To start

The first thing to remember when developing a site to be displayed on an iPhone is that it is very similar to designing a print stylesheet. You need to linearise everything. Make sure you have one column and everything is read in one line—straight from top to bottom. This will also put your markup writing skills to the test.

Some people don’t agree with browser sniffing, but you need to detect the iPhone somehow.

This first bit of code is a PHP browser sniffing snippet, the actual CSS we’ll use is not brought through via any server side code, we’ll use some CSS media queries for that. What we’ll use this code for is serving the markup with an iPhone specific meta tag and to shorten the current page’s title.

  $browser = strpos($_SERVER['HTTP_USER_AGENT'],"iPhone");
    if ($browser == true){
    $browser = 'iphone';

What the above code does is sees if the user agent contains any instance of ‘iPhone’ using the strpos PHP function. Place this piece of code at the very top of your header include, before any other markup. In order to action something if the browser is an iPhone, simply use the following bit of PHP logic in the place you want it to be initiated:

<?php if($browser == 'iphone'){ ?>DO THIS<?php } ?>

We want people to save your site to their home screen…

Now, to put that snippet to use. We want to do two things with this little piece of PHP.

Saving to the homescreen—shortening the page title

An iPhone screenshot of the CSS Wizardry home screen icon

First off, we’d like users to be able to save a link to your site on their home screen, this is simple enough, they simply need to select to do so from within the browser. However, if you look at the title of my home page alone, it’s quite long: CSS Wizardry—CSS, Web Standards, Typography, and Grids by Harry Roberts. This would never fit underneath an icon without being shortened, so we need to serve a different title to the iPhone only. To achieve this we us the PHP snippet like so:

<?php if($browser == 'iphone'){ ?>
  <title>Short iPhone only title</title>
<?php }else{ ?>
  <title>Regular title</title>
<?php } ?>

Now, both when browsing and saving your site to their home screen, a user will only ever see the shortened version.

The home screen icon

Actually making the icon is very simple. All you need to do is upload a 57×57px icon (usually a larger version of your favicon) to your server root. The icon must be named apple-touch-icon.png, and the iPhone will sort the rest out. See my icon.

Stopping user pinch-zooming

The second use for the PHP snippet is to serve the iPhone a meta tag which disables the user pinch-zoom that Mobile Safari offers:

<?php if($browser == 'iphone'){ ?>
  <meta name="viewport"
  minimum-scale=1.0, maximum-scale=1.0" />
<?php } ?>

This means that, once we’ve linearised the content and sorted the font sizing, the user will only ever have to traverse down your page, much like a native app.

Beginning styling

Some developers prefer to redirect iPhone users to a totally different version of the site—we won’t be doing that.

We could use the PHP snippet to serve the iPhone a whole new stylesheet, or even send the user to a whole new site, rather like Twitter does ( However, there’s a simpler way to do it using some CSS media queries. The advantage of this is that you’re simply reusing old content and pre-written markup, and only ever using one CSS file.

The first thing you need to do is make sure the HTML link element that points to your main stylesheet does not have a media attribute:

<link rel="stylesheet" type="text/css" href="/path/to/style.css" />

Next, we’re going to use Quick Tip #15 that I wrote on my Quick Tips page. This means that we can just add our iPhone styles directly onto the end of the main stylesheet, and inherit all the styles set for desktop viewing:

/*--- Main CSS here ---*/

@media screen and (max-device-width: 480px){
/*--- iPhone only CSS here ---*/

Now any CSS before the media query will be used across all platforms, but anything between the query will be used by any screen media with a maximum screen size of 480px (i.e. an iPhone).

Things to remember

There are a few key things to remember when developing CSS for the iPhone:

  • Avoid explicit absolute widths—where possible you should use percentage widths.
  • Linearise everything—where possible, remove all floats. We want no content side-by-side unnecessarily.

The first thing to do is to set the -webkit proprietary CSS -webkit-text-size-adjust on the body which will resize the text for you, meaning you shouldn’t have to touch any font sizes yourself. Also, if your body copy is set in a sans font such as Arial, now is your chance to use some Helvetica—for normal sites, Helvetica should not be used as body copy as it renders hideously on a PC. Take advantage of the fact that you can guarantee its presence and quality on an iPhone. Change your font-family:

/*--- Main CSS here ---*/

@media screen and (max-device-width: 480px){
  font-family:Helvetica, Arial, Verdana, sans-serif;

Above, I also added a small padding to make sure nothing touches the edge of the browser. All wrapper and content divs from here on in should be set to width:100%; making them the whole width of the screen, minus 10px.


Now, as all layouts differ I am going to assume a similar one to mine, a simple two column set up with a logo and menu in the header. If your layout is different I am sure you can quite easily retrofit it. As I mentioned before, remove all stylistic floats and set all widths to 100%. If you are using divs sensibly (i.e. for large bodies of content and not for nav items) this code should see you right for linearising the content:

@media screen and (max-device-width: 480px){

That will force all divs to rest one on top of the other, full width and in order. You have begun linearising all your content.

The navigation

If you have a navigation menu in which all the items are floated and made horizontal, insert the following:

@media screen and (max-device-width: 480px){
#nav,#nav li{
  margin:0 0 20px 0!important;
  border:1px solid #ccc;
#nav li{
#nav li a{

A screenshot of the CSS Wizardry navigation menu on an iPhone

This then will give you a vertical navigation menu which has a 100% width and the actual links themselves have a larger hit area (applied via display:block;), meaning that it’s prominent at the top of each page and easier for users to select single items.


As images inherently have a set pixel width (i.e. their own width) there is a high chance that they will break out of the wrapper area (as a lot of images will be above 480px wide). To combat this simply add the following:

@media screen and (max-device-width: 480px){
#nav,#nav li{...}

Other than elements very specific to my site, that is pretty much all the CSS I use to quickly size and linearise my content. Any elements specific to your own site will obviously need considering on a case-by-case basis, but if you remember to not set absolute widths and to always linearise your content then it should be a doddle. Oh and it’s a great time to use some guaranteed CSS3.

View a screenshot of an entire page of CSS Wizardry on an iPhone.


Posted in Uncategorized | Leave a comment

Put Your Content in My Pocket

by Craig Hockenberry

Unless you’ve been hiding in a cave with Osama bin Laden, you know that Apple is selling an iPhone and that it’s a hit. Apple is well on its way to selling ten million mobile Internet devices by the end of 2008. Besides being a great phone, the iPhone also includes a sophisticated new Safari browser. This version is touted as “the most advanced web browser on a portable device” and from what I’ve seen, it deserves this accolade.

So what does this mean for you? Millions of visitors accessing your content on a small display with very high resolution. At some point in the near future, you’re going to want to take a look at your current site design to make sure that it looks good and works well on this new device and its Mobile Safari browser.

(Note: For the remainder of this article, I’ll refer to this new browser as Mobile Safari to avoid confusion with its desktop sibling.)

In this first of two articles on bringing your content to the iPhone, I’ll explain what your options are and give you some guidance for tuning your site and making changes that enhance your users’ experience. In the second part of this series, I’ll examine some of the pitfalls and problems with this new web development environment.

While these articles are specifically targeted at the iPhone, many of the ideas and concepts I’m presenting can be useful and effective with other mobile devices. The processing power of these devices will continue to increase, bringing an end to the “dumbed down” mobile web, and it’s likely that the iPhone is just the beginning of an exciting new chapter in the storied life of HTML.

Time to clean up

The iPhone developers did a really smart thing—they designed the iPhone so that you really don’t need to do anything with your site for it to display correctly. So why am I writing this article? Well, you don’t really need to bathe periodically, either. But dealing with a clean person is much more palatable than one who hasn’t touched a bar of soap for several months. So it is with the iPhone: clean up a few things and your visitors will love you for it.

The first thing you’ll want to do is check your site for compatibility. After that, you can begin to make some simple changes that adapt your content to the iPhone. Finally, you may wish to make a version of your site that is targeted directly at the iPhone: a site fully optimized for the device.

Keep in mind that, like most things on the web, adding support for the iPhone is an evolutionary endeavor: you don’t need to completely change your site overnight. Many of these changes can be done incrementally without adversely affecting the other parts of your site.


First, you’ll want to make sure that your site is accessible by the iPhone. As I said earlier, it’s likely that you won’t need to do much—for the most part, compatibility just happens.

If you’ve been using web standards to develop your site, you’ll find that Mobile Safari works just as you’d expect. Because it uses the same Web Kit rendering engine as Safari on the desktop, it supports—with a few exceptions—the latest versions of HTML/XHTML, CSS, JavaScript, and the W3C DOM. (While Part I of this series will provide an overview of iPhone-friendly development, Part II will detail the iPhone’s deficiencies and limitations, including those exceptions.) Many of the AJAX technologies, including getElementById and XMLHttpRequest, work just like their counterparts on the desktop.

Still, there are some areas in which Mobile Safari will work differently or not at all.

Trouble with the plug-in

The omission causing the most grief for developers is that the Flash plug-in is not supported. If your site relies on Flash, all iPhone visitors will see is a blue Lego-style brick with question marks.

If you rely on Flash for navigation or multimedia, you have a few options, only one of which is truly compelling:

  • Wait, possibly in vain, for Apple to add Flash support. It is likely that Flash is not being included due to performance and battery life problems.
  • Use browser detection. Those of us who remember the halcyon days of the late 90s, and a web before standards, will know that maintaining different site versions based on browser type is more trouble than it’s worth.
  • Rely on web standards. If actions speak louder than words, note that Apple has replaced Flash with web standards on its own corporate website.

Safari for everyone

Developers on both Mac and Windows can use the Safari browser as a proxy for web development on the iPhone. For the most part, the way Safari renders content is identical to the way it’s rendered on the phone. There are some differences and caveats, which I’ll cover in the second article of this series.

Apple also has a website dedicated to web development on the iPhone. The Apple site is a great place to look for the latest news and information: if I’m having a problem with some aspect of iPhone web development, their “Web Development Guidelines” are the first place I look.

The iPhone works well with non-Flash multimedia content—a special version of the QuickTime plug-in is available using normal <object> and <embed> tags. Mobile Safari, however, behaves differently than Safari on the desktop. Embedded movies or audio only display a “play” button which opens the media in a separate window that overlays your content (referred to as “playback mode”). Additionally, you don’t have any control over this playback mode with JavaScript.

Because of these differences, Apple recommends that you add a poster image when you embed multimedia content (Line wraps marked » —Ed.):

<embed src="poster.jpg" href="" »
width="456" height="123" ...> 

The poster image is displayed until the user clicks on it to play the multimedia content. This gives a consistent user experience for both mobile and desktop visitors.


After you’ve verified that your site is compatible with the iPhone, you’ll want to focus on some simple changes that give your visitors the best possible experience.

In my opinion, you’ll need to have an iPhone for this type of development. As noted above, you can use the desktop version of Safari to preview content, but the types of changes I’m going to talk about now consist of fine-tuning that content. Unless you are holding a phone in your hand, you can’t tell whether or not your changes are effective. Remind yourself (or your boss) that the IRS would consider the iPhone a valid business expense and pick one up.

The iPhone makes prominent a little-discussed web development concept: the viewport. To deal with the problem of fitting a relatively large web page onto a small phone display, the iPhone’s developers use a viewport to select the part of the page you are viewing.

Conceptually, the viewport is like a loupe whose magnification is adjustable. When you open a page in Mobile Safari, it will render a 980-pixel-wide section of your website (Apple chose this size to accommodate the largest number of websites). The magnification of the loupe, or scaling factor, is set to shrink these 980 pixels to the iPhone’s 320-pixel-wide screen.

As you pinch or spread your fingers, you are effectively changing the magnification of the loupe (and adjusting the scaling factor). Likewise, double-tapping on a page element, such as a <div>, will adjust the scaling factor so that the viewport is optimized for viewing the element.

Thanks to a new <meta> tag recognized by the iPhone, you can control the behavior of the viewport. Imagine a site whose <body> content is exactly 808 pixels wide. By specifying the following <meta> tag, we can tell Mobile Safari how big to make the initial viewport:

<meta name="viewport" content="width=808" />

This cuts the number of pixels the iPhone has to squeeze onto its screen from 980 to 808. It may not seem like much, but when you consider that the phone’s display width is just 320 pixels, it makes a big difference. In the case of my personal site, it makes the title of each posting readable on the first view—a huge usability improvement.

You also need to be aware that the iPhone adjusts text sizes as the viewport changes. The font size increases automatically to make text as readable as possible. Sometimes this negatively affects elements that use absolute positioning or fixed sizes (especially when using pixels to specify page coordinates). If you find that this causes overflow or other unsightly results, you can easily turn it off using the following CSS rule:

-webkit-text-size-adjust: none;

Alternatively, you can use ems to specify coordinates. Sizes specified this way will increase along with the text size.

In some cases, you may want to use this feature to increase font size for important information on your page. As an example, you could increase type size in a header tag used for a weblog title with a rule like this:

  h1 {
    -webkit-text-size-adjust: 200%;

Styling for the iPhone

Before pursuing further adaptions, consider the hardware we’re dealing with—that of both the phone and our bodies. The screen on the iPhone squeezes 160 pixels into every inch of display space—and you’re using your finger to access that display. If you press your finger against the edge of a ruler, you’ll see it uses somewhere between 1/4” and 1/2” at the point of contact. That corresponds to anywhere between 40 and 80 pixels of display space.

Now, look at your web page. How many pixels are between the items on your navbar? If you answer less than 40, then you’re effectively asking your visitor to play Russian roulette: their 40-80 pixel finger isn’t going to hit your 20 pixel link effectively.

When you use iPhone specific styles, it improves accessibility for someone working on a high-density mobile device. My rule of thumb is to double important elements: bumping a font-size from 18px to 36px, for example. You’ll want to focus both on interactive elements (such as <a> and <input>) and navigational indicators (such as section titles and bread crumb trails).

So how do you use styling rules that apply only to the iPhone? The answer is to use a media query on a <link> tag. The following rule is recommended by Apple:

<link media="only screen and (max-device-width: 480px)"
    href="iPhone.css" type="text/css" rel="stylesheet" />

Other browsers will ignore iPhone.css since they have a maximum device width greater than 480px.

Integrating your site with the rest of the iWorld

As you continue to adapt your site to the iPhone, you’ll want to think about how Mobile Safari integrates with other services on the phone. It’s easy to have your page pass information to the Mail, Maps, and Phone applications—all you need to do is craft special hrefs for your links.

A link with a mailto: in the href works as expected—it opens the iPhone Mail application using the specified parameters. You can specify some HTML markup in the body, but I’d advise against it since not all mail clients will handle it correctly. For example, the following will work fine on the iPhone (Line wraps marked » —Ed.):

<a href=" »
<b>love</b> %26lt;html%26gt; mail!">Hi!</a>

And create a message that looks like this:

Subject: Sarcasm

I love <html> mail!

However, most other mail clients will create a message with a body that looks like this:

I <b>love</b> &lt;html&gt; mail!

Mobile Safari handles links to Google Maps differently than other browsers, too. It checks to see if a link href begins with “” and will automatically load the remaining part of the URL into the Maps application instead of a new web page. The normal ?q=location and ?saddr=start&daddr=destination map queries will be handed by Maps from that point on. Note that since you’re switching applications, the user will have to click the Home button, then the Safari icon to return to your web page from the Maps application. Be judicious when using map links as this can be a disruptive context switch for the user—in most cases it would be wise to provide a map preview on the link so the user can get basic directions without loading the interactive Maps.

The sexiest links ever

Now to the newest and most interesting linking feature on the iPhone: clicking on a link to make a call.

Say you have the following hCard microformat on your contact page:

<div id="hcard-Ernestine" class="vcard">
    <span class="fn">Ernestine</span>
    <div class="tel">555-1212</div>

By default, the iPhone will turn the 555-1212 into a clickable link. It will take whatever styling has been specified for the parent (i.e. there isn’t any way to specify an id or class for the automatically generated link).

If you’d like more control over the link that is generated, you can use markup like this:

<a class="call" href="tel:555-1212">Call Me</a>

When the user clicks on the link, it will initiate a call to the number specified. You need to be careful with these links. Many browsers will display an error message because they don’t recognize the tel: protocol. You’ll probably want to hide these links in your site-wide CSS. {
    display: none;

And then use your iPhone-specific CSS, to show them with the following: {
    display: inline;

Going deeper: designing for the iPhone

After taking care of the structural and presentational aspects of your page, you may want to examine some of your design decisions.

One thing that’s important to remember when working with Mobile Safari web pages is that they will often be served over the EDGE network. This network, based on cell phone technology, is much slower than broadband networks. It also has higher latency—it takes longer for your HTTP requests to reach a server and for the responses for the request to arrive back at the phone.

The feeling is very similar to the days when the 56K modem reigned supreme. And like those days, it’s important to keep an eye on the size of what’s on your server:

  • HTML—Leverage web standards to keep markup and page size to a minimum.
  • CSS—Use media queries to ensure that a minimum number of rules are loaded and parsed.
  • Multimedia—Use QuickTime H.264 encoding and pay attention to bit rates. Reference movies allow you to serve up different sized content using the same HTML.
  • Images—Use iPhone-specific CSS to load lower resolution images.
  • JavaScript—Be careful about including large JavaScript frameworks—loading hundreds of KB of scripts to show and hide a <div> doesn’t make sense.

Finally, remember the width of the iPhone screen: 320 pixels (for portrait) and 480 pixels (for landscape). Content that fits naturally within these sizes works best and will require less scrolling by the user. Likewise, content that does not span across multiple columns will be easier for the iPhone user to access.


Now let’s talk about taking the big plunge: creating a separate part of your website that is dedicated to iPhone users.

Why would you want to do this?

Again, before we can answer this question, we need to take a high-level look at the surroundings for our web designs. We’re all familiar with the current desktop and the browsers that run in this environment—so much so that we take its high density for granted.

The desktop allows us to do many things at once: browsing, e-mail, multimedia, chat, etc. There’s enough space for us to move our attention between many disparate tasks.

Now look at your iPhone. Typically, you’re only doing one thing at a time—making a call, finding a restaurant, or checking your appointments. The interfaces for these tasks are much simpler, making it much easier for you to focus on the work at hand.

Your website probably has functionality for many different use cases. Some of that functionality may be inappropriate for someone who’s on the go, and this is a great reason to make a site targeted towards the iPhone. If you have e-commerce or other transactional functionality, you may find that your current interface makes transactions cumbersome on the iPhone—and making it easy for people to give you money can be a direct benefit, even if that means streamlining your existing site or creating an iPhone-specific site. Other types of sites, like blogs, with their low information density, don’t need this kind of special treatment.

Once you’ve decided that you want to customize your site for the iPhone, there are things you need to keep in mind:

  • Simplify—On the iPhone, less is more. Let the user focus on your content. Use one column layouts instead of two or three columns.
  • Size—Bigger is better. Make it easy for the user to manipulate your content. Element sizes should start at 40 pixels and go up from there.
  • Emulate—Designs that mimic the iPhone user interface will be more successful. The user doesn’t have to learn new conventions when dealing with your content.

Emulation and frameworks

Let’s take a quick look at some of the tools you can use to help emulate the iPhone UI. Since you’re only worried about this working in Mobile Safari, you can utilize features that aren’t available in other browsers. You don’t have to worry about how a design looks in Internet Explorer—dreams do come true!

  • Use the <canvas> tag for drawing dynamic images and graphics.

There are also JavaScript-based frameworks being developed to ease the development of iPhone-specific interfaces. One of the more advanced and popular ones is Joe Hewitt’s iUI. If you’ve used the iPhone, you already know how to use his examples.

One final thing to keep in mind when you start this kind of development: make it an addition to your existing site. Don’t force an iPhone to use this special section of your site—it’s an enhancement, not a jail. Likewise, if a user without an iPhone wants to look at this part of your site, don’t block them with some “for iPhone only” nonsense. Remember that the web always works best when it’s open and developers don’t try to outsmart their visitors.


I realize that a lot of information has been presented in this article—there’s a lot to learn about this new device. But don’t be overwhelmed: much of what I’ve presented can be done incrementally. Start by setting up the <meta> tag with the viewport information and then experiment and test your ideas and changes. In the end you’ll end up with a site whose content is much more accessible from the iPhone. I, and millions of other visitors, will thank you.


Posted in Uncategorized | Leave a comment

iPad-Specific CSS

@media only screen and (device-width: 768px) {    /* For general iPad layouts */  }    @media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:portrait) {    /* For portrait layouts only */  }    @media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:landscape) {    /* For landscape layouts only */  }

Posted in Uncategorized | Leave a comment

iPad Orientation CSS

For the most part, Mobile Safari on the iPad is the same as that on the iPhone. One difference that I’ve found is that Webkit on the iPad honors CSS media query declarations based on orientation.

I’ve built a sample page demonstrating orientation css for iPad.

Using orientation in CSS is very simple. The code looks like this:

<link rel=”stylesheet” media=”all and (orientation:portrait)” href=”portrait.css”>
<link rel=”stylesheet” media=”all and (orientation:landscape)” href=”landscape.css”>

In this example, the only difference between the two stylesheets is that they hide one of two headings. The html for the page has the following code:

<h1 id=”portrait”>You’re Viewing in Portrait Mode</h1>
<h1 id=”landscape”>You’re Viewing in Landscape</h1>

The css for portrait.css simply hides the landscape <h1>:

#landscape {display:none}

And of course, landscape.css does the opposite.

You can see this css query in current versions of Safari and Firefox on your desktop machine. Simply change the size of your browser window until the height is taller than the width.


Posted in Uncategorized | Leave a comment

Разработка веб-приложений для iPad, iPhone и iPod

Всем привет! У меня хорошая новость – авторы временно.нет постепенно просыпаются после летнего отдыха. За это время мы много сделали и многому научились. Пришло время делиться этими знаниями с нашими дорогими читателями.

Сегодня я хочу сделать краткий обзор того, что позволяет делать мобильный сафари на айДевайсах, какие инструменты есть в руках у веб-разработчиков и как эти инструменты применять.

Сразу хочется предупредить, что ни в статье, ни в комментах не стоит обсуждать нужен айПад или не нужен. Нам, как веб-разработчикам просто необходимо согласиться с фактом, что уже миллионы владельцев айПадов ходят по улицам, летают на самолетах или сидят дома, наслаждаясь теплом домашнего вайфая. Эти самые владельцы очень щепетильные и придирчивые пользователи, и они очень хотят чтобы приложения, которые они используют, хорошо работали и эстетично выглядели на их девайсе.

Наша задача – уметь такие приложения делать, ведь мы очень любим наших пользователей, правда?

Как вы думаете, напишу ли я в будущем статью вроде “Оптимизация сайта для iPod Shuffle и Nano”?

Материал этой статьи будет устаревать, потому что чуть ли не каждую неделю выходит какая-то новая библиотека для трогательных девайсов. Поэтому я буду ее дополнять по мере поступления какой-либо новой информации.

Итак, начнем.

Иконка приложения

Про это уже была небольшая статья. Но здесь надо повториться.
Когда мы добавляем закладку “Домой” (можно сказать на рабочий стол), мы можем задать иконку, которая будет отображаться.

Задается иконка следующим образом:

 <link rel="apple-touch-icon" href="/apple-touch-icon.png" /> 

С появлением четвертого айФона и айПада, требование к этой иконке изменились – теперь она должна быть размером 114×114 для айфона или 72×72 для айпада. В общем-то размер этой иконки может быть и больше, сафари самостоятельно сожмет до нужного разрешения и добавит “стеклянность” иконке. Если стеклянность иконке не к лицу, тогда вместо apple-touch-icon следует прописывать apple-touch-icon-precomposed:

<link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-precomposed.png" />

Полноэкранный режим

По-умолчанию закладка с рабочего стола запускает веб-сайт в нормальном режиме сафари – с адресной строкой.
Чтобы приложение открылось в полноэкранном режиме, необходим такой мета-тег:

 <meta name="apple-mobile-web-app-capable" content="yes" />

Скрываем статус-бар

Для того, чтобы изменить статус-бар, используется мета-тег apple-mobile-web-app-status-bar-style

 <meta name="apple-mobile-web-app-status-bar-style" content="default" />

content здесь может быть один из трех вариантов – default, black или black-translucent.

Отключаем зум

Для управления зумом используется мета-тег viewport. Отключаем возможность зумить:

 <meta name="viewport" content="user-scalable=no, width=device-width" />

Картинка загрузки (splash image)

Если такая картинка не будет задана, то при открытии приложения, будет показан скриншот последнего состояния приложения.

 <link rel="apple-touch-startup-image" href="./startup.png" />

Картинка должна быть точно следующих размеров (иначе устройство его не примет):

  • 320×480 (iPhone < 4, iPod Touch)
  • 640×960 (iPhone 4, новый iPod Touch)
  • 768×1004 (iPad portrait)
  • 1024×748 (iPad landscape)

Все описанные выше пункты позволять создать веб-приложение используя html, css и javascript, которое будет внешне выглядеть как нативное. Да, его нельзя опубликовать в апп стор, но если приложение.

Ориентация экрана

В зависимости от ориентации айДевайса возможно вы захотите по-разному отображать содержимое. Самое простое – использовать такие объявления css:

 <link rel=”stylesheet” media=”all and (orientation:portrait)” href=”portrait.css”>
 <link rel=”stylesheet” media=”all and (orientation:landscape)” href=”landscape.css”> 

portrait.css будет использован для портретной ориентации, а landscape.css соответственно для ландшафтной.

С помощью js также можно отловить событие поворота экрана. Для этого служит событие orientationchange

 window.addEventListener('orientationchange', ChangeOrientation, false);

 function ChangeOrientation() {
  var orientation = Math.abs(window.orientation) === 90 ? 'landscape' : 'portrait';

Избавляемся от эластичного скролла

В сафари есть замечательная фича – эластичный скролл в конце и начале страницы. Нечто подобное я когда-то делал с помощью jQuery в этой статье. Демо здесь. Чтобы создать еще более достоверную имитацию нативного приложения, от этой фичи можно избавиться парой строчек js

 function NoElasticScroll(e) {
  e.preventDefault(); }
<body ontouchmove="NoElasticScroll(event);" >

Определение iOS

Для того, чтобы определить, на каком из айДевайсов просматривается страница, можно использовать следующий сниппет:

 var Device = {};

Device.isiPhone = function() {
   return navigator.userAgent.indexOf('iPhone') != -1;
Device.isiPod = function() {
   return navigator.userAgent.indexOf('iPod') != -1;
Device.isiPad = function() {
   return navigator.userAgent.indexOf('iPad') != -1;
Device.isiOS = function() {
   return Device.isiPhone || Device.isiPod || Device.isiPad;

Вот как выглядит ЮзерАгент у этих девайсов:


 Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 

iPod (старый):

 Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A101a Safari/419.3 


 Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) version/4.0.4 Mobile/7B367 Safari/531.21.10 

Инструменты, библиотеки

C самого появления айПада, на свет стали рождаться различные фреймворки, плагины для фреймворков, плагины для плагинов фреймворков и так далее.
Яблочники сделали для айПада страничку с хелпом, которая работала как нативное приложение. Там использовался своя наработка, которая называлась AdLib. В интернетах ее прозвали “секретным фреймворком Эпла” )) линк.

Прошло некоторое время и появились не такие секретные наработки.


Это jQuery-плагин, призванный упростить разработку веб-приложений. Все весьма просто и понятно. Анимация работает замечательно только на iPhone, iPod Touch. На айпаде некоторые виды анимации глючат – поэтому желательно предварительно проверить, если вы хотите, например использовать поворот куба. А на андроиде вообще желательно обойтись без анимации. Во всяком случае, на моем Герое, css-трансформация работает очень… неприятно.


Sencha Touch

Сенча – это такой зеленый чай, производится в Японии.

Сенча Тач – это объединение вышеупомянутого jQTouch, extJS и Raphaël (последняя библиотека – разработка Дмитрия Барановского, упрощающая работу с векторной графикой на вебе).

Сенча Тач позиционируется как ДжаваСкрипт-фреймворк для разработки веб-приложений для тач-девайсов iOS и Android. На сайте доступно много демок. Рекомендую заценить.



Этот инструмент попроще. Единственное что он делает – позволяет скролить контент внутри блока фиксированного размера. Как раз то что надо, чтобы создавать веб-приложения. Мой выбор.



Слаблет – это CSS/jQuery фреймворк для создания веб-проектов для айпада. Для скролла контента используется вышеупомянутый iScroll.




jQuery Touchwipe Plugin

Плагин для обработки события “wipe”. Или “протирания” по-русски. Когда пальцем (ну или кому как удобнее) проводим по экрану, например, слева направо. Для нативных приложений iPhone это движение обычно вызывает кнопочки удаления элемента.

iToggle for jQuery

Плагин jQuery для имитации нативных чекбоксов айДевайсов.


jQuery Slider Егора Хмелева

Этот слайдер отличается от прочих тем, что поддерживает работу на айДевайсах.

[offtop] Егор сейчас в команде, работающей над замечательным проектом Букмейт (у меня еще есть пара инвайтов, могу выслать).
Для чтения на айДевайсах там имеется неплохое веб-приложение… хотя его можно и значительно улучшить.


Инструменты для рисования интерфейсов, вайрфреймов и прототипирования

Для начала мне нравится интерфейс набросать на бумаге. За бугром есть нету проблемы приобрести блокнот для этой цели. И найти их нету проблемы.

Если вы производите такие блокноты (или знаете где их достать), пишите в комментах, я обязательно добавлю в статью.

А пока для домашних нужд предлагаю использовать распечатки.

Для прототипирования онлайн могу предложить два приложения


Читатель targa кинул ссылку на этот ресурс. Это виндуз-приложение, дающее необходимый инструментарий для создания дизайна и тестирования(!) приложений.



Кстати, обнаружил что 15 сентября они выходят из стадии Беты. Очень неплохой инструмент.



Наброска интерфейса для айфона.


Парк приложений для айДевайсов постоянно растет. И очень часто можно найти какое-то интересное решение в интерфейсе. Все приложения не пересмотришь, но интересные идеи можно найти на Эмбере. Конкретно по айПаду здесь.

Ну а несомненно лучший способ вдохновиться – это получить приз от Временно ;)


Posted in Uncategorized | Leave a comment

iPhone и CSS-фреймворки

iPhone и CSS-фреймворки

Как и многие жизненные проблемы,
эту можно решить сгибанием

Бендер, Футурама

Сначала о том, что накипело: я нашел в себе силы, справился с ленью и переверстал-таки свой блог. Верстать под WordPress оказалось весьма сомнительным удовольствием. Ни тебе XSLT, ни вообще какого-то языка шаблонов: голый PHP с весьма странными функциями вроде the_tags() и the_content() (Капитан Очевидность легко подскажет их назначение). Стандартные темы, которые я взял для примера, оказались перегружены лишними кусками html-кода и их пришлось серьезно перерабатывать (проще говоря, делать с нуля). В общем, одни огорчения.

Я бы еще поворчал на тему верстки под WordPress, но в заголовке статьи нет про него ни слова :) . Что ж…

Верстать под iPhone? Проще некуда

Все более-менее активные интернет-пользователи давно обзавелись или собираются купить в ближайшее время айфоны или Android-телефоны. Увы, обычные сайты совершенно не предназначены для мобильных устройств: и на экран они не умещаются, и кнопки слишком мелкие, и картинок для дорогого EDGE/3G многовато. Приходится делать более компактные и менее функциональные версии сайтов. Естественно, верстка под умные мобильники чуть-чуть отличается.

Есть два пути сделать айфон версию сайта (господа фанаты Android, я вас тоже имею в виду :) ):

1. написать все с нуля;
2. воспользоваться готовым фреймворком и сымитировать интерфейс нативного приложения.

Написать с нуля будет несложно. Вам понадобятся специальные мета теги (например, чтобы избавиться от дурацкого масштабирования) и капелька представлений об удобстве и юзабилити. Для погружения в верстку вполне сойдет вот эта презентация (осторожно, PDF!).

Дальше поможет только опыт (и, надеюсь, мои статьи о html-верстке). Спустя короткое время вы выясните, что onclick и onmouseover, onmousemove и onmouseout работают несколько не так, как вы ожидаете (по сути в айфоне нет клика, есть только наведение мышью). Eще через короткое время вы узнаете, что, чтобы сделать полноэкранный сайт, вам понадобится не только специальный метатег, но и AJAX (иначе новая страница будет открываться в браузере с элементами управления, а не на весь экран). Вас определенно порадуют фишки современного браузера и отсуствие Internet Explorer как такового :) .

К фишкам современных браузеров, конечно, стоит отнести и HTML5 и CSS3 (правда, зачастую с префиксами -webkit ) и довольно быстрый JS. Стоит, правда, оговориться, что так было не всегда и первые версии прошивок для iPhone не имели многих возможностей, хотя… кого это сейчас волнует?

Однако иногда нужно сделать сайт, который будет в точности повторять нативное приложение (например, чтобы не писать приложение на Objective C для iTunes Store). Конечно, такое решение будет не совсем верным: правильно сымитировать интерфейс вам не удастся. Почему? Сейчас расскажу.

“Лучшие” фреймворки для верстки

О библиотеках для верстки под айфон не написал только ленивый. Говорят, основная цель этих фреймворков – минимизировать вашу возню с дизайном и созданием контролов и эффектов, похожих на настоящие “айфоновские”: они сами принесут с собой CSS и JavaScript, которые будут эмулировать поведение элементов интерфейса на веб-странице. Они также избавят вас от возни с AJAX и прочей вебдванольностью. Поиск в Google даст целую кучу фреймворков и каждый из них будет, по мнению разработчиков, самым удобным, самым быстрым и самым гибким.

Когда я начинал работать над  iPhone-версией нашего сериального стартапа, я прошелся по всему списку фреймворков и попробовал каждый из них. Ровно неделю я потратил на то, чтобы поковыряться в начинках этих фреймворков, отправить один багрепорт и сверстать таки сайт без их использования. О причинах такого странного решения чуть позже. Сейчас давайте поговорим о каждом в отдельности.

1. jQtouch

По первым двум буквам несложно догадаться, что он имеет какое-то отношение к jQuery. Так и есть. Это плагин для знаменитого jQuery. Как и почти все плагины для jQuery он удобен, красив и монструозен: его интерфейс заслуживает высших оценок, но… обманывать пользователя и вынуждать загрузить 60 килобайт ради пары чекбоксов, мне кажется, будет подло. Подождать 20-30 секунд тоже захочет не каждый.

Несмотря на всю красоту и кажущееся удобство, я отказался от него: нам не нужен был сайт, сжирающий весь трафик разом.

2. IUI

Это минималистичная библиотека, которая состоит из пары JS и CSS файлов и набора картинок. Она приносит с собой стандартные поля ввода, чекбоксы и кнопочки в стиле iPhone. Создатели не напирали на кроссбраузерную совместимость (напомню, в iPhone и в Android используется один и тот же Webkit) и поступили правильно: код достаточно хорош, компактен, им приятно пользоваться. На этой библиотеке я, наверное, и остановился, если бы не баги в работе с AJAX. Одну ошибку удалось-таки исправить (не отправлявшаяся форма), с остальными я мириться не смог и, плюнув на почти готовый сайт, взялся переделывать все с нуля.

3. UiUIKit

Справедливости ради, стоило начинать именно с этого фреймворка, однако именно этим фреймворком я и заканчивал свои “исследования”. Это набор CSS и HTML, который несет в себе вполне неплохие примеры пользовательского интерфейса в iPhone. Пожалуй, это все, что можно про него сказать: нет смысла использовать чужой CSS и HTML, добавлять ему типично айфоновское поведение и укрощать те баги, которые будут периодически лезть из всех щелей (верстка чужая, и баги будут точно).

Конечно же, были и другие фреймворки, эмулирующие поведение айфона. Увы, они все равно эмулировали его: подтормаживали, загружали непонятно что из интернета и не всегда были настолько smooth and sexy, насколько бывают iPhone-приложения.

Попробовав немало сайтов (в частности, айфон вариант Facebook), я окончательно убедился, что двигаюсь в неверном направлении и за вечер смастерил вполне неплохой сайт для iPhone, написав весь код с нуля.


И я твердо уяснил для себя, что пока нет ни одного нормального CSS-фреймворка под iPhone, который сгодится для эмуляции интерфейса. Следовательно, не нужно подражать нативным приложениям. Надо всего лишь делать свои iPhone-сайты удобными и понятными.


Posted in Uncategorized | Leave a comment

Как сделать сайт более iPhone-совместимым за 5 шагов

Тот факт, что iPhone предлагает наиболее развитый мобильный браузер среди мобильных платформ, пожалуй, ни у кого не вызовет сомнений. Однако не все знают, что довольно небольшими усилиями можно сайт сделать еще более дружественным к тем, кто смотрят его на iPhone или iPod Touch.

Ниже предлагаются простые 5 шагов, с которых можно начать, на примере сайта WHOIS Digger.

Шаг 1. Аналог favicon.ico

Когда пользователь создает ссылку на ваш сайт в виде иконки в SpringBoard, iPhone автоматически формирует картинку из скриншота страницы. В результате почти всегда получается неразборчивая каша, которая на гордое звание «иконки для iPhone» никак не тянет. Пропишите этот тег в заголовке страницы:

<link rel="apple-touch-icon" href="res/iphone_icon.png" />

и добавьте соответствующую картинку res/iphone_icon.png размером 57х57 пикселов. iPhone сам добавит скругленные углы и полукруглый блик, сделав вашу иконку похожей на остальные.

Вот так выглядит исходная картинка и иконка на рабочем столе iPhone:

Шаг 2. Полноэкранный режим (почти).

Добавление вот этого тега приведет к тому, что ваш сайт, будучи запущен по иконке из SpringBoard, будет похож на отдельностоящее приложение (не будет отображаться ни строка ввода адреса / поиска, ни нижний тулбар). Останется только верхняя полоска статуса.

<meta name="apple-mobile-web-app-capable" content="yes" />

Минусы — навигация на сайте должна быть самодостаточной, ибо на кнопки Back / Forward браузера уже полагаться не получится.

Это вид веб-сайта, запущенного с иконки на рабочем столе. Как видите, ничего лишнего.

Шаг 3. Адаптируем диапазон масштабирования

Если Ваш сайт изначально отображается в iPhone не на полный экран, то вы можете подобрать начальный масштаб отображения, максимальный масштаб отображения и, при необходимости, запретить масштабирование пальцами вообще (если весь сайт при выбранном масштабе умещается на экране по горизонтали):

<meta name="viewport" content="width=device-width; initial-scale=0.85; maximum-scale=0.85; user-scalable=0;" />

Шаг 4. Добавляем CSS-стили, предназначенные только для iPhone

Вот так можно подключить отдельный CSS, который будет воспринят только на iPhone:

<link rel="stylesheet" href="res/iphone.css" media="only screen and (max-device-width: 480px)" />

Критически оцените вид вашего сайта на iPhone и посмотрите, какие элементы навигации и контента можно увеличить, чтобы по ним легче было попадать пальцем. Какие блоки можно на iPhone вообще скрыть или уменьшить? Можно ли привести сайт к одноколоночной верстке, для которой легче подобрать масштаб? Понятно, что разработка полноценного стиля сайта под iPhone — занятие ответственное, но какие-то моменты можно подправить достаточно быстро.

Шаг 5. Отмена автоматической коррекции масштабирования

Если Ваш сайт использует Ajax-запросы или Javascript для динамического изменения содержимого страницы, вы можете наблюдать неприятные побочные эффекты в виде изменения масштаба текста при изменениях DOM или сворачивании/отображении некоторых элементов. Следующий кусок CSS отключит встроенную эвристику мобильного Safari и избавит от этих эффектов:

html {
-webkit-text-size-adjust: none;

В итоге за 15 минут работы получилось полноценное веб-приложение для iPhone:


Posted in Uncategorized | Leave a comment