« Atrás

Liferay.com, mobile sites and responsive layouts

22 de mayo de 2011 Por Nate Cavanaugh

Bryan recently blogged about the new site design and how Liferay.com is displaying a mobile formatted website for different types of devices (go ahead and test it out, hop into any browser and resize the page as small as it can go). Today I want to discuss a bit how we achieved this from a technical level. This is one of the most common questions I not only got from people who attended our East Coast Symposium, but also inside of Liferay from other devs.

Liferay.com can resize from desktop to mobile dynamically

Because we like to keep our ear to the ground on all things front end, we’ve actually been following the discussion/debate about responsive web design since Ethan Marcotte published his article on the subject last year. If you haven’t read the article, the tl;dr version is that using CSS media queries, it’s possible to pass a different set of CSS styles to different devices and have a design that’s customized for a specific browser/device size.

As far as mobile strategies go, it’s probably the easiest to implement, and there are a lot of quick wins with it. However, Jon Neal pointed out to me when we were first discussing this idea that there’s very little difference between using CSS media queries and just using Javascript to simulate the same thing.

I’ve since read other people bring up a similar point, and it’s a fair one. In fact, there are multiple issues with CSS media queries that make them cumbersome. For instance, let’s say we want to share some styling across two specific devices. It’s possible using the logical operators but even then, you end up with duplicate CSS (and it becomes much harder to read). And the fact that IE doesn’t support media queries was another major impediment to us using it, so we were going to need to use JavaScript anyways (either to add the CSS classnames or to parse mediaqueries).

So Jon wrote up a script that would handle this logic for us. Here’s how the script works: When the page is loaded or resized, the script checks the width of the window and it looks into an object of 4 major size specifications; 960, 720, 480, and 320.

What do those numbers mean? 960px is based on the uber-popular 960 grids which is a layout width that looks great on most desktop computers, and the iPad in landscape mode. 720px is a layout width that looks great when the iPad is in portrait mode. 480px is the width of the window of most smart phones in landscape mode. 320px is the width of the window of most smart phones in portrait mode.

The other great thing Jon came up with was to add greater-than and less-than css classes. I’ll show how this works in a second, but the idea is basically, you can not only target a specific device width, but also if it’s greater than or less than any of those above widths.

If your target device is 600x800, you can still target that device with the css classes.

With what Jon prototyped, I’ve created an Alloy module that codifies this so that it’s super easy to use (while at the same time, staying out of the way for users who don’t wish to use it).

For a quick and simple demo, open up the viewport demo (if you view it in Chrome or Safari, Firefox or Opera, you’ll see some cool CSS3 generated content/animation, but the demo works in any browser).

To get the module to run, all you need to do is call: AUI().use('aui-viewport') in a script tag anywhere on your page.

Now you can target your site design to specific device sizes. Let’s say we want to give our navigation items to sit side by side when we view on the ipad or larger, but that we want to have them stack on smart phones:

#navigation li {
    display: inline;
    float: left;
}
.aui-view-lt720 #navigation li {
    display: block;
    float: none;
}

or let’s say we don’t want to make sure our images don’t exceed a certain width on the iPad in portrait mode

.aui-view-720 img {
    max-width: 300px
}

Or perhaps we want to target just portrait mode of smartphones and tablets:

.aui-view-720 body, .aui-view-320 body {
    background: #ccc;
}

You can even combine this with our other browser selectors to target very specific browsers:

.touch.aui-view-lt720 {} /* Touch based smartphones */
.webkit.aui-view-lt960 {} /* Webkit based tablets and smartphones */
.win.aui-view-720 {} /* Smaller browser views on just Windows */

Now, how is the logic applied? If the screen is equal to or between any of our defined widths, it will get this CSS class: aui-view-{WIDTH}. And, if the screen is greater than any of our widths, it will also get: aui-view-gt{WIDTH}. Lastly, if the screen is less than any of our widths, it will also get: aui-view-lt{WIDTH}.

So a window size of 1900x1200 would get:

aui-view-gt320
aui-view-gt480
aui-view-gt720
aui-view-gt960
aui-view-960

whereas a window size of 800x600 would get:

aui-view-gt320
aui-view-gt480
aui-view-gt720
aui-view-720
aui-view-lt960

Notice that the classes represent the width rounded down to the nearest division. This is to guarantee that your styled layout won’t exceed the current width. Because of that the css class doesn’t exactly represent the current width, but rather enforces you to think about the layout at specified sizes and devices.

Caveats

Life is not all cheese and bananas with this system, as there are some caveats to be aware of:

  • You are delivering the same content to all devices.

    Depending on the project, this could either seal the deal or break it. There’s an added cost to shipping down different images for the same page, and some mobile websites may wish to send only a very limited set of content to mobile devices (or perhaps very targeted content). The answer to this then is decide which of the 2 strategies you wish to use for your specific project: same content for all devices, but dimension specific designs, or redirect to a mobile/touch specific community that serves a targeted set of content and design.

  • Designs can require more planning for each of the design layouts

    You’ll notice that the design now has to accommodate basically 4 different views: desktop, tablet(portrait), and smartphone (portrait and landscape). This of course means thinking about a different set of design compromises and layouts for how the same content should fit (or which content should be hidden) for different types of views. Of course, this caveat extends to both content strategies, but having the same content automatically in every view often requires a bit more forethought during the design process.

