PM說要實現一個一鍵設置主題的功能,作為技術,你能想到的實現方式有哪些呢?1. 什么是主題樣式?
相信大家對網頁的主題樣式功能肯定不陌生。對于一些站點,在基礎樣式上,開發者還會為用戶提供多種主題樣式以供選擇。
下面就是一個主題樣式功能:用戶可以在右側選擇自己喜歡的主題色,從而得到一個“個性”的頁面。
還有時候,我們開發了一個系統用來售賣,采購我們系統的客戶可能有多個。也許其中一個客戶很喜歡我們當前的深色色系主題,但是另一個系統的采購方希望我們能為它們定制一套新的樣式。他們希望買來的系統能貼合它們自己的品牌調性,變為淺色的。這其實也是一種主題樣式的需求。
在上面的討論里,除了“主題”外,我們又引出了一個概念——個性化。經常,我們說到主題時,還會有一種說法叫做:個性化主題。這兩者在英文中分別有兩個對應的詞: Theming 與 Customisation。
當我們說主題(Theming)與個性化定制(Customisation)的時候,很多時候其實并沒有區分兩者。但實際上,兩者還是有一些微妙的區別的。
1.1. 主題 Theming 與個性化定制 Customisation 的區別我們說的主題(Theming)與個性化定制(Customisation)的時候,還是有一些微妙的區別的。
主題:由開發者定義主要表現在:
系統的輸入是由開發者定義的
一般來說具有有限的種類
具有已知的規則與常量
例如,我們常見的一些應用會提供夜間主題、閱讀模式,這些也算是主題(Theming)的范疇。
個性化定制:由用戶定義特點表現在:
系統的輸入是由用戶來提供
一般具有無限種可能
規則更靈活,用戶“為所欲為”
可以看到,“個性化”其實更強調了用戶對系統的的影響力。
很多時候,我們談到“主題”與“個性化定制”時,也許并沒有一個明確的邊界。從上面的描述也可以看出,兩者似乎是處于天平的兩端,區別主要在于開發者對規則的控制力度以及所能實現的差異化的粒度。
而我們更多的是在兩點之間找到一個平衡點。
1.2. 對實現“主題功能”的建議我們已經對主題樣式有了初步的了解,如果你也在產品中遇到了主題樣式的相關需求,不妨先看看以下幾點建議:
盡可能避免這個功能。因為很多時候這可能只是個偽需求。
KISS原則(Keep It Simple, Stupid!)。盡可能降低其復雜性。
盡量只去改變外觀,而不要改動元素盒模型(box-model)。
嚴格控制你的規則,避免預期外的差異。
把它作為一個錦上添花的功能來向上促銷(up-sell)。
2. 實現“主題樣式”的方式 2.1. 方式一:Theme LayerOverriding default style with additional CSS.
這應該是實現主題功能的一種最常用的手段了。首先,我們的站點會有一個最初的基礎樣式(或者叫默認樣式);然后通過添加一些后續的額外的CSS來覆蓋與重新定義部分樣式。
具體實現首先,我們引入基礎的樣式 components.* 文件
@import "components.tabs"; @import "components.buttons"
其中 components.tabs 文件內容如下
.tab { margin: 0; padding: 0; background-color: gray; }
然后,假設我們的某個主題的樣式文件存放于 theme.* 文件:
對應于 components.tabs,theme.tabs 文件內容如下
.tab { background-color: red; }
因此,我們只需要引入主題樣式文件即可
@import "components.tabs"; @import "components.buttons" @import "theme.tabs";
這樣當前的樣式就變為了
.tab { margin: 0; padding: 0; /* background-color: gray; */ background-color: red; }優點
實現方式簡單
可以實現將主題應用與所有元素
缺點過多的冗余代碼
許多的CSS其實是無用的,浪費了帶寬
把樣式文件切分到許多文件中,更加瑣碎
2.2. 方式二:Stateful ThemingStyling a UI based on a state or condition.
該方式可以實現基于條件選擇不同的主題皮膚,并允許用戶在客戶端隨時切換主題。非常適合需要客戶端樣式切換功能,或者需要對站點某一部分(區域)進行獨立樣式設置的場景。
具體實現還是類似上一節中 Tab 的這個例子,我們可以將 Tab 部分的 (S)CSS 改為如下形式:
.tab { background-color: gray; .t-red & { background-color: red; } .t-blue & { background-color: blue; } }
這里我們把.t-red與.t-blue稱為 Tab 元素的上下文環境(context)。Tab 元素會根據 context 的不同展示出不同的樣式。
最后我們給body元素加上這個開關
此時 Tab 的顏色為紅色。
當我們將t-red改為t-blue時,Tab 就變為了藍色主題。
進一步的,我們可以創建一些 (S)CSS 的 util class(工具類)來專門控制一些 CSS 屬性,幫助我們更好地控制主題。例如我們使用如下的.u-color-current類來控制不同主題下的字體顏色
.u-color-current { .t-red & { color: red; } .t-blue & { color: blue; } }
這樣,當我們在不同主題上下文環境下使用.u-color-current時,就可以控制元素展示出不同主題的字體顏色
...
上面這段代碼會控制元素字體顏色為紅色主題時的顏色。
優點將許多主題放在了同一處代碼中
非常適合主題切換的功能
非常適合站點局部的主題化
可以實現將主題應用于所有元素
缺點有時有點也是缺點,將許多主題混雜在了同一塊代碼中
可能會存在冗余
2.3. 方式三:Config ThemingInvoking a theme based on settings.
這種方式其實是在開發側來實現主題樣式的區分與切換的?;诓煌呐渲茫浜弦恍╅_發的自動化工具,我們可以在開發時期根據配置文件,編譯生成不同主題的 CSS 文件。
它一般會結合使用一些 CSS 預處理器,可以對不同的 UI 元素進行主題分離,并且向客戶端直接提供主題樣式下最終的 CSS。
具體實現我們還是以 Sass 為例:
首先會有一份 Sass 的配置文件,例如settings.config.scss,在這份配置中定義當前的主題值以及一些其他變量
$theme: red;
然后對于一個 Tab 組件,我們這么來寫它的 Sass 文件
.tab { margin: 0; padding: 0; @if ($theme == red) { background-color: red; } @else { background-color: gray; } }
這時,我們在其之前引入相應的配置文件后
@import "settings.config"; @import "components.tabs";
Tab 組件就會呈現出紅色主題。
當然,我們也可以把我們的settings.config.scss做的更健壯與易擴展一些
$config: ( theme: red, env: dev, ) // 從$config中獲取相應的配置變量 @function config($key) { @return map-get($config, $key); }
與之前相比,這時候使用起來只需要進行一些小的修改,將直接使用theme變量改為調用config方法
.tab { margin: 0; padding: 0; @if (config(theme) == red) { background-color: red; } @else { background-color: gray; } }優點
訪問網站時,只會傳輸所需的 CSS,節省帶寬
將主題的控制位置放在了一個地方(例如上例中的settings.config.scss文件)
可以實現將主題應用于所有元素
缺點在 Sass 中會有非常多邏輯代碼
只支持有限數量的主題
主題相關的信息會遍布代碼庫中
添加一個新主題會非常費勁
2.4. 方式四:Theme PalettesHolding entire themes in a palette file.
這種方式有些類似于我們繪圖時,預設了一個調色板(palette),然后使用的顏色都從其中取出一樣。
在實現主題功能時,我們也會有一個類似的“調色板”,其中定義了主題所需要的各種屬性值,之后再將這些信息注入到項目中。
當你經常需要為客戶端提供完全的定制化主題,并且經常希望更新或添加主題時,這種模式會是一個不錯的選擇。
具體實現在方式三中,我們在一個獨立的配置文件中設置了一些“環境”變量,來標示當前所處的主題。而在方式四中,我們會更進一步,抽取出一個專門的 palette 文件,用于存放不同主題的變量信息。
例如,現在我們有一個settings.palette.red.scss文件
$color: red; $color-tabs-background: $color-red;
然后我們的components.tabs.scss文件內容如下
.tabs { margin: 0; padding: 0; backgroung-color: $color-tabs-background; }
這時候,我們只需要引入這兩個文件即可
@import "settings.palette.red"; @import "components.tabs";
可以看到,components.tabs.scss中并沒有關于主題的邏輯判斷,我們只需要專注于編輯樣式,剩下就是選擇所需的主題調色板(palette)即可。
優點編譯出來的樣式代碼無冗余
非常適合做一些定制化主題,例如一個公司采購了你們的系統,你可以很方便實現一個該公司的主題
可以從一個文件中完全重制出你需要的主題樣式
缺點由于主要通過設定不同變量,所以代碼確定后,能實現的修改范圍會是有限的
2.5. 方式五:用戶定制化 User CustomisationLetting users style their own UIs.
這種模式一般會提供一個個性化配置與管理界面,讓用戶能自己定義頁面的展示樣式。
“用戶定制化”在社交媒體產品、SaaS 平臺或者是 Brandable Software 中最為常見。
具體實現要實現定制化,可以結合方式二中提到的 util class。
首先,頁面中支持自定義的元素會被預先添加 util class,例如 Tab 元素中的u-user-color-background
此時,u-user-color-background還并未定義任何樣式。而當用戶輸入了一個背景色時,我們會創建一個標簽,并將 hex 值注入其中
這時用戶就得到了一個紅色的 Tab。
Twitter 就是使用這種方式來實現用戶定制化的界面樣式的:
優點不需要開發人員的輸入信息(是用戶定義的)
允許用戶擁有自己“獨一無二”的站點
非常實用
缺點不需要開發人員的輸入信息也意味著你需要處理更多的“不可控”情況
會有許多的冗余
會浪費 CSS 的帶寬
失去部分 CSS 的瀏覽器緩存能力
3. 如何選擇方案?最后來聊聊方案的選擇。
在第二部分我們已經了解了五種實現方式(或者說4?種方法,因為第五種其實更偏個性化定制一些),那么面對產品需求,我們應該如何選擇呢?
這里有一個不是非常嚴謹的方式可以參考。你可以通過嘗試問自己下面這幾個問題來做出決定:
是你還是用戶誰來確定樣式?
用戶:選擇【方式五】User Customisation
主題是否會在客戶端中被切換?
是:選擇【方式二】Stateful Theming 或【方式五】User Customisation
是否有主題能讓用戶切換?
是:選擇【方式二】Stateful Theming
你是希望網站的某些部分需要有不同么?
是:選擇【方式二】Stateful Theming
是否有預設的主題讓客戶端來選擇?
是:選擇【方式三】Config Theming
是否是類似“貼牌”這類場景?
是:選擇【方式一】Theme Layer 或【方式四】Theme Palettes
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/117051.html
摘要:當然,也可自己寫一個轉換函數,按照一定規則便行為編碼的字節,如下例中國結果中國結果結果通過簡單的函數,就可以完成編碼到編碼的轉換,進而完成寬字節字符到編碼的轉換。 前端開發過程中會接觸各種各樣的編碼,比較常見的主要是 UTF-8 和 HTML 實體編碼,但是 web 前端的世界卻不止這兩種編碼,而且編碼的選擇也會造成一定的問題,如前后端開發過程中不同編碼的兼容、多字節編碼可能會造成的 ...
摘要:前言最近搭建的項目想引入并實現樣式局部作用域化,但是在網上找了很多方法試過了都不行,最后打到解決方法,在此記下這慘痛的歷程。 微信公眾號:愛寫bugger的阿拉斯加如有問題或建議,請后臺留言,我會盡力解決你的問題。 1. 前言 最近搭建的 react 項目想引入 less ,并實現樣式局部作用域化,但是在網上找了很多方法試過了都不行,最后打到解決方法,在此記下這慘痛的歷程。 2. cr...
閱讀 2400·2021-09-08 09:45
閱讀 3340·2021-09-08 09:45
閱讀 3097·2019-08-30 15:54
閱讀 3347·2019-08-26 13:54
閱讀 1404·2019-08-26 13:26
閱讀 1383·2019-08-26 13:23
閱讀 908·2019-08-23 17:57
閱讀 2177·2019-08-23 17:14