Design your web pages so that they adapt to the client viewport in which they are displayed. With responsive design, the same pages can be effectively displayed on multiple devices in both orientations. The following image demonstrates some ways in which a page can respond to changes in viewport size:

Layout: Use single-column layouts for smaller viewports, and multiple-column layouts for larger viewports.

Content: Include only the most important content when displaying on smaller devices.

Navigation: Device-specific tools are provided for accessing other pages.

Images: Serving image renditions that are appropriate for the client viewport. according to the window dimensions.

Develop CQ applications that generate HTML5 pages that adapt to multiple window sizes and orientations. For example, the following ranges of viewport widths correspond with various device types and orientations

Maximum width of 480 pixels (phone, portrait)

Maximum width of 767 pixels (phone, landscape)

Width between 768 pixels and 979 pixels (tablet, portrait)

Width between 980 pixels and 1199 pixels (tablet, landscape)

Width of 1200px or greater (desktop)

See the following topics for information about implementing responsive design behavior:

Using Media Queries

Media queries enable the selective use of CSS styles for page rendering. AEM development tools and features enable you to effectively and efficiently implement media queries in your applications.

The W3C group provides the Media Queries recommendation that describes this CSS3 feature and the syntax.

Creating the CSS File

In your CSS file, define media queries based on the properties of the devices that you are targeting. The following implementation strategy is effective for managing styles for each media query:

Use a ClientLibraryFolder to define the CSS that is assembled when the page is rendered.

Define each media query and the associated styles in separate CSS files. It is useful to use file names that represent the device features of the media query.

Define styles that are common to all devices in a separate CSS file.

In the css.txt file of the ClientLibraryFolder, order the list CSS files as is required in the assembled CSS file.

The Geometrixx Media sample uses this strategy to define styles in the site design. The /etc/designs/geometrixx-media/clientlibs folder is a ClientLibraryFolder. The following table lists the files in the css child folder.

File name

Description

Media Query

style.css

Common styles.

N/A

bootstrap.css

Common styles, defined by Twitter Bootstrap.

N/A

responsive-1200px.css

Styles for all media that are 1200 pixels wide or wider.

@media (min-width: 1200px) {
...
}

responsive-980px-1199px.css

Styles for media that are between 980 pixels and 1199 pixels wide.

@media (min-width: 980px) and (max-width: 1199px) {
...
}

responsive-768px-979px.css

Styles for media that are between 768 pixels and 979 pixels wide.

@media (min-width: 768px) and (max-width: 979px) {
...
}

responsive-767px-max.css

Styles for all media that are less than 768 pixels wide.

@media (max-width: 767px) {
...}

responsive-480px.css

Styles for all media that are less than 481 pixels wide.

@media (max-width: 480) {
...
}

The css.txt file in the /etc/designs/geometrixx-media/clientlibs folder lists the CSS files that the client library folder includes. The order of the files implements style precedence. Styles are more specific as the device size decreases.

Previewing for Specific Devices

See previews of your pages in different viewport sizes to test the behavior of your responsive design. In Preview mode, Sidekick includes a Devices drop-down menu that you use to select a device. When you select a device, the page changes to adapt to the viewport size.

To enable the device preview in Sidekick, you must configure the page and the MobileEmulatorProvider service. Another page configuration controls the list of devices that appears in the Devices list.

Adding the Devices List

The Devices list appears in Sidekick when your page includes the JSP script that renders the Devices list. To add the Devices list to Sidekick, include the /libs/wcm/mobile/components/simulator/simulator.jsp script in the head section of your page.

Name: com.day.cq.wcm.mobile.core.impl.MobileEmulatorProvider-alias
The -alias suffix is required because the MobileEmulatorProvider service is a factory service. Use any alias that is unique for this factory.

jcr:primaryType: sling:OsgiConfig

Add the following node property:

Name: mobile.resourceTypes

Type: String[]

Value: The paths to the page components that render your web pages. For example, the geometrixx-media app uses the following values:geometrixx-media/components/page
geometrixx-unlimited/components/pages/page
geometrixx-unlimited/components/pages/coverpage
geometrixx-unlimited/components/pages/issue

Specifying the Device Groups