How can you get this module?

If you’re an Enterprise Edition customer, this module will be available in the 6.0 SP2 service pack (and the great part is, if you don’t want to use it, it will have 0 affect on your application). If you’re running Community Edition, this will be in Liferay 6.1 or if you’re running trunk of Liferay you can see it today. We’ll also be releasing another version of AlloyUI soon that will have it included.

Conclusions

Overall, the response has been great, and the design/development process was surprisingly smooth. I would recommend it as a general principle for your design, as it helps our designs fit the fluid nature of the web.

More information

Responsive Web Design by Ethan Marcotte
MediaQueri.es
The practicalities of CSS Media Queries, lessons learned.

Mostrando 19 Comentarios

Deb Troxel
23/05/11 7:45

Thanks Nate! Your blogs are always packed with great info.

Szymon Gołębiewski
24/05/11 1:30

Nice article Nate. One question - does mobile theme works with all portlet or am I limited to just some of them?

wasim shaikh
24/05/11 3:15

Thanks nate, nice article.
Is there any YUI plugin availale for this? I want to use it in simple htmls.

Thanks,
Wasim Shaikh,
http://microblog.wasimshaikh.com

Nate Cavanaugh
24/05/11 7:49

@Szymon:
In this case, it can work with any of them. Basically, it just depends on what portlets you'll style in which view. For some mobile devices, some portlets might make less sense (for instance, a flash portlet wouldn't work so well on most smart phones these days). But since its just CSS, the possibilities are pretty wide emoticon

@wasim:
Not yet, but I'll be pushing this one over to the YUI Gallery, so as soon as it's up, I can let you know emoticon

Thanks all!

Jay Patel
25/05/11 5:05

Nice article Nate..Thanks for sharing...

Shagul Khajamohideen
2/06/11 3:28

Thanks Nate. This is a great step. I guess Jorge and team are addressing the different content for different devices part.

Jignesh Vachhani
12/06/11 22:15

Very Nice Demo and Article Nate !!!! Thanks

Gem E
3/08/11 16:51

This is a great feature and I got it to work nicely on my liferay except that it isn't getting picked up on the iphone (haven't tried it on an ipad yet). I noticed the viewport demo doesn't work correctly on the iphone either (it's being treated as desktop size 960px) - do you know why this may be?

Hossein Oloomi
13/11/11 7:15

Dear Nate,
<br>
I want to use my own JavaScript calendar and date picker instead of aui-calendar and aui-datepicker all over Liferay. I want to replace my js files with those of aui, but clearly this will not work; what functions should my files have and what should they return?
<br>
Thanks in advance

Suraj Bihari
15/11/11 13:25

Thanks for providing this helpful tutorial on responsive layouts. Olaf tipped this during the developer course!

Nagendra Kumar Busam
12/12/11 23:14

Really gr8 stuff emoticon

Ben Chapman
16/12/11 6:42

Nate,

Thanks very much for this; however, I must not be doing something quite right as it doesn't seem to have any effect on our pages.

Where would I put the call to AUI().use('aui-viewport')? I've tried doing it in the script section of the page (Manage>Page>Script), but that does not result in generating the expected classes in the HTML. We are EE customers and I can see that AUI().use... is inserted in the source of the HTML, but that's it.

Can you provide a pointer to further information?

Many thanks and sorry for the very basic question!

Nate Cavanaugh
16/12/11 12:10

Hi Ben,
Thanks for reaching out. The only thing I can think of that would cause this not to work is perhaps the version of EE you have isn't the latest service pack? This component was included in a service pack, so it's not available in earlier ones.
If you get in touch with your account rep, they can probably get you a patch that would include just the files you need for this feature.

If you are on the latest service pack and it's still no go, you can either get in touch with support to help debug your specific case, or you can create a forum thread and paste the link here and I'll take a look at it and see if I can spot anything.

Thanks Ben,

9/02/12 3:52

[...] Override  ServicePre() in ServicePreAction.java to incorporate check for the isMobile() and if found true use Wap theme. Override html/../layout/view/portlet.jsp to include check for isMobile() and if... [...] Read More

Dave Weitzel
8/03/12 8:02

Has this been carried over to 6.1? I do not see anything in CE 6.1 GA1. If not can someone write a log about the mobile device rules and what they are how to use them and examples?
Would prefer the view-port was there so we don't have to do much with more guidance on how to use in custom themes

Steve C Groninga
13/03/12 15:44

Nate this is really great stuff. Have you run into the following: works great on the desktop monitor (able to minimize browser window and the alternate css is used), but fails on an actual handheld device... ( iPhone, android, etc....)

Nate Cavanaugh
13/03/12 15:50

Hi Steve,
I have run into an issue on Retina screens where the reported size wasn't being properly handled.
In those cases, I had to set something like the following in the head of the document:
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" />

Let me know if that helps.

Thanks,

Nate Cavanaugh
13/03/12 15:51

And Dave, yes this module is inside of 6.1 as well. As long as you call AUI().use('aui-viewport') in your theme, you should be good to go.

HTH,

Steve C Groninga
16/03/12 10:33

Nate, Thanks for this tip! My initial tests seem to work perfectly! Now on to redesigning for these devices/smaller screens! Well Done! This certainly has a far reaching impact!

Steve

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