Upload
phamdien
View
221
Download
1
Embed Size (px)
Citation preview
Developing Adaptive and Flexible Metro HTML5/JavaScript* Apps
Objective
HTML5 and JavaScript* have emerged as powerful tools that can be utilized to create full featured
compelling Metro style applications on devices running the Windows 8* OS. These applications can
target multiple form factors like UltraBook™ devices, and tablets and laptops running Windows 8. In
this article we will walk through different considerations in building HTML/JavaScript Metro style apps
that are adaptive to any screen size, and use flexible layouts to fit different views of Windows 8
apps, including snap view, filled view, and portrait or landscape. We will look at taking advantage of
CSS3 features like grid layouts, flexbox, and media queries. Finally, we will walk through a sample
app** to demonstrate these development methodologies.
Table of Contents
1. Introduction
2. Overview of HTML5/JavaScript Metro Apps
3. Device Size, Views and Orientation
4. App Layouts and View Design
5. Using CSS3 Grid and Flexbox Layouts
6. Using Media Queries
7. Putting all together and Validating in Windows 8 Simulator
8. Summary
Introduction
Metro style applications are a new application development platform introduced with Windows 8 that
provides the capability of developing applications that can be deployed on multiple form-factor
devices running Windows 8. Developers create a common application regardless of the deployment
device, the runtime framework manages the behavior of the application on the target device. To
develop Metro style apps, developers are encouraged to follow the Metro Style Guidelines, found at:
http://msdn.microsoft.com/en-us/library/windows/apps/hh464920.aspx
One of these guidelines is to develop apps that “Snap and scale beautifully.” The app GUI needs to
have a flexible layout, so that it can adapt its user interface to any screen size, re-orient the user
interface as the device is rotated (portrait or landscape), and also be flexible enough to adapt to
snapped or filled views of Metro style apps. The user interface design needs to take into account all
of these aspects during the initial stages of application development.
In this article we will showcase how to take advantage of HTML5/CSS3 features to achieve these
design targets. We will walk through a sample app and demonstrate step-by-step procedures to
implement these features.
It is assumed that the reader has basic familiarity with HTML and CSS.
Overview of HTML5/JavaScript Metro Apps
With Windows 8 and Metro style apps, developers can take advantage of their HTML/JavaScript skills
in developing full blown apps with functionality on par with native Windows apps. These apps have
full access to all system APIs exposed via WinRT. More details on developing Metro Style apps using
JavaScript can be found on this link:
http://msdn.microsoft.com/en-us/library/windows/apps/hh465037.aspx
In this article, for demonstration purposes, we will use a sample HTML5/JavaScript-based Metro style
app called “Tower of Hanoi” (ToH) (http://en.wikipedia.org/wiki/Tower_of_Hanoi). The objective of the
ToH app is for users to solve the “Towers of Hanoi” puzzle by moving disks from pole #1 to pole #3,
using pole #2 as temporary location. ToH will also provide a button to animate the solution if the
users so chooses, and the solution is presented via an animation with a configurable delay. In
addition, controls for changing some of the application configurations and display of status
information are also included in the sample app.
The ToH app’s final design is shown below:
We also have an app bar button to show “About Game” information. Below is the screenshot for app
bar and “About Game.”
The big goal of this app is to target different form-factor devices, all the way from tablets (e.g., 10.6””
1024x768) to big screen devices (e.g., up to 27’’, 2560x1440). We would also like the app to adapt to
portrait view and Metro fill/snap views automatically. The disks, poles, and text sizes will have to
scale up and down seamlessly depending on available screen real estate.
Device Size, Views, Orientation, and App Layouts
Device size is a factor of screen resolution or pixels and size of the screen. Windows 8 and Metro
style apps support different combinations of them and have the ability to scale to any size. Metro
style apps or games typically have UI resources in either image format (e.g., png or jpeg) or some
custom graphics like SVG. If developers use SVG assets, they will automatically scale. If developers
have custom images, they might store different sizes of the image for each scale; Windows 8 will
automatically pick the correctly scaled version. It is recommended to use Windows 8 facilities for
automatic resource loading with naming conventions for the three different zoom levels (100%,
140%, 180%). This will handle most of the pixel densities and screen resolution for the images. More
information on device size and scaling can be found here:
http://blogs.msdn.com/b/b8/archive/2012/03/21/scaling-to-different-screens.aspx
In the ToH app, we do not have any graphics resources or images. All the UI elements are
implemented in plain HTML5/CSS3 elements. For ToH, we would like to support all screen sizes from
10.6”” (1024x768), 1366x769 (the minimum to support snapped/fill views) and above. To test and
interactively design the app, developers can use “Blend for Visual Studio*,” which shows quick,
interactive layout of the app in different screen sizes. The screenshot below shows all the available
options in the Blend tool.
Windows Metro style apps allow the users to change the app display into a snapped view or a filled
view. More details can be found at this link:
http://msdn.microsoft.com/en-us/library/windows/apps/hh465371.aspx
For the ToH app, below are the final layouts for the filled view and snapped view, respectively.
Filled view:
Please note the disk and pole sizes are automatically reduced. The status text is also automatically
realigned, pushing the “Status:” text below the Moves/Elapsed text.
Snapped view:
In the snapped view, all the elements including text size are automatically scaled down. For lack of
space, the snapped view is not showing the control buttons; it only shows the current status text.
Developers are encouraged to reduce the amount of information shown in snapped view, due to the
limited space. One strategy is to show the minimal amount of information that a user would find
useful. Some apps may not be able to achieve a snapped view that is useful to users; in which case,
the app should not be loaded (maybe have an app or game logo). Users will have to use a form factor
that accommodates the filled or full view to use the app. The store app is a good example of this, as
shown in the Snapped view screenshot above.
Users can also change the orientation of their devices to a landscape or portrait mode. We want our
sample app to automatically reorient and scale the disk sizes, poles, and status/controls to fit the
appropriate orientation. The previous screenshots show landscape mode; below is the screenshot for
portrait mode for our sample app. In this mode the poles are reoriented vertically, very similar to the
snapped view. But in this case the app occupies the full screen and shows all the app pieces, unlike
the snapped view.
In this section, we have discussed device screen sizes, views, orientation, and how we want the ToH
app layout to be in each of these cases. In the next few sections we will discuss how to implement
these features.
App Layouts and View Design
As part of the design of a new app, it’s recommended to identify core UI pieces of the app. Developers
need to break the app’s full UI into pieces that can be moved around or scaled as required.
For example, in ToH app we can break the UI into several pieces: three towers that constitute the
core piece, game controls, and status. Since our core piece is a little big (not flexible as a whole), we
can break it down into three separate towers that can be moved around as needed. But we still need
a way to identify which tower is #1, #2, or #3, as it’s part of the game’s core logic (e.g., the game
ends when all disks are moved to tower #3).
The screenshot below shows the breakdown:
We have four UI pieces:
1. Tower #1
2. Tower #2
3. Tower #3
4. Game panel - Combines both controls (4.1) and status (4.2)
We want to be able to move these pieces in any configuration, dynamically at runtime. We want the
app to respond to any view change or portrait change by updating the location of these pieces. All
these pieces are also expected to scale up or down appropriately.
Ideally, it is preferable if we could accomplish all of this inside the presentation layer. Let the system’s
(in this case HTML5/CSS3) presentation facilities handle the four pieces automatically in the most
optimized and HW-accelerated way. Fortunately, the latest CSS3 standard makes this possible. We
can use CSS3 media queries to listen to view or orientation change(s), and respond by reconfiguring
the app layouts using new CSS3 flexbox and grid layout features. All of this, without even a single line
of JavaScript code. Also, this nicely separates the presentation layer from the underlying app core
logic or game model.
Using CSS3 Grid and Flexbox Layouts
As we have seen, all the elements in our sample app are just plain HTML elements (no HTML5 canvas
element). Below is the HTML markup for the four pieces we identified in the last section.
Each of our pieces has a corresponding div Id or class, as seen in the above markup:
1. Tower #1 - #pole1
2. Tower #2 - #pole2
3. Tower #3 - #pole3
Game panel – Combines both controls (4.1) and status (4.2) – “.controls”, “gctrl”, “#status”
We will use these identifiers in CSS styling to control their size, style, and layout(s).
<div class="gamePage" id="gameHost">
<div class="pole" id="pole1"> <div class="dbase"></div> <div class="dpole"></div> <div class="dhost" id="dhost1"></div> </div> <div class="pole" id="pole2"> <div class="dbase"></div> <div class="dpole"></div> <div class="dhost" id="dhost2"></div> </div> <div class="pole" id="pole3"> <div class="dbase"></div> <div class="dpole"></div> <div class="dhost" id="dhost3"></div> </div>
<div class="controls"> <div class="gctrl"> <button class="btn" id="ResetButton">Reset Game</button><br /><br /> Number of Disks: <span id="numDisksLabel"></span><br /> <input type="range" class="btn" id="numDisksSlider" min="1" max="12" /> </div> <div class="gctrl"> <button class="btn" id="StartAnimButton">Solve and Animate</button><br/><br/> Animation Delay: <span id="animationSpeedLabel"></span><br /> <input type="range" class="btn" id="animationSpeedSlider" min="0" max="100" /> </div> <div id="status"></div> </div>
</div>
CSS3 introduces new flexible layout options. The main ones among them are the grid layout and
flexbox layout. Metro apps support both.
Grid layout lets the developers define the layout in terms of columns and rows. The users can then
define which element will occupy which box (box formed by the intersections of rows and columns).
We can even assign combined box(es) to elements. For example, we can combine row 2 (r2) with
columns 3 (c3) and 4 (c4). So we get a combination of box r2-c3 and box r2-c4. This is a very powerful
way to position and align different layout pieces of the app. The child elements of the grid can further
define their own rules.
Without the grid layout feature, users have to resort to different rudimentary position techniques
(e.g., absolute position, table layout, etc.) that are not as flexible as grid layout. For our sample app,
we mainly use grid layout to specify where all our main pieces (the four pieces discussed above) will
go, and how they will be laid out in different views (snap, fill, portrait, etc.). But grid layouts are
capable of much more than this. For more detailed info, please refer to the documentation at:
http://www.w3.org/TR/css3-grid-layout/
For the ToH app, we define the default (landscape, full screen) grid layout in CSS3 styling as shown
below:
Here, we define five columns (values separated by space) and two rows. Users can define the size in
terms of fractions, among other metrics. In this case, we want each of the towers to have the same
space, so we define 1fr for each (equal ratio for all 3). Please note, users can also use absolute pixel
to define the columns or row sizes. In the above example, we used 0px for columns 1 and 5, as a
place holder for future modifications if we decide we want some kind of border for our game (maybe
of 4 pixel breathing space between device borders). We can leave such placeholders so we don’t have
to modify all of the elements’ positioning again, every time we change the grid layout initialization. So
in this case, we could make columns 1 and 5 of 4px each, and everything will work with a nice 4px
border on both sides.
For rows, we left 14 rem (relative sizing based on system font size) for our game panel controls, and
everything else for the towers. Using relative font sizing (rem metric) helps to scale the size of
control panel depending on the screen size. We do not have to use absolute metrics, which will not
scale automatically.
For each tower, we define the corresponding element id to use grid positioning as shown below (each
tower occupying 1fr columns 2-4):
#gameHost { width: 100%; height: 100%; display: -ms-grid; -ms-grid-columns: 0px 1fr 1fr 1fr 0px; -ms-grid-rows: 1fr 14rem;
}
This only positions three major pieces. We still have the controls (buttons and status text) to position.
Controls will use the 2nd row, and all columns (1 to 5). Below is the grid assignment for this element
(“.controls”).
This element has two sub-elements, as seen in the HTML markup. One for the fixed buttons/controls
and another for the game status. Notice it uses flexbox (display: -ms-flexbox) as its display,
which we will cover next.
Flexbox is another nice CSS3 layout feature that serves a slightly different purpose than grid layout.
It is very useful particularly when you have a bunch of elements that you want to throw inside a div,
and make them automatically align, flex, stretch, or pack depending on total available space. A good
example is command icons or game controls that are aligned horizontally or vertically. Using flexbox,
we can specify the elements to be automatically centered, stretched, packed in the middle, etc.
Further, we can specify some children as a fixed rigid size or how flexible they should be. The fixed
items (non flexible) take up their required size, and any remaining space is automatically distributed
among theflexible items.
In the ToH app, we apply this flexbox layout to our controls panel. The controls panel has two sub
pieces, the buttons/controls (4.1) and game status (4.2). The default Windows 8 metro slider input
controls for HTML5/JavaScript are of fixed size. So we combine all buttons, input slider controls into
one “fixed” (non-flex) piece, and keep the status section (which has game moves, time elapsed, and
game status items) to take up all the remaining space automatically (flexible item). Please see the
flexbox CSS3 markup below for the “controls” (piece #4) panel.
#pole1 { -ms-grid-column: 2; -ms-grid-row: 1; } #pole2 { -ms-grid-column: 3; -ms-grid-row: 1; } #pole3 { -ms-grid-column: 4; -ms-grid-row: 1; }
.controls { -ms-grid-column: 1; -ms-grid-row: 2; -ms-grid-column-span: 5; display: -ms-flexbox; -ms-flex-align: center; -ms-flex-pack: start; -ms-flex-wrap: wrap; color: hsl(30, 88%, 50%);
}
To further customize the status box (which is now a flexible item inside the “controls” flexbox), we
make it another flexbox. This is another nice feature of these advanced grid and flexbox layouts.
They can be nested!
Below is the CSS3 flexbox markup for the status item (piece #4.2).
As seen above, we make this status piece a flexible item (-ms-flex :1 ) and further set its display to “-
ms-flexbox”. This allows the pieces inside the status element (game moves, elapsed time, and game
status) to automatically flex their size as needed. Based on testing the app in different views, it was
required to mark the game status as a flexible item, keeping game moves and elapsed time as non-
flexible. Below is the markup. The first one is for non-flexible game moves/elapsed time. The second
item is the flexible game status message with –ms-flex: auto.
.controls { -ms-grid-column: 1; -ms-grid-row: 2; -ms-grid-column-span: 5; display: -ms-flexbox; -ms-flex-align: center; -ms-flex-pack: start; -ms-flex-wrap: wrap; color: hsl(30, 88%, 50%);
}
#status { display: -ms-flexbox; -ms-flex: 1; -ms-flex-align: start; -ms-flex-pack: start; margin: 0.5rem; font-size: 1.5rem; -ms-flex-wrap: wrap;
}
.gsts { -ms-flex: none; margin: 0.5rem; text-align: center; } .gstsmsg { margin: 0.5rem; -ms-flex: auto; text-align: left;
}
Flexbox, in general, is capable of much more. Please refer to the document below for more details on
flexbox:
http://dev.w3.org/csswg/css3-flexbox/
To summarize, our sample app uses one grid layout and two flexbox layouts. App UI pieces 1, 2, 3, 4,
4.1, and 4.2 (please refer previous screenshots with annotations) all are inside the main grid layout. UI
piece 4 has its own flexbox to manage pieces 4.1 and 4.2. Further, we need flexibility inside UI piece
4.2, which also uses another flexbox (this flexbox is the child of the previous flexbox, which itself is a
child of the main grid layout!)
With these app layouts configured, our sample app is ready to respond to orientation or view changes.
Using Media Queries
CSS3 layout features provide excellent capabilities and flexibility to configure app layouts. But we
need a way to know when the user rotates the device into portrait mode, or when the user changes
the metro app view to a filled or snapped view mode.
HTML5/CSS3 Media Queries provide this capability. Windows 8 Metro style apps further integrated
snapped and filled views inside CSS3 media queries as well. So the media queries cover all
orientations and view possibilities on devices running Windows 8 Metro style apps.
Media queries let developers define or override element styles based on view state and orientation
changes.
For example, in the snapped view portion of our sample app, we want to hide game controls/buttons,
and just display the status panel. We can define a new media query rule and override the
corresponding element’s display property to none, as shown in the code snippet below.
Whenever the device enters the snapped view, this style rule (display : none) will be automatically
applied to that element.
@media screen and (-ms-view-state: snapped) { .gctrl {
display: none;
}
Media queries are very powerful and easy to use. Complex app layout changes can be achieved for
different view states. More detailed information on media queries and how to use them is available
here:
http://www.w3.org/TR/css3-mediaqueries/
For the ToH app, we designed most of our element sizes and layout sizes size based on a relative font
size (rem –root em metric). This metric will apply relative size of the main root font size (defined
inside root “html” element). So in our media queries, we just have to change this root element font
size, and everything will automatically resize relative to it.
For example, in snapped view the space is very limited even for higher resolutions. So we would apply
a media query like the one below:
The above rules will be applied based on the minimum display height (1920 or 2500px). Since the
root font-size changed, all the corresponding element and layout sizes that used “rem” metric, will
automatically scale/resize as well (this includes our grid layout sizes).
Another important scenario is that of portrait and snapped views in general. They both have the
vertical display (landscape width becomes the height), and screen width of the device is reduced. In
our sample app, this complicates our position of towers. We need to position the towers in vertical
alignment, one below each. Since both of these views require this, we can combine the media queries
for them with a “,” in between (so you can combine several media queries into one as needed). Please
see the media query markup for this scenario below:
@media screen and (-ms-view-state: snapped) and (min-height:2500px) { html { font-size: 15px; } } @media screen and (-ms-view-state: snapped) and (min-height:1920px) { html { font-size: 11px; }
}
We redefine our grid layout to contain a single big column with more rows (one each for the towers,
and one for controls). These layouts will be automatically applied when the device goes into a
snapped or portrait views.
If users need to further customize the snapped view, they could define another media query after the
above query. For example, in the ToH, app we need to use all the available space so we set columns 1
and 3 to 0 size, and leave one big main column (column 2) as shown below:
@media screen and (-ms-view-state: fullscreen-portrait), screen and (-ms-view-state: snapped) { #gameHost { width: 100%; height: 100%; display: -ms-grid; -ms-grid-columns: 4rem 1fr 4rem; -ms-grid-rows: 1fr 1fr 1fr 19rem; } .controls { -ms-grid-column: 1; -ms-grid-row: 4; -ms-grid-column-span: 3; display: -ms-flexbox; -ms-flex-align: center; -ms-flex-pack: start; color: hsl(30, 88%, 50%); -ms-flex-wrap: wrap; } #pole1 { -ms-grid-column: 2; -ms-grid-row: 1; } #pole2 { -ms-grid-column: 2; -ms-grid-row: 2; } #pole3 { -ms-grid-column: 2; -ms-grid-row: 3; } .disk { height: 1.6rem; margin-left: auto; margin-right: auto; border: 1px solid #666666; border-radius: 1rem 1rem;
These rules will override the ones defined for the snapped view earlier in the CSS markup.
Similarly, users can apply different style rules depending on the required views or orientations, by
using appropriate media queries for them.
Putting It All Together and Validating It in Windows 8 Simulator
The ToH app now has flexible and adaptive layouts, which respond to any device orientation or
system view state(s). Developers can use the Windows 8 Simulator to validate the app for all use
cases. Currently, the simulator supports the screen sizes below:
@media screen and (-ms-view-state: snapped) { #gameHost { -ms-grid-columns: 0px 1fr 0px; -ms-grid-rows: 1fr 1fr 1fr 14rem; } #status { -ms-flex: 1; } .gctrl { display: none; } html { font-size: 8px; } .disk { height: 1.9rem; }
}
It can emulate different view states as well: portrait, filled, or snapped views. We can combine both
screen sizes and views to come up with several combinations for testing. Not all combinations are
valid, for example, there are no snapped/filled views in portrait mode.
The simulator can be chosen as the debug target inside Visual Studio, which will automatically start
the simulator and launch the app inside. The simulator has buttons to rotate the device 360 degrees,
so we can test all orientations. We can choose the check box for the required device screen
resolution. For example, in the screenshot below we show a test case for 27’’ 2560x1440 device in
portrait mode (which is not that common)—just shows what’s possible with the simulator.
Developers can use Blend in Visual Studio during design and development stages and finally verify
their apps inside the simulator (for another level of verification).
Summary
With Windows 8 and Metro style apps, developers can target different form-factor devices from
tablets to big screen devices. Developing HTML5/JavaScript Metro style apps that are flexible and
adaptive to multiple devices is critical. In this article we discussed the challenges of different screen
sizes, Windows 8 Metro views, device orientations and how to solve them. We used a sample app as a
case study to demonstrate how to apply the latest HTML5/CSS3 features like grid layout, flexbox,
and Media Queries. These features allow us to implement our solution entirely in presentation layer
(HTML5/CSS3). Developers are encouraged to take advantage of these features, to make their apps
work on different form-factor devices, and comply with Metro guidelines like “Snap and scale
beautifully”.
Notices
INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL
PRODUCTS. NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO
ANY INTELLECTUAL PROPERTY RIGHTS IS GRANTED BY THIS DOCUMENT. EXCEPT
AS PROVIDED IN INTEL'S TERMS AND CONDITIONS OF SALE FOR SUCH PRODUCTS,
INTEL ASSUMES NO LIABILITY WHATSOEVER AND INTEL DISCLAIMS ANY EXPRESS
OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL PRODUCTS
INCLUDING LIABILITY OR WARRANTIES RELATING TO FITNESS FOR A PARTICULAR
PURPOSE, MERCHANTABILITY, OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR
OTHER INTELLECTUAL PROPERTY RIGHT.
UNLESS OTHERWISE AGREED IN WRITING BY INTEL, THE INTEL PRODUCTS ARE
NOT DESIGNED NOR INTENDED FOR ANY APPLICATION IN WHICH THE FAILURE OF
THE INTEL PRODUCT COULD CREATE A SITUATION WHERE PERSONAL INJURY OR
DEATH MAY OCCUR.
Intel may make changes to specifications and product descriptions at any time,
without notice. Designers must not rely on the absence or characteristics of any
features or instructions marked "reserved" or "undefined." Intel reserves these for
future definition and shall have no responsibility whatsoever for conflicts or
incompatibilities arising from future changes to them. The information here is subject
to change without notice. Do not finalize a design with this information.
The products described in this document may contain design defects or errors known
as errata which may cause the product to deviate from published specifications.
Current characterized errata are available on request.
Contact your local Intel sales office or your distributor to obtain the latest
specifications and before placing your product order.
Copies of documents which have an order number and are referenced in this
document, or other Intel literature, may be obtained by calling 1-800-548-4725, or
go to: http://www.intel.com/design/literature.htm
Software and workloads used in performance tests may have been optimized for
performance only on Intel microprocessors. Performance tests, such as SYSmark and
MobileMark, are measured using specific computer systems, components, software,
operations, and functions. Any change to any of those factors may cause the results
to vary. You should consult other information and performance tests to assist you
in fully evaluating your contemplated purchases, including the performance of that
product when combined with other products.
Any software source code reprinted in this document is furnished under a software
license and may only be used or copied in accordance with the terms of that license.
Intel, Ultrabook, and the Intel logo are trademarks of Intel Corporation in the US
and/or other countries.
Copyright © 2012 Intel Corporation. All rights reserved.
*Other names and brands may be claimed as the property of others.
**This sample source code is released under the Intel Sample Source Code License Agreement