To specify the device groups that appear in the Devices list, add a cq:deviceGroups property to the jcr:content node of the root page of your site. The value of the property is an array of paths to the device group nodes.

Device group nodes are located in the /etc/mobile/groups folder.

For example, the root page of the Geometrixx Media site is /content/geometrixx-media. The /content/geometrixx-media/jcr:content node includes the following property:

For device groups that you use for responsive design, edit the device group and on the General tab select Disable Emulator. This option prevents the emulator carousel from appearing, which is not relevent to responsive design.

Using Adaptive Images

You can use media queries to select an image resource to display in the page. However, every resource that uses a media query to conditionalize its use is downloaded to the client. The media query merely determines whether the downloaded resource is displayed.

For large resources such as images, downloading all resources is not an efficient use of the client's data pipeline. To selectively download resources, use javascript to initiate the resource request after the media queries perform the selection.

The following strategy loads a single resource that is chosen using media queries:

Add a DIV element for each version of the resource. Include the URI of the resource as the value of an attribute value. The browser does not interpret the attribute as a resource.

Add a media query to each DIV element that is appropriate for the resource.

When the document loads or the window is resized, javascript code tests the media query of each DIV element.

Based on the results of the queries, determine which resource to include.

Insert an HTML element in the DOM that references the resource.

Evaluating Media Queries using javascript

Implementations of the MediaQueryList interface that the W3C defines enable you to evaluate media queries using javascript. You can apply logic to the media query results and execute scripts that are targeted for the current window:

Browsers that implement the MediaQueryList interface support the window.matchMedia() function. This function tests media queries against a given string. The function returns a MediaQueryList object that provides access to the query results.

For browsers that do not implement the interface, you can use a matchMedia() polyfill, such as matchMedia.js, a freely-available javascript library.

Selecting Media-Specific Resources

The W3C-proposed picture element uses media queries to determine the source to use for image elements. The picture element uses element attributes to assocate media queries with image paths.

The freely-available picturefill.js library provides similar functionality as the proposed picture element, and uses a similar strategy. The picturefill.js library calls window.matchMedia to evaluate the media queries that are defined for a set of div elements. Each div element also specifies an image source. The source is used when the media query of the div element returns true.

The picturefill.js library requires HTML code that is similar to the following example:

Create a component that generates the required div elements that the picturefill.js code expects. In an AEM page, the value of the data-src attribute is the path to a resource in the repository. For example, a page component can hard-code the media queries and the associated paths for image renditions in DAM. Or, create a custom Image component that enables authors to select image renditions or specify runtime rendering options.

The following example HTML selects from 2 DAM renditions of the same image.

Script that generates the HTML: /libs/foundation/components/adaptiveimage/adaptiveimage.jsp

The subsequent section provides details about this component.

Understanding Image Rendering in AEM

To customize image rendering, you should understand the default AEM static image rendering implementation. AEM provides the Image component and an image-rendering servlet that work together to render images for web page. The following sequence of events occur when the Image component is included in the the page's paragraph system:

Authoring: Authors edit the Image component to specify the image file to include in an HTML page. The file path is stored as a property value of the Image component node.

Page request: The JSP of the page component generates the HTML code. The JSP of the Image component generates and adds an img element to the page.

Image request: The web browser loads the page, and requests the image according to the src attribute of the img element.

Image rendering: The image-rendering servlet returns the image to the web browser.

For example, the JSP of the Image component generates the following HTML element:

When the browser loads the page, it requests the image using the value of the src attribute as the URL. Sling decomposes the URL:

Resource: /content/mywebsite/en/_jcr_content/par/image_0

File name extension: .jpg

Selector: img

Suffix: 1358372073597.jpg

The image_0 node has a jcr:resourceType value of foundation/components/image, which has a sling:resourceSuperType value of foundation/components/parbase. The parbase component includes the img.GET.java script that matches the selector and the file name extension of the request URL. AEM uses this script (servlet) to render the image.

To see the source code of the script, use CRXDE Lite to open the /libs/foundation/components/parbase/img.GET.java
file.

Scaling Images for the Current Viewport Size

Scale images at runtime according to the characteristics of the client viewport to provide images that conform to the principles of responsive design. Use the same design pattern as static image rendering, using a servlet and an authoring component.

The component needs to perform the following tasks:

Store the path and desired dimensions of the image resource as property values.

Generate div elements that contain media selectors and service calls for rendering the image.

Note: The web client uses the matchMedia and Picturefill javascript libraries (or similar libraries) to evaluate the media selectors.

The servlet that processes the image request needs to perform the following tasks:

Retrieve the path and dimensions of the image from the component properties.

Scale the image according to the properties and return the image.

Available Solutions

AEM installs the following implementations that you can use or extend.

The Adaptive Image foundation component that generates media queries, and HTTP requests to the Adaptive Image Component Servlet that scales the images.

Understanding the Adaptive Image Component

The Adaptive Image foundation component generates calls to the Adaptive Image Component Servlet to render an image that is sized according to the device screen. The component includes the following resources:

The value of the data-scr attribute is a URL that Sling resolves to the Adaptive Image Component Servlet that renders the image. The data-media attribute contains the media query that is evaluated against the client properties.

The following HTML code is an example of the div elements that the JSP generates:

The service name on the Configuration tab is Adobe CQ Adaptive Image Component Servlet

com.day.cq.wcm.foundation.impl. AdaptiveImageComponentServlet

Property

Supported Widths

To add a supported width, click a + button and enter a positive integer.

To remove a supported width, click the associated - button.

To modify a supported width, edit the field value.

adapt.supported.widths

The property is a multivalued String value.

Implementation details

The com.day.cq.wcm.foundation.impl.AdaptiveImageComponentServlet class extends the AbstractImageServlet class. The AdaptiveImageComponentServlet source code is located in the /libs/foundation/src/impl/src/com/day/cq/wcm/foundation/impl folder.

The class uses Felix SCR annotations to configure the resource type and file extension that the servlet is associated with, and the name of the first selector.

The AbstractImageServlet class provides the doGet method that processes the HTTP request. This method determines the resource that is associated with the request, retrieves resource properties from the repository, and returns them in an ImageContext object.

The AdaptiveImageComponentServlet class overrides the createLayer method. The method obtains the path of the image resource and the requested image width from the ImageContext object. It then calls the methods of the info.geometrixx.commons.impl.AdaptiveImageHelper class, which performs the actual image scaling.

The AdaptiveImageComponentServlet class also overrides the writeLayer method. This method applies the JPEG quality to the image.

Image Reference Modification Servlet (Geometrixx Common)

The sample Image Reference Modification Servlet generates size attributes for the img element to scale an image on the web page.

Calling the servlet

The servlet is bound to cq:page resources and supports the .jpg file extension. The servlet selector is image. Therefore, Sling resolves HTTP request URLs of the following format to this servlet:

Three additional selectors specify the requested image width, height, and (optionally) quality. The following example requests an image of width 770 pixels, height 360 pixels, and of medium quality.

http://localhost:4502/content/geometrixx/en.image.770.360.MEDIUM.jpg

Supported image properties

The servlet accepts a finite number of image dimensions and quality values.

The following values are supported by default (widthxheight):

256x192

370x150

480x200

127x127

770x360

620x290

480x225

320x150

375x175

303x142

1170x400

940x340

770x300

480x190

The following values for image quality are supported:

low

medium

high

When working with AEM there are several methods of managing the configuration settings for such services; see Configuring OSGi for full details.

Specifying the image resource

The image path, dimensions, and quality values must be stored as properties of a node in the repository:

The node name is image.

The parent node is the jcr:content node of a cq:page resource.

The image path is stored as the value of a property named fileReference.

When authoring a page, use Sidekick to specify the image and add the image node to the page properties:

In Sidekick, click the Page tab, and then click Page Properties.

Click the Image tab and specify the image.

Click OK.

Implementation details

The info.geometrixx.commons.impl.servlets.ImageReferenceModificationServlet class extends the AbstractImageServlet class. If you have the cq-geometrixx-commons-pkg package installed, the ImageReferenceModificationServlet source code is located in the /apps/geometrixx-commons/src/core/src/main/java/info/geometrixx/commons/impl/servlets folder.

The class uses Felix SCR annotations to configure the resource type and file extension that the servlet is associated with, and the name of the first selector.

