移動端使用者佈建字型放大導致的問題

來源:互聯網
上載者:User

標籤:代碼   ima   結果   api   adjust   瀏覽器   需要   listener   解決方案   

問題背景

很多webview提供了調整頁面字型大小的功能,例如手機QQ、、部分Android內建瀏覽器等。大部分瀏覽器調整字型只會導致字型顯示大小發生改變,其他元素的大小不受影響。但對於結構稍微複雜一點的頁面,字型大小的變動就足以導致頁面配置亂掉,導致文本不置中、文字折行、布局混亂等問題。

 

調整字型大小功能24-mobile-browser-font-size/1.png)

 

作為前端工程師,碰到頁面亂掉的情況就會覺得很無辜了,明明是你自己放大的字型,放大了卻還要我來承擔排版亂掉的後果,多委屈啊。很久以前,在PC端,好歹我們還可以提示使用者按CTLR + 0將頁面的比例調整回來,現在在移動端,卻很難阻止使用者縮放字型大小。

然而即使再委屈,當問題來了之後還是需要處理的,誰讓我們是前端工程師呢?(笑)

原理

由於並不是很清楚各個平台(瀏覽器)放大字型的機制,我分別諮詢了我們 iOS 和 Android 的同事,得知在調整字型大小時時,2個用戶端的處理方式不同。

iOS

iOS上需要調整 webview 的字型大小時,是通過給 body 設定 -webkit-text-size-adjust 屬性實現的:

 

iOS設定字型縮放代碼

 

既然這樣,我們應該可以通過JS取到這個屬性:

var body = document.body;alert(body.getAttribute(‘style‘));

 

iOS擷取樣式

 

圖上可以看到,當頁面文字被放大時,確實多了一個-webkit-text-size-adjust屬性。

Android

Android通過給 webview 設定字型的縮放來完成,具體的API是setTextZoom(int)

 

Android設定字型縮放代碼

 

我們通過一個demo頁面來查看效果:

 

Android設定字型縮放代碼

 

可以看到,文字確實是被放大了。例如“文字大小10px”這一段文字被放大了兩倍,隨文字一同被放大的還有以em為單位的尺寸和line-height

於是很自然地想到,我們是否可以取到這些屬性呢?

// 取元素的fontSizedocument.querySelector(‘.s10‘).style.fontSize;

結果很失望,取不到什麼有用的資訊。

按iOS的方式,也取不到任何有用的樣式,可見Android webview中並不是使用-webkit-text-size-adjust這個屬性來放大文字的。

一籌莫展之際,忽然想到是否應該取一下computedStyle

window.getComputedStyle(document.querySelector(‘.fs10‘),null).getPropertyValue(‘font-size‘)

這次終於有結果了,“文字大小10px”這一段文字明明白白地被使用了20px的文字大小!

至此,我們可以大概推測出 Android webview 放大文字的原理:在CSS解析之後,渲染之前,將所有的字型大小的值進行縮放,後面的排版和渲染都會直接使用縮放後的CSS值。

解決方案

針對iOS,調整字型大小本身只是改變body的css屬性,因此可以通過覆蓋樣式來控制。

body {    -webkit-text-size-adjust: 100% !important;}

Android因為改變的是字型的大小,所以可以考慮將字型大小在設定的時候進行等比例縮小。例如,一個文字希望以10px來進行渲染,當webview被放大兩倍時,此時font-size會變為20px。因此我們可以在取到這個放大比例之後,對原樣式進行等比縮小,比如將原文字大小設定為5px,渲染的時候就變成了10px

var $dom = document.querySelector(‘.fs10‘);var originFontSize = 10;var scaledFontSize = parseInt(window.getComputedStyle($dom, null).getPropertyValue(‘font-size‘));var scaleFactor = originFontSize / scaledFontSize;$dom.style.fontSize = originFontSize * scaleFactor;

