Viewports for mobile devices and tablet PC’s : a pixel is not a pixel

Last update : June 24, 2014

Designing a webpage which looks good on desktop PC’s, mobile devices and tablet PC’s is challenging. You have to optimize your content at least for screens that are 320px, 480px, 768px, and 1024px wide. One tool to reach this goal is the viewport meta tag.

The viewport meta tag was introduced by Apple for the iPhone, and it has since been picked up by Microsoft for Windows Mobile, by Nokia for Maemo and by Android. Remember however that the viewport has nothing to do with the device. The viewport is the browser and more precisely the window of the browser. Recently the W3C published a draft of a CSS Device Adaptation based on the viewport meta tag.

The tag is ignored by regular desktop browsers.

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

Mobile Safari presents desktop-sized websites on small screens by rendering to a virtual browser screen that is 980 pixels wide. Opera assumes a page to be 850 pixels wide. Pages on the iPad in portrait mode and on other mobile devices are scaled down.  Pages can be zoomed and panned. Viewport tags tell the Mobile Safari that the website displays properly narrower than 980 pixels. The webpage can be set for other scaling preferences.

Apple suggests to avoid hard-coding a width for the viewport and to use the physical device-width to set the viewport :

<meta name="viewport" content="width=device-width" />

This setting makes one CSS pixel equal to one device pixel. The physical device-width refers to the screen size in portrait mode. One problem is that the content is blowed up if the device is oriented in landscape mode. To avoid blow-up, a maximum scale factor can be applied :

<meta name="viewport" content="width=device-width, maximum-scale=1.0" />

You can add the attribute “user-scalable=no” to disable the pinch-to-zoom feature :

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

This is useful for preventing accidental zooms and makes web apps feel more app-like, but most users might want to see the content at a larger size.

The complete list of viewport properties for iPad (and iPhone with Retina display) is given below :

  • width : 200 – 10.000 ; default : 980
  • height : 223 – 10.000
  • minimum-scale : 0.0 – 10.0 ; default : 0.25
  • maximum scale : 0.0 – 10.0 ; default : 1.6
  • initial-scale : between min and max
  • user-scalable : yes / no ; default : yes

To hide the control-bar which consumes about 60 pixels, the following script can be used :

<body onload="setTimeout(function() { window.scrollTo(0, 1) }, 100);"></body>

To deal with the greatly differing screen sizes, CSS media queries allow to specify completely different stylesheets depending on how large the screen is.

<link media="only screen and (max-device-width: 480px)" href="small.css" type= "text/css" rel="stylesheet">
<link media="only screen and (min-device-width: 481px) and (max-device-width: 1024px)" href="medium.css" type="text/css" rel="stylesheet">
<link media="screen and (min-device-width: 1025px)" href="large.css" type="text/css" rel="stylesheet">

Instead of using separate css-files, the media query can be used inside a single css-file :

@media only screen and (min-device-width: 481px) and (max-device-width: 1024px)
{
styles
}

In fact it’s useful to consider two viewports : one based on device pixels, the other based on CSS pixels. Only at zoom level 100% one CSS pixel is exactly equal to one device pixel.

The iPhone 4’s Retina display has a far larger physical pixel density than previous iPhones. Still, it reports 320px for the device-width media query (as well as JavaScript screen.width) both with and without the meta viewport width=device-width.

A few links about useful tutorials about viewports and other related subjects are listed herafter :

The next list shows links to iPad and iPhone simulators to test the rendering of webpages on these devices :

Facebook URL Linter and Insights

The Facebook URL linter is a tool that helps you to debug Open Graph webpages, pages with embedded like button or with other social plugins.

The Open Graph Protocol Open Source Community developped other tools and parsers for php, java, python, ruby, json to check Open Graph webpages.

It’s even possible to see how many URL’s of pages that are not part of the Facebook Open Graph have been shared by using the API request :

http://graph.facebook.com/?id=http://www.example.com

More details are provided by the API request

https://api.facebook.com/method/fql.query?query=SELECT%20share_count,%20like_count,%20comment_count,%20total_count,%20click_count%20
FROM%20link_stat%20WHERE%20url=%27http://www.example.com/%27

Insights provides analytics on a Facebook Page, app and website. The Insights Dashboard makes it easy to see how Facebook users are interacting with your content, and the Insights APIs allow developers to obtain additional statistics and integrate the data with third party reporting systems.

Valid W3C websites with Facebook Open Graphs or Like Buttons

last update : December 23, 2011
A developer who added Facebook Open Graph metatags or Like Buttons to his webpage finds a lot of error messages (invalid HTML/XHTML) in the W3C Validator. This means it won’t work on a lot of browsers.

Several fixes exist to make the webpages W3C compliant. A few useful links will be given below:

Google Apps Engine Tips

Rollback

If an update for GAE (Google App Engine) doesn’t complete it will cause an error (similar to : Another transaction by user xxxx  is already in progress for this app and major version. That user can undo the transaction with appcfg.py’s “rollback” command.) and not allow you to upload new updates. The rollback can de done with a batch file. A faster solution to fix this problem is incrementing the version number in the app.yaml file and activating the new version in the online console. The same error arise if you want to delete an a app with failed update. The only solution in this case is to do the rollback.