The AbstractImageServlet class provides the doGet method that processes the HTTP request. This method determines the resource that is associated with the call, retrieves resource properties from the repository, and saves them in an ImageContext object.

The ImageReferenceModificationServlet class overrides the createLayer method and implements the logic that determines the image resource to render. The method retrieves a child node of the page's jcr:content node named image. An Image object is created from this image node, and the getFileReference method returns the path to the image file from the fileReference property of the image node.

Developing a Fluid Grid

AEM enables you to efficiently and effectively implement fluid grids. This page explains how you can integrate your fluid grid or an existing grid implementation (such as Bootstrap) into your AEM application.

If you are not familiar with fluid grids, see the Introduction to Fluid Grids section at the bottom of this page. This introduction provides an overview of fluid grids and guidance for designing them.

Defining the Grid Using a Page Component

Use page components to generate the HTML elements that define the content blocks of the page. The ClientLibraryFolder that the page references provides the CSS that controls the layout of the content blocks:

Note: When a component includes multiple cq:include elements that reference the parsys component, each path attribute must have a different value.

Scaling the Page Component Grid

The design that is associated with the geometrixx-media page component (/etc/designs/geometrixx-media) contains the clientlibs ClientLibraryFolder. This ClientLibraryFolder defines CSS styles for row-fluid classes, span* classes, and span* classes that are children of row-fluid classes. Media queries enable styles to be redefined for different viewport sizes.

The following example CSS is a subset of those styles. This subset focuses on span12, span8, and span4 classes, and media queries for two viewport sizes. Notice the following characteristics of the CSS:

The .span styles define element widths using absolute numbers.

The .row-fluid .span* styles define element widths as percenteages of the parent. Percentages are calculated from the absolute widths.

Repositioning Content in the Page Component Grid

The pages of the sample Geometrixx Media application distribute rows of content blocks horizontally in wide viewports. In smaller viewports, the same blocks are distributed vertically. The following example CSS shows the styles that implement this behavior for the HTML code that the media-home page component generates:

The default CSS for the media-welcome page assigns the float:left style for span* classes that are inside row-fluid classes.

Media queries for smaller viewports assign the float:none style for the same classes.

Tip: Modularize Your Page Components

Modularize your components to make efficient use of the code. Your site likely uses several different types of pages, such as a welcome page, an article page, or a product page. Each type of page contains different types of content and likely use different layouts. However, when certain elements of each layout are common across multiple pages, you can re-use the code that implements that part of the layout.

Use page component overlays

Create a main page component that provides scripts for generating the various parts of a page, such as head and body sections, and header, content, and footer sections within the body.

Create other page components that use the main page component as the cq:resourceSuperType. These components include scripts that override the scripts of the main page as needed.

For example, the goemetrixx-media application includes the page component (the sling:resourceSuperType is the foundation page component). Several child components (such as article, category, and media-home) use this page component as the sling:resourceSuperType. Each child component includes a content.jsp file that overrides the content.jsp file of the page component.

Re-use scripts

Create multiple JSP scripts that generate row and column combinations that are common for mulitple page components. For example, the content.jsp script of the article and media-home components both reference the 8x4col.jsp script.

Organize CSS styles by targeted viewport size

Include CSS styles and media queries for different viewport sizes in separate files. Use client library folders to concatenate them.

Inserting Components into the Page Grid

When components generate a single block of content, generally the grid that the page component establishes controls the placement of the content.

Authors should be aware that the content block can be rendered in various sizes and relative positions. Content text should not use relative directions to refer to other content blocks.

If necessary, the component should provide any CSS or javascript libraries that are required for the HTML code that it generates. Use a client library folder inside the component to generate the CSS and JS files. To expose the files, create a dependency or embed the library in another client library folder below the /etc folder.

Sub-grids

If the component contains multiple blocks of content, add the content blocks inside a row to establish a sub-grid on the page:

Use the same class names as the containing page component to express div elements as rows and content blocks.

To override the behavior that the page design's CSS implements, use a second class name for the row div element and provide the associated CSS in a client library folder.

For example, the /apps/geometrixx-media/components/2-col-article-summary component generates two columns of content. The HTML that it generates has the following structure:

The .row-fluid .span6 selectors of the page's CSS applies to the div elements of the same class and structure in this HTML. However, the component also includes the /apps/geometrixx-media/components/2-col-article-summary/clientlibs client library folder:

The CSS uses the same media queries as the page component to establish changes in layout at the same discrete page widths.

Selectors use the multi-col-article-summary class of the row div element to override the behavior of the page's row-fluid class.

For example, the following styles are included in the /apps/geometrixx-media/components/2-col-article-summary/clientlibs/css/responsive-480px.css file:

Introduction to Fluid Grids

Fluid grids enable page layouts to adapt to the dimensions of the client viewport. Grids consist of logical columns and rows that position the blocks of content on the page.

Columns determine the horizontal positions and widths of content blocks.

Rows determine the relative vertical positions of content blocks.

Using HTML5 technology you can implement the grid and manipulate it to adapt page layouts to different viewport sizes:

HTML div elements contain blocks of content that span a certain number of columns.

One or more of these div elements comprise a row when they share a common parent divelement.

Using Discrete Widths

For each range of viewport widths that you are targeting, use a static page width and content blocks of constant width. When manually resizing a browser window, changes to content size occur at discrete window widths (also known as breakpoints). Consequently, page designs are more closely adhered to, maximizing the user experience.

Scaling the Grid

Use grids to scale content blocks to adapt to different viewport sizes. Content blocks span a specific number of columns. As column widths increase or decrease to fit different viewport sizes, the width of the content blocks increase or decrease accordingly. Scaling can support both large- and medium-sized viewports that are wide enough to accommodate the side-by-side placement of content blocks.

Repositioning Content in the Grid

The size of content blocks can be constrained by a minimum width, beyond which scaling is no longer effective. For smaller viewports, the grid can be used to vertically distribute blocks of content rather than horizontally.

Designing The Grid

Determine the columns and rows that you need to position the blocks of content on your pages. Your page layouts determine the number of columns and rows that span your grid.

Number of columns

Include enough columns to horizontally position the content blocks in all of your layouts, for all viewport sizes. You should use more columns than are currently needed to accommodate future page designs.

Row contents

Use rows to control the vertical positioning of content blocks. Determine the content blocks that share the same row:

Content blocks that are located next to each other horizontally in any of the layouts are in the same row.

Content blocks that are located next to each other horizontally (wider viewports) and vertically (smaller viewports) are in the same row.

Grid Implementations

Create CSS classes and styles to control the layout of the content blocks on a page. Page designs are often based on the relative size and position of content blocks within the viewport. The viewport determines the actual size of the content blocks. Your CSS needs to account for the relative and the absolute sizes. You can implement a fluid grid using three types of CSS classes:

A class for a div element that is a container for all rows. This class sets the absolute width of the grid.

A class for div elements that represent a row. This class controls the horizontal or vertical positioning of the content blocks that it contains.

Classes for div elements that represent blocks of content of different widths. Widths are expressed as a percentage of the parent (the row).

Targeted viewport widths (and their associated media queries) demarcate discrete widths that are used for a page layout.

Widths of Content Blocks

Generally, the width style of content block classes are based on the following characteristics of your page and grid:

The absolute page width that you are using for each targeted viewport size. These are known values.

The absolute width of the grid columns for each page width. You determine these values.

The relative width of each column as a percentage of the total page width. You calculate these values.

The CSS includes a series of media queries that use the following structure:

Use the following algorithm as a starting point for developing the element classes and CSS styles for your pages.

Define a class name for the div element that contains all rows, for example content.

Define a CSS class for div elements that represent rows, such as row-fluid.

Define class names for content block elements. A class is required for all possible widths, in terms of column spans. For example, use the span3 class for div elements that span 3 columns, use span4 classes for spans of 4 columns. Define as many classes as there are columns in your grid.

For each viewport size that you are targeting, add the corresponding media query to your CSS file. Add the following items in each media query:

Add the style to the .row-fluid selector inside each media query. Set the value according to the page layout that you are using for that media query. For example, the following diagram illustrates a row that distributes content horizontally for wide viewports, and vertically for narrow viewports.

Assigning Classes to Content Blocks

For the page layout of each viewport size you are targeting, determine the number of columns that each content block spans. Then, determine which class to use for the div elements of those content blocks.

When you have established the div classes, you can implement the grid using your AEM application.