Mastering Mobile Weather UI: REM Layout, Flexbox, Canvas & Performance Hacks
This article walks through the development of the HandQ Weather H5 page, covering REM‑based responsive layout, Flexbox sectioning, HTML5 canvas charts and animations, CSS3 transitions, and a suite of performance and compatibility optimizations for mobile browsers.
Introduction
HandQ Weather is a feature added in QQ version 6.0 and above. The page displays the current temperature, a five‑day temperature line chart, a 24‑hour temperature chart, and eight different weather animations such as rain, snow, clouds, and sunlight.
1. REM Overall Layout
For mobile devices, resolution adaptation is a common problem. Designers usually provide a visual draft based on iPhone 6 (750 px). Using REM for the whole layout is an excellent solution.
What is REM?
rem (root element font size) is a relative unit that depends on the font size of the root element.
Basic Syntax
/* Define html root element font size */
html {
font-size: 10px;
}
/* Use rem for child elements */
.sonDom {
width: 6rem; /* 6 × 10 = 60 px */
height: 3rem; /* 3 × 10 = 30 px */
line-height: 3rem;
font-size: 1.2rem; /* 1.2 × 10 = 12 px */
border-radius: .5rem; /* 0.5 × 10 = 5 px */
}Because 1 rem equals the root element’s font‑size value , changing the root font-size proportionally changes all elements that use rem, achieving perfect resolution adaptation.
How to Change the Root Font‑Size Dynamically
Two common methods are used:
1. Media Queries
/* Default 20px */
html {font-size: 20px;}
@media only screen and (min-width: 320px) {html {font-size: 10px;}}
@media only screen and (min-width: 375px) {html {font-size: 16px;}}
@media only screen and (min-width: 414px) {html {font-size: 20px;}}2. JavaScript
// Set font size dynamically
var doc = document,
win = window;
function initFontSize() {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
var fontSizeRate = clientWidth / 375,
baseFontSize = 15 * fontSizeRate;
docEl.style.fontSize = baseFontSize + 'px';
};
recalc();
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
}2. Flexbox Local Layout
Previously, equal‑width layouts were achieved with floats or inline‑block, both requiring clearfixes or margin tweaks. CSS3 Flexbox offers a cleaner solution.
Compatibility
Modern Android and iOS browsers support Flexbox well, making it a safe choice for mobile development.
HandQ Weather Example
The page is divided into five equal parts, each occupying the same width.
HTML Structure
Flexbox CSS
/* Set container as flexbox */
.info-day-list {
display: -webkit-box;
padding: 1rem 0;
}
/* Set each item */
.info-day-item {
-webkit-box-flex: 1; /* equal proportion */
width: 1%;
font-size: 1.4rem;
line-height: 3rem;
text-align: center;
}All items have box-flex: 1, so they share the remaining space equally.
Flexbox Pitfalls
1. Uneven Width Due to Text Length
When the weather description length varies (e.g., "southwest wind" vs. "light breeze"), the items may not divide evenly. Setting a uniform width: 1% on the child elements resolves the issue.
3. HTML5 Canvas
Complex animations such as temperature line charts, rain, and snow are more performant when drawn on a canvas instead of manipulating the DOM.
Line Chart
Rain & Snow Animation
Canvas Pitfalls
1. High‑DPI Blur
On retina screens, the canvas appears blurry because the device pixel ratio (DPR) is greater than 1. The solution is to scale the canvas size according to devicePixelRatio:
// Adjust canvas for high‑DPI screens
var c = document.getElementById("canvas");
var DPR = window.devicePixelRatio;
// Assume canvasWidth and canvasHeight are the CSS dimensions
c.width = canvasWidth * DPR;
c.height = canvasHeight * DPR;2. Memory Consumption
Canvas can consume a lot of memory, especially when many particles (rain drops, snowflakes) are rendered. Avoid creating multiple canvases and limit the number of particles on low‑end devices.
4. CSS3 Transition & Animation
Transitions and keyframe animations are used for interactive effects such as the zodiac slider.
Slider Example
.star-icon-outside-l {
z-index: 20;
-webkit-transform: translateX(-18.8rem) scale(.673);
transform: translateX(-18.8rem) scale(.673);
}
/* ... other icon classes omitted for brevity ... */Keyframe Examples
@-webkit-keyframes toggleShow {
0% {opacity: 0;}
11% {opacity: 0;}
12.5%{opacity: 1;}
20% {opacity: 0;}
100% {opacity: 0;}
}
@-webkit-keyframes shine {
0% {-webkit-transform: scale(1,1);}
50% {-webkit-transform: scale(1.2,1.2);}
100% {-webkit-transform: scale(1,1);}
}5. Performance Optimizations
Basic Animation Optimization
Prefer transform: translate() over left/right and use 3D acceleration where possible.
Use requestAnimationFrame
// Polyfill for requestAnimationFrame
window.requestAnimFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
function(callback) { return window.setTimeout(callback, 1000 / 30); };Canvas Optimization
Reduce particle count on low‑end phones by decreasing OPTS.maxNum when frame time exceeds a threshold.
// Reduce max number of drops if frame takes too long
if (new Date - lastTime > 30 && drops.length < OPTS.maxNum && OPTS.maxNum > 21) {
OPTS.maxNum -= 10;
}Memory Optimization
Pause the weather webview when it is hidden to save memory:
if (mqq && mqq.iOS && mqq.addEventListener) {
mqq.addEventListener("qbrowserVisibilityChange", function(e) {
cancelAnimationFrame(drp_ticker);
if (!e.hidden) { update(); }
});
}Caching
Store weather data in localStorage and reuse it on subsequent loads.
if (checkCache('weather-local_weather_info')) {
Page.processData(local_weather_info);
weather_info = local_weather_info;
} else {
Vinda.getData('data-weatherInfo', function(data) {
if (data && data.retcode == 0) {
Page.processData(data);
$.extend(data.result, {searchTime: +Date.now(), city: city});
$S.save({key: 'local_weather_info', value: data});
}
});
}Pre‑loading
DNS pre‑fetch: <link rel="dns-prefetch" href="//pub.idqqimg.com" /> CGI pre‑loading to fetch data before JS execution.
Code Optimizations
Reuse DOM objects for the zodiac slider (7 DOM nodes for 12 items) and load low‑weight modules asynchronously.
// Module definition
var Page = {};
var headerMod = {};
var timeDegreeMod = {};
var adsMod = {};
var detailMod = {};
var AnimationMod = {};
Page.render = function() {
headerMod.render();
timeDegreeMod.render();
detailMod.render();
adsMod.getAds();
require.async('./setAnimation', function(AMod) {
AnimationMod = AMod;
AnimationMod.init();
});
};Other Optimizations
Sprite sheets, file merging, resource compression, inline CSS/JS placed at the end to avoid render‑blocking.
6. Compatibility Issues
iOS App‑Ad Handling
When an ad is an iOS app download, a JSONP request retrieves the App Store link and launches the app via mqq.app.launchApp. Otherwise, a new webview is opened.
// Detect iOS app ad and launch
var isIosAppAds = mqq.iOS && mqq.device.isMobileQQ() && producttype == 19;
if (isIosAppAds) {
$.ajax({url: adsMod.jump_url, data: {acttype: 1}, dataType: 'jsonp', success: function(o) {
if (o && o.ret >= 0 && o.data && o.data.dstlink) {
mqq.app.launchApp({name: o.data.dstlink});
}
}});
} else {
mqq.ui.openUrl({url: adsMod.jump_url, target: 1, style: 0});
}X5 Kernel Compatibility
In X5 tbs.1x, pseudo‑elements cannot be animated and transition‑timing‑function: ease‑out is unsupported. Support improves in tbs.2x.
Non‑ Tag Jump Bug
On low‑end Android devices, click handlers on div elements may trigger the reporting request but not the navigation. Using an a tag resolves the issue.
7. Shortcomings
High memory consumption due to numerous animations and canvas usage, especially on low‑memory phones.
Animation rendering and code still need refinement; the author acknowledges many areas for improvement.
Conclusion
QQ Weather H5 was the author’s first independent project at Tencent. Although the project has been handed over, revisiting the code and its evolution continues to provide valuable learning experiences.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