Google App Engine (GAE)

Google App Engine

GAE (Google App Engine) is a platform for developing and hosting web applications in Google-managed data centers. It was first released as a beta version in April 2008. GAE is cloud computing technology. It virtualizes applications across multiple servers and data centers. GAE is Platform as a Service while AWS (Amazon Web Services) is Infrastructure as a Service.

GAE is free up to a certain level of used resources. Fees are charged for additional storage, bandwidth, or CPU cycles required by the application.

The applications of the logged Google developer are available at https://appengine.google.com/

List of GAE applications

The dashboard allows to manage the different applications (quotas, instances, logs, cron jobs, task queues, blacklists, datastore, blob viewer, settings, permissions, billing, resources, …). A very efficient feature is the version control based on the app.yaml file :

GAE version control

Another useful feature is the error logging :

GAE error logging reports

YAML and MVC

YAML is a human-readable data serialization format that takes concepts from programming languages such as C, Perl, Python, ideas from XML and the data format of electronic mail. YAML was first proposed by Clark Evans in 2001, who designed it together with Ingy döt Net and Oren Ben-Kiki.

MVC (Model–view–controller) is a software architecture considered as an architectural pattern used in software engineering. The pattern isolates “domain logic” (the application logic for the user) from the user interface (input and presentation), permitting independent development, testing and maintenance of each (separation of concerns). MVC was first described in 1979 by Trygve Reenskaug, then working on Smalltalk at Xerox PARC.

Python conventions

last update : March 31, 2011

Module names

A module is a file containing Python definitions and statements. The file name is the module name with the suffix .py appended. Within a module, the module’s name (as a string) is available as the value of the global variable __name__. Every Python module has it’s __name__ defined and if this is ‘__main__’, it implies that the module is being run standalone. The function called main doesn’t have any special significance in Python. However, it is common practice to organize a program’s main functionality in a function called main and call it with code similar to the following:

def main():
    # the main code goes here

if __name__ == "__main__":
    main()

Comments

There are two styles of comments in python :

# single line comments

" " " multiple

line

comments " " "

Multiline comments, enclosed by triple-quotes, are used to embed doc strings, for example in a class school. If you declare an object t=school and then t . __doc__ or t (help), the embedded comments are returned. Triple-quotes should not be used to comment out large blocks of Python code.

Self argument of methods

The first argument of a method is usually called self. This is nothing more than a convention: the name self has absolutely no special meaning to Python.  Programs that are not following these convention are less readable to other Python programmers and may fail in class browser programs which rely upon such a convention.

Unicode

In Python source code, Unicode literals are written as strings prefixed with the ‘u’ or ‘U’ character:

u'abcdefghijk'

Raw Strings

Raw strings are written as strings prefixed with the ‘r’ or ‘R’ character. Raw strings don’t treat the backslash as a special character. Every character you put into a raw string stays the way you wrote it.

r'/user/'

Indentation

Indentation (leading whitespaces) in Python counts. Every block structure — controls, classes, functions, etc. — must be indented the same number of times for their level in the program. Convention is to use four spaces (without tabs) for each level of indentation.

Line continuation

To break a long statement into several lines, the line continuation character (backslash) can be used at the end of the breaked physical lines (explicit line joining). This syntax is however outdated and should be avoided. Expressions in parentheses, square brackets or curly braces can be split over more than one physical line without using backslashes (implicit line joining). A line ending in a backslash cannot carry a comment, but implicitly continued lines can carry comments. The indentation of implicit continuation lines is not important.

Django : high-level Python Web framework

Django was designed to make common Web-development tasks fast and easy. Django adheres to the DRY (Don’t repeat yourself) principle.

Django comes with an object-relational mapper in which you describe your database layout in Python code. Other useful features are a caching framework that integrates with memcached or other backends and a syndication framework that makes creating RSS and Atom feeds as easy as writing a small Python class.

Django has a rich documentation and great tutorials. An active community gives answers to common questions and hints to solve problems.

The Google App Engine provides a Python runtime environment including Django as a third-party library. I started yesterday evening to host a first Facebook application, designed with Python and Django,  on the Google App Server.

Django was originally developed at World Online, the Web department of a newspaper in Lawrence, Kansas, USA. Django is now run by an international team of volunteers.

The main elements of the Django Template Language are :

  • variables :  {{section.title}}   the content is replaced by the title attribute of the section object
  • filters : {{name|ower}}   the content is replaced by the lowercase string of the name; there are about 30 built-in filters; custom template filters can be created
  • tags :  {% doit %}  tags are more versatile than variables;  tags can be used for loops, conditions, …; there are about 24 built-in tags; custom template tags can be created
  • comments :  {#my comment#}  only for single-line comments
  • decorators : @my_decorator   – a decorator is a function that wraps the decorated function  in yet another function, allowing you to run code both before and after the main function
  • template inheritance : {%block identifier%} …….. {%endblock%}   the content of the block named identifier in the base template can be overridden by the content specified in child templates