但是這樣做仍然有幾個問題:

  1. 一次只能操作一個DOM元素,無法批量處理
  2. 需要知道DOM元素原來設定的字型大小

這幾個問題並不如想象中的好解決。於是另闢蹊徑,看看是否有一勞永逸的辦法。腦海中很快冒出一個名詞——rem

如果我們的頁面字型大小都使用rem進行聲明,那麼我們就只需要在頁面載入的時候根據縮放比例計算出html元素的字型大小即可!詳見下方代碼:

(function(){    var $dom = document.createElement(‘div‘);    $dom.style = ‘font-size:10px;‘;    document.body.appendChild($dom);    // 計算出放大後的字型    var scaledFontSize = parseInt(window.getComputedStyle($dom, null).getPropertyValue(‘font-size‘));    document.body.removeChild($dom);    // 計算原字型和放大後字型的比例    var scaleFactor = 10 / scaledFontSize;    // 取html元素的字型大小    // 注意,這個大小也經過縮放了    // 所以下方計算的時候 *scaledFontSize是原來的html字型大小    // 再次 *scaledFontSize才是我們要設定的大小    var originRootFontSize = parseInt(window.getComputedStyle(document.documentElement, null).getPropertyValue(‘font-size‘));    document.documentElement.style.fontSize = originRootFontSize * scaleFactor * scaleFactor + ‘px‘;})();

因為這段代碼中建立了一個元素,並放入了document.body中,所以不能放在head中運行。如果放在頁尾啟動並執行話,則有可能會產生閃爍的情況,因此最好的辦法是將這段代碼放在<body>開始的地方。

除了在Android webview以外,以上代碼在 Android 中實測也有效。

其它方案Android

在編寫本文時,通過網上一些資料,發現在Android中,也可以藉助WeixinJSBridge對象來阻止字型大小調整。實測也有效。

(function() {    if (typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function") {        handleFontSize();    } else {        document.addEventListener("WeixinJSBridgeReady", handleFontSize, false);    }    function handleFontSize() {        // 設定網頁字型為預設大小        WeixinJSBridge.invoke(‘setFontSizeCallback‘, { ‘fontSize‘ : 0 });        // 重寫設定網頁字型大小的事件        WeixinJSBridge.on(‘menu:setfont‘, function() {            WeixinJSBridge.invoke(‘setFontSizeCallback‘, { ‘fontSize‘ : 0 });        });    } })();
Android QQ

作為使用者量龐大的APP之一,QQ也提供了禁止調整字型大小的方案,android qq中可以自訂webview顯示的控制項,通過在url中加入指定參數即可。見如何定製手Q的Webview.

 

手機QQ文檔

 

理論上,www.futu5.com/?_wv=128訪問這個連結,功能菜單中不會出現調整字型大小的按鈕。但是,但是,但是,在我實測過程中,所有的參數中,就只有【128隱藏字型項不生效】。不知道是QQ的bug還是有意為之,目前已提交反饋,但未收到回應。

聲音和思考

在組內分享的時候,大家對於字型大小調整這個頭疼的問題各自有不同的看法,大概有怎麼幾種聲音:

  1. 從產品的角度來說,、QQ等用戶端既然提供調整字型的功能,必然是想用它來提供更好的體驗,不應該禁用。
  2. 從開發的角度來說,字型縮放之後,頁面會亂掉,根本原因在於頁面的適應性不夠,應該從代碼層面去最佳化。
  3. 繼續從開發的角度說,雖然理論上開發應該做好適配,但是對於文字突然被放大兩倍,很多時候確實心有餘而力不足。如果要做好,需要花費大量的時間和精力,並且需要設計和產品同學從設計上留出一些適配空間。
  4. 既然使用者選擇了用大字型來瀏覽頁面,他就應該知道這個頁面是被自己放大了,需要承擔頁面配置亂掉的結果。

移動端使用者佈建字型放大導致的問題

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.