可摺疊Web可能會給咱們帶來的變化

可摺疊Web的說法是可摺疊設備帶來的。可摺疊設備形式多樣,從筆記本電腦到手機,再到新奇的雙屏幕混合設備。對於這類新發明並無一個全面的定義,但大多數均可以歸爲兩類。「可摺疊」是指屏幕能夠摺疊的設備(好比華爲Mate X,三星Galaxy Z Flip);而「雙屏」設備的屏幕是分開的,但也能夠以獨特的方式一塊兒工做,以靈活的形式提供生產力(好比,微軟的Surface Neo和Surface Duo)。當涉及到Web設計時,這兩種類型可能會遵循相似的規則。若是這項技術能大獲成功,那麼Web設計將面臨十年來最大的變革。這對於咱們Web開發者而言,也將會開啓新的旅程。css

聽起來就很使人興奮,但這到底意味着什麼呢?可摺疊Web將帶來新的挑戰新的機遇,並且極可能還會帶來新的概念。互聯網可能也會經歷自智能手機以來最大的變革。你可能會認爲這是一種炒做,但事實上這樣的一天已經離咱們不是太遠。記得在去年這個時候,有些移動品牌商,好比華爲,三星都推出可摺疊的硬件設備,而微軟,蘋果等公司在幕後的努力也不遜色。能夠說可摺疊Web即將到來。咱們真的應該去思考可摺疊Web可能會給我帶來什麼變化?若是這一天真的到來,咱們的技術是否能支持該設備。簡單地說,咱們開發的Web頁面能不能在可摺疊設備和雙屏幕上完美的運行。html

可摺疊和雙屏設備

可摺疊設備採用的是一種柔性屏幕技術,該技術的研究始於20世紀70年代,但直到世紀之交才獲得真正的發展。特別是在去年,獲得了爆發式的發展——在市場上能看到一些可摺疊設備終端。好比三星Galaxy Z Flip手機,模仿的是老式的翻蓋手機:git

好比三星的Galaxy Fold手機,在摺疊狀態是一個小屏幕,展開狀態是一個寬屏幕:github

好比華爲Mate X,屏幕是包裹在手機外面的:web

還有不少像電子書同樣,當設備徹底打開時,內部的兩個顯示屏會合二爲一。一般在外面有一個獨立的小屏幕,這樣用戶在使用的時候就不用打開它。npm

雙屏幕設備是具備兩個對稱屏幕的便攜式設備,以獨特的方式一塊兒工做,以靈活的形式提供生產力。好比像微軟的Surface Neo和Surface Duo這樣的雙屏幕設備,人們能夠比以往任什麼時候間都更快地完成工做。若是你使用過Surface Neo這樣的雙屏幕設備,你能夠在一個屏幕上作筆記,在傳輸過程當中在另外一個屏幕上查看完整的項目建議書:windows

儘管如今市場上有不一樣的摺疊屏,雙屏幕設備,並且還會有更多的相似設備出現,但咱們相信爲這些設備設計應用程序會有一個共同的方法。咱們但願這將幫助你的應用程序能跑在更多的設備上,而不須要爲不一樣的設備作特殊的設計和處理。api

換句話說,在可摺疊屏或雙屏幕的設備上,用戶能夠作更多的事情,好比說讓屏幕分屏,能夠同時打開多個應用程序:數組

也能夠打開同一個應用,在應用中分屏,打開不一樣的頁面,好比:瀏覽器

像上圖這樣,應用程序在兩個屏幕上顯示,就是所謂的跨屏佈局。默認狀況下,該應用程序將表現得好像它是在一個更大的屏幕上顯示。你也能夠改變你現有的應用程序佈局來適應兩個屏幕之間的縫隙,或者你能夠更進一步,允分的利用雙屏幕設備而專門建立不一樣的佈局控件。好比iPad版本的手淘,就能夠分屏展現:

新的Web標準、新的體驗和新的問題

可摺疊和雙屏幕設備正在出現。這已經不是概念,也不是炒做。這更不是重點。重點是:

可摺疊和雙屏幕這項技術將如何影響Web開發人員、用戶體驗設計師以及其餘以提供高質量瀏覽體驗爲業務的人

首先可摺疊和雙屏幕會給視覺設計師在作設計的時候帶來很大的變化。

整個可摺疊的概念是基於你能夠把你的手機變成平板電腦的想法。市場上大多數平板電腦的屏幕寬高比都是 4:3,因此手機和平板電腦的混合也應該是4:3。這使用摺疊設備達到3:2。而這些比率都不能保證16:918:9的真實視頻體驗。其中4:3的寬高比更適合在各類文本和圖形編輯器中執行任務和工做,好比iPad,但它須要更大的分辨率,這是可摺疊設備沒法作到的。這使得大多數可摺疊手機處於一個模糊地帶,給人用戶的體驗就會變得很糟糕,這也是由於在傳統手機中是沒法達到16:9的比例。

爲了讓可摺疊手機成爲一種有用的媒體設備,它必須轉換成16:918:9的設備,而後再摺疊成8:99:9 —— 基本上就是一個正方形。@Nathan Cunn經過計算得出結論,摺疊手機的完美寬高比應該是其寬度的1.4倍。

這也將會是iPhone摺疊屏將會採用的一種寬高比例:

除此以外,無論是可摺疊設備仍是雙屏幕設備,最大的特徵就是屏幕變大了,在展開的狀態下和平板同樣了。這樣一來,可用的空間就變大了。

可摺疊和多屏設備打破了移動設備(手機)可用空間小的束縛!

空間大了,能放置的內容就多了,若是設計仍是按着之前的思路,直接拉伸平滿全屏,就過於浪費了。面對這樣的場景,除了響應式Web設計能幫助咱們更好的利用可用空間以外,還能夠參照淘寶設計提出的一個概念:

讓你的內容像水同樣的流動(「Content is like water」)

用一張圖來描述:

有關於這方面更詳細的介紹,能夠關注淘寶設計微信公衆號

你能夠搜索「可摺疊」關鍵詞,能找到一些這方面的文章,好比:

對於雙屏幕給設計帶來的變化,或者說設計應該要注意的細節,能夠閱讀微軟官方有關於雙屏幕的介紹:《Introduction to dual-screen devices》。

另外,摺疊屏幕還會帶來一些其餘的設計和體驗變化。

單(雙)手移動設計

隨着狀態的改變(這裏的狀態是摺疊和展開狀態,單屏和多屏狀態),整個體驗自己也隨之改變。目前大多數用戶都習慣用一隻手操做移動設備(手機),而展開狀態,就像iPad了,這個時候須要兩隻手來操做設備(或應用)。

手機操做 vs 平板操做

屏幕連續性和間隔

可摺疊設備和多屏幕設備有着明顯的區別。

可摺疊設備在展開狀態時,它的屏幕是連續性的,咱們在設計的體驗應該無縫地轉移到全屏上。

針對這樣的情景,若是隻是粗暴的放大到全屏,那麼佈局上不會有太多的變化,只不過對於Web中的部分對象會變得模糊,好比圖像。固然,也能夠考慮設計上作差別性的處理,好比說作分屏設計:

對於多屏幕設備,有可能屏幕不是連續性的,好比微軟的Surface Neo和Surface Duo,屏幕之間就有一個間隙:

在設計和佈局的時候,就須要避免Web對象處在兩個屏幕的間隙之間,好比:

或者:

多窗口,多應用

前面提到過,摺疊屏和多屏幕最大的特徵之一,就讓咱們有更多的空間可利用。這樣對於用戶來講,對於處理多任務更友好,能同時作更多的事情。所以,咱們應該始終考慮用戶可能會同時運行多個App應用。好比說,一邊查看日曆,一邊查看地圖,一邊看新聞:

除了同時打開多個App應用以外,還能夠在同一個App中,分屏作不一樣的事情,好比,一邊看直播,一邊逛淘寶:

摺疊屏和多屏幕除了給設計師帶來新的挑戰以外,給Web開發者也帶來相應的挑戰。在去年華爲Mate X出來的時候,有幸參與在Mate X作一些Web端的適配處理。主要處理H5的應用完美適配摺疊屏設備。

因爲相關H5業務採用的都是視窗單位vw(我常稱該方案爲vw-layout),能較好的讓相應的H5業務適配摺疊屏展開狀態,但也存在一些相應的問題,最爲突出的是圖像變得模糊:

固然也嘗試着採用響應式Web設計來作不一樣的佈局處理:

雖然該方式可讓咱們的H5應用最大化的利用摺疊屏可用空間,但也存在必定的缺陷。所以在《聊聊安卓摺疊屏給交互設計和開發帶來的變化》一文中提出相應的概念:

處理摺疊屏時,咱們應該像一些帶有劉海設備(好比iPhone X)同樣,具備獨特的檢測特性來檢測摺疊設備或多屏幕設備

值得慶幸的是這一年來,在這方面有了明顯的變化,尤爲是微軟公司的團隊對可摺疊技術的探究和討論很是的積極。在今年2月份,三位微軟開發人員@Bogdan Brinza@Daniel Libby@Zouhir Chahoud發表了一篇文章,解釋如何使用JavaScript API和CSS 媒體查詢來處理可摺疊和多屏幕設備的佈局

該文檔提出兩個概念:用於雙屏幕布局的CSS窗口段枚舉的JavaScript API。它的宗旨是做爲討論摺疊屏和多屏幕在Web開發中技術標準。即:以可摺疊和雙屏幕設備爲目標的Web開發人員可以在跨多個顯示區域的窗口中有效的對Web應用進行佈局

將來處理可摺疊或多屏幕的Web技術

@Bogdan Brinza@Daniel Libby@Zouhir Chahoud三位開發者在Github上發表的文檔《Web Platform Primitives for Enlightened Experiences on Foldable Devices》來看。處理可摺疊和多屏幕設備的Web佈局主要由兩部分特性組成,其一是CSS的媒體查詢特性,其二是JavaScript API。

接下來,咱們主要圍繞着這兩個部分來展開。

用於構建雙屏幕布局的CSS特性

特別聲明:用於雙屏幕布局的CSS還處於W3C規範的草案當中,一切皆有可能會變

@Brinza、@Libby和@Chahoud提出了一個CSS特性,即媒體特性,它能夠肯定網站是否跨越兩個相鄰的顯示區域,以及這兩個相鄰顯示區域的配置。相應的還提出了另外一個特性,即環境變量(指的是用戶代理定義的環境變量),它將幫助Web開發人員以CSS像素計算每一個屏幕區域的大小。

爲何要提出新的CSS特性

當瀏覽器窗口跨越設備摺疊時,告訴Web開發者摺疊方向和顯示邊界能夠幫助他們開發出來具備較好體驗的Web應用。這裏快速概述可能會出現的模式。

將更大屏幕的UI模式帶到更小的便攜設備

因爲屏幕尺寸的限制,傳統的便攜式觸摸設備在很大程度上依賴於「疊加視圖」,好比點擊收件箱列表中的一封郵件,就會致使整個收件箱列表視圖被選中的郵件內容視圖所取代。這種行爲一般會建立額外的操做步驟;而在更大屏幕的設備上將會有一個更天然的配置,郵件收件箱列表視圖和郵件內容視圖是並排的。

固然,這種從新創造的模式並非惟一的解決方案,只不過可摺疊屏和多屏幕設備相對於傳統的便攜觸摸式移動設備來講多了一個顯示器,至關於增長一個屏幕空間,這樣一來能夠爲Web開發者和設計師提供獨特的機會來創造新的體驗。

輕鬆改進現有的Web應用和UI組件

Web開發人員可能不想爲這類設備引入主要的UI更改,而只想簡單地移動一些組件。在下面的示例中,對於模態對話框(Modal)避免設備摺疊更有意義(不管可摺疊設備是無縫的仍是有間隙的),並容許Web開發人員逐步加強他們的站點,提供更好的體驗。

也正由於這些緣由,提出了相應的CSS特性和設計原則。

CSS媒體特性:spanning

提出一個新的媒體特性:spanning,該特性可用於檢測瀏覽器窗口是否跨越多個顯示區域。

spanning特性主要有三個值:

  • single-fold-vertical:屏幕是水平的,佈局視圖跨越單個摺疊(兩個屏幕)而且摺疊姿式是垂直時(分左右兩邊),這個值是匹配的
  • single-fold-horizontal:屏幕是垂直的,佈局視圖跨越單個摺疊(兩個屏幕)而且摺疊姿式是水平時(分上下),這個值是匹配的
  • none:描述瀏覽器窗口不處於跨越模式時的狀態

識別摺疊或多屏設備的CSS環境變量

這個有點相似於劉海設備同樣,經過env()函數來識別環境變量,即識別安全區域:

  • env(safe-area-inset-top):在Viewport頂部的安全區域內設置量(CSS像素)
  • env(safe-area-inset-bottom):在Viewport底部的安全區域內設置量(CSS像素)
  • env(safe-area-inset-left):在Viewport左邊的安全區域內設置量(CSS像素)
  • env(safe-area-inset-right):在Viewport右邊的安全區域內設置量(CSS像素)

這份建議預約義了幾個可識別摺疊或多屏設備的CSS環境變量:fold-topfold-leftfold-widthfold-height

Web開發人員能夠利用這些變量來計算橫屏和豎屏的每一個屏幕片斷大小。

注意,這些CSS環境變量的值是CSS像素,而且是相對於佈局視圖的(即在客戶端座標中,由CSSOM視圖定義)。當不處於跨越狀態時,這些值將被視爲不存在,則會取env()函數的回退值。

來看一個簡單的示例:一個地圖應用程序,在一個屏幕上顯示地圖,在另外一個屏幕上顯示搜索結果。以下圖所示:

若是用CSS代碼來實現的話,大體以下:

@media (spanning: single-fold-vertical) {
    body {
        flex-direction: row;
    }

    .map {
        flex: 1 1 env(fold-left)
    }

    .locations-list {
        flex: 1;
    }
}
複製代碼

spanning的Polyfill

到目前爲止,新增的CSS媒體特性spanning和相應的環境變量都還處於草案的討論階,但若是你要嘗試着在摺疊設備或多屏幕設備上使用該特性的話,可使用@darktears 提供的一個Polyfill

這個Polyfill的使用很簡單,你可使用NPM將這個Polyfill加載到你的項目中

npm install --save spanning-css-polyfill
複製代碼

安裝完以後,經過<script>將對應的spanning-css-polyfill.js引入到項目中:

<script type="module" src="/path/to/modules/spanning-css-polyfill.js"></script>
複製代碼

也可使用import的方式引入:

import "/path/to/modules/spanning-css-polyfill/spanning-css-polyfill.js";
複製代碼

這樣你就能夠在CSS中使用spanning這個新媒體查詢特性和CSS環境變量fold-topfold-leftfold-widthfold-height

固然,你還能夠手動改變顯示(display)相關的配置。好比,經過導入FoldablesFeature對象:

import { FoldablesFeature } from '/path/to/modules/spanning-css-polyfill/spanning-css-polyfill.js';
複製代碼

能夠經過FoldablesFeature對象來更新像spanningfoldSizebrowserShellSize等值。你也能夠訂閱change事件,以便spanning媒體查詢特性或環境變量發生變動時獲得相應的通知。

import { FoldablesFeature } from '/path/to/modules/spanning-css-polyfill/spanning-css-polyfill.js';

const foldablesFeat = new FoldablesFeature;

// Add an event listener.
foldablesFeat.onchange = () => console.log("change");

// Add as many event listeners as you want.
foldablesFeat.addEventListener('change', () => console.log("change"));

// Change a single value; results in one update (one 'change' event firing).
foldablesFeat.foldSize = 20;

// Change multiple values by assignment; results in one update.
Object.assign(foldablesFeat, { foldSize: 50, spanning: "none"});

// Change multiple values in one scope; results in one update
(function() { foldablesFeat.foldSize = 100; foldablesFeat = "single-fold-horizontal" })();
複製代碼

有關於spanning更詳細的使用,能夠查看Github上的相關教程

枚舉窗口片斷的JavaScript API

特別聲明,枚舉窗口片斷的JavaScript API已移到W3C第二屏幕社區組。相關的解釋、問題和評論,能夠參閱GitHub的webscreens/window-segments倉庫。

這裏提出了一個窗口片斷的新概念,它表示位於單獨(相鄰)顯示上的窗口區域(及其尺寸)。窗口片斷尺寸以CSS像素表示,並容許Web開發者經過JavaScript API對窗口片斷進行枚舉,在相應的窗口片斷上放置獨立內容。

這個建議主要針對響應式場景,在這種狀況下,Web應用程序但願利用跨越多個顯示的優點,經過用戶、窗口管理器將其置於該狀態。它不適合將內容預先放置在各類可用顯示的單獨頂級瀏覽器上下文的狀況(這屬於Window Placement APIPresentation API)。請注意,使用枚舉窗口片斷的API和Web現有的特性,可使用JavaScript來編寫交叉顯示和窗口的矩形,同時考慮devicePixelRatio來,計算橫跨多個顯示的窗口區域。不過,這個並不能正確的處理將來設備形式中存在的極端狀況,所以,這個提議試圖解決Web開發人員針對或考慮顯示內容屏幕做爲一個實際的起點。

簡單地來講,Web開發者可使用getWindowSegments()來獲取一個DOMRects數組,而後根據每一個窗口片斷返回的數據,開發人員可以推斷出可用連接(Hinge)的數量以及其方向。

用戶能夠在任什麼時候候將瀏覽器窗口脫離跨越模式,並將其放在某個屏幕上,反之亦然,在這種狀況下,將觸發窗口resize事件,從而能夠查詢並得到可用屏幕段的數量。

好比咱們上面提到的示例:

若是使用JavaScript來解決的話,能夠像下面這樣:

const screenSegments = window.getWindowSegments();

if( screenSegments.length > 1 ) {
    // 如今咱們知道這個設備是可摺疊(可多屏幕)的
    // 建議測試 screenSegments[0].width === screenSegments[1].width
    // 能夠更新CSS類,實現不一樣的佈局效果

    document.body.classList.add('is-foldable');
    document.querySelector('.map').classList.add('flex-one-half');
    document.querySelector('.locations-list').classList.add('flex-one-half');
}
複製代碼

咱們再來看另外一個示例,當窗口的resize事件和spanning狀態發現變化時處理方案。

先看CSS的解決方案:

@media (spanning: none) and (max-width: 728px) {
    body {
        flex-direction: column;
    }

    .map {
        flex: 0 0 300px;
    }

    .locations-list {
        flex: 1;
    }
}
複製代碼

若是使用JavaScript能夠這樣:

window.onresize = function() {
    const segments = window.getWindowSegments();
    console.log(segments.length) // 1

    if( screenSegments.length > 1 ) {

        document.body.classList.add('is-foldable');
        document.querySelector('.map').classList.add('flex-one-half');
        document.querySelector('.locations-list').classList.add('flex-one-half');
    }
}
複製代碼

實戰:多屏幕布局

最後咱們來看實際案例。

你可能在手上沒有摺疊屏或多屏幕的設備,有可能沒法看到實際效果。但可使用一款基於Web的模擬器,這款模擬器能夠模擬微軟 Surface DuoSurface Neo兩款分屏設備:

@kenchris 在GitHub上spanning-css-polyfill提供了幾個Demo,咱們來看最簡單的basic中的index.html

HTMl部分很簡單(這個Demo自己就很簡單):

<div class="wrapper">
    <div class="col1"></div>
    <div class="col2"></div>
</div>
複製代碼

</body>前加載了一個.js文件,根據CSS Spanning Polyfill提供的一些方法,處理一些全局樣式,甚至能夠根據JavaScript的API來構建CSS方面的樣式。

<script type="module" src="../../src/index.js"></script>
複製代碼

index.js對應的詳細代碼能夠點擊這裏查閱

接着看CSS部分。在CSS中使用媒體查詢特性:

/* 普通設備下對應的CSS */
.wrapper {
    display: flex;
    height: 100%;
    width: 100%;
}

.col1 {
    flex: 0 0 200px;
    background-color: lightgray;
    transition: background-color .2s linear;
}

.col2 {
    flex: 1;
    background-color: papayawhip;
    transition: background-color .2s linear;
}

.col1:before {
    content: "not spanning";
}

.col2:before {
    content: "not spanning";
}
複製代碼

不是分屏(或摺疊)設備中,看到的效果像下面這樣:

在水平方向分屏狀態(即spanning取值爲single-fold-vertical)下的CSS:

@media (spanning: single-fold-vertical) {
    .col1 {
        flex: 0 0 env(fold-left);
        margin-right: env(fold-width);
        background-color: steelblue;
    }

    .col2 {
        background-color: yellow;
    }

    .col1:before {
        content: "spanning single-fold-vertical";
    }
    .col2:before {
        content: "spanning single-fold-vertical";
    }
}
複製代碼

注意,示例中還使用了CSS的env()函數,調用了CSS環境變量fold-leftfold-width。這個時候看到的效果以下:

當你把瀏覽器模式(Browser Mode)切換爲「Left」或「Right」時,看到的效果以下:

上圖是Surface Duo模擬器,Browser Mode爲Left狀態效果

上圖是Surface Duo模擬器,Browser Mode爲Right狀態效果

接下來再來設備垂直方向分屏(即spanning取值爲single-fold-horizontal)的佈局樣式:

@media (spanning: single-fold-horizontal) {
    .wrapper {
        flex-direction: column;
    }

    .col1 {
        flex: 0 0 env(fold-top);
        margin-bottom: env(fold-height);
        background-color: pink;
    }

    .col2 {
        background-color: seagreen;
    }

    .col1:before {
        content: "spanning single-fold-horizontal";
    }
    .col2:before {
        content: "spanning single-fold-horizontal";
    }
}
複製代碼

將設備的方向切換到portrait狀態下,瀏覽器在spanning狀態下,看到的效果以下:

一樣的,若是你把模擬器的瀏覽器模式切換到"Top"或"Bottom"狀態下,看到的效果也會不同:

最後,你還能夠在spanning:none狀態下設置相應的CSS:

@media (spanning: none) {
    .col1:before {
      content: "spanning:none";
    }
    .col2:before {
      content: "spanning:none";
    }
}
複製代碼

上面是一個較爲簡單的示例。那麼接下來,咱們在上面的基礎上把頁面作得稍微複雜一點:

<!-- HTML -->
<ul class="card__container">
    <li class="card">
        <div class="card__object"><img src="//source.unsplash.com/300x300?01" alt="Psychopomp"></div>
        <div class="card__body">
            <h4 class="card__title">Psychopomp</h4>
            <p>Japanese Breakfast</p>
        </div>
    </li>
    <!-- ... -->
</ul>
複製代碼

按照上面的示例,在媒體特性以外,給普通設備添加樣式(也能夠說是全局樣式):

/* 佈局關鍵樣式 */
body {
    width: 100vw;
    min-height: 100vh;
    margin: 0;
    padding: 2vh;
}

.card__container {
    gap: 2vmin;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    grid-auto-flow: dense;
}

.card:nth-child(1) {
    grid-column: span 2;
}

.card:nth-child(6) {
    grid-column: span 3;
}
複製代碼

普通設備(非摺疊和分屏)下效果點擊這裏查看

拖動瀏覽器時改變視窗大小,看到的效果以下:

在不對spanning媒體特性下作任何樣式處理時,在分屏狀態下看到的效果以下:

一樣的,先對spanning: single-fold-vertical作樣式上的處理:

@media (spanning: single-fold-vertical) {

    .card__container {
        gap: env(fold-width);
        grid-template-columns: repeat(auto-fit, minmax(calc((env(fold-left) - env(fold-width) - 4vh) / 2), 1fr));
    }

    .card:nth-child(6) {
        grid-column: span 2;
    }
}
複製代碼

這個時候水平分屏狀態下的效果以下:

接着來看垂直方向的分屏狀態下的效果,先來看未處理時的效果:

接下來在spanning: single-fold-horizontal媒體特性下作一些佈局上的處理:

@media (spanning: single-fold-horizontal) {

    .card__container {
        gap: 20px;
        grid-template-columns: 1fr;
        grid-template-rows: calc(env(fold-height) - 4vh);
    }

    .card__object {
        height: 250px;
    }

    .card:nth-child(1) {
        grid-column: span 1;
    }

    .card:nth-child(6) {
        grid-column: span 1;
    }
}
複製代碼

看到的效果以下:

實際操做的時候,應該根據本身的使用場景,而後對應的媒體查詢特性中配合CSS本地環境使用,實現不一樣的效果。

有關於這方面的Demo,還能夠查閱:

小結

可摺疊Web的出現,讓移動優先的設計變得更加複雜,但也更加使人興奮。可摺疊Web多是第一次手持設備感到空間的擴展而不是限制。對於一些Web應用或Web頁面來講,須要作必定的調整,而對於另外一些Web應用來講,則意味着須要大規模的從新設計。這個範圍取決於開發人員的創新。

參考資料

相關文章
相關標籤/搜索