這一期中我們主要來聊聊全屏的事情。對於全屏的佈局,大家可能首先想到的是

100%

(或

100vw

)來實現,但如果你要在一個限寬的容器中實現一個全屏效果呢?比如說,一個Banner區全屏顯示。類似這樣的效果在PC端是非常常見的一個效果。可能會有很多同學會說,這樣的效果有什麼好聊的,不是非常簡單的Layout嗎?其實還是有點事情可聊的。如果你感興趣,不仿繼續往下閱讀。

全屏寬度的事情

在Web佈局中,特別是在PC端中,常常可以看到這樣的設計風格:內容居中,然後Banner區全屏。這也就是標題所說的效果,限寬的容器中實現全屏效果。那麼問題來了,在實際中如何實現在限寬的容器中實現全屏效果。比如下面的設計風格:

Web技巧(09)

看到上圖的效果,我們可能首先會想到從HTML結構上來做相應的處理:

對應的CSS樣式:

。banner 。container {

width: 100%

}

如果對於多個

區域全屏

和多個區域限寬居中呢?如果還是從結構上做處理的話,可能會:

CSS並不會太複雜:

。full-width {

width: 100%;

}

。wrap {

width: 80%;

max-width

: 24em;

margin: 0 auto;

}

這其實很簡單。如果我們換過一個環境或提高限制條件呢?假設你是在為一個CMS系統做開發(你並沒有自主修改HTML的許可權)。即你的結構有能都是這樣的一個模式:

。container

中設定一個限制寬度,比如:

。container {

width: 80%;

max-width: 80vw;

margin: 0 auto;

}

基於這樣的一個Layout結構,如果

header

。banner

footer

區域需要全屏顯示。在不修改HTML結構的情況之下,如何實現需要的效果。

負margin和正padding相互抵銷

大家是否還記得等高佈局,在等高佈局的實現方案中就有一個負

margin

和正

padding

相互抵銷的方案。那麼如果僅實現一個全屏的背景顏色也可以使用該方案:

header {

margin: 0 -9999rem;

padding: 1rem 9999rem;

}

負責margin和正border相互抵銷

和前面的一個方案類似,只不過把正

padding

換成了

border

。banner {

border-left

: 600rem solid maroon;

border-right: 600rem solid maroon;

margin: 0 -600rem;

}

vw和calc()相結合

使用

vw

calc()

兩者的結合可以讓事情變得更為簡單,比如:

。full-width {

width: 100vw;

position: relative;

left: 50%;

right: 50%;

margin-left: -50vw;

margin-right

: -50vw;

}

在CSS中,我們可以藉助

transform

中的

translate()

來替代

left

right

,上面的示例程式碼可以變成:

。full-width {

width: 100vw;

transform: translateX(calc(( 960px - 100vw ) / 2)); // 假設限寬的容器寬度為960px

}

上面的程式碼咱們繼續最佳化一下:

960px

相當於

100%

,這樣一來

960px / 2

也就相當於

50%

;對應的

100vw / 2

就變成了

50vw

。這樣上面的程式碼就變成了:

。full-width {

margin-left: calc(50% - 50vw);

margin-right: calc(50% - 50vw);

}

如果你使用Sass這樣的CSS處理器,你還可以將其封裝成一個

@mixin

@mixin full-width($support-type: margin,$min-width:null){

@if $support-type == ‘margin’ {

margin-left: calc(-50vw + 50%);

margin-right: calc(-50vw + 50%);

// margin-left: calc(-100vw / 2 + #{$min-width} / 2);

// margin-right: calc(-100vw / 2 + #{$min-width} / 2);

}

@if $support-type == ‘position’ {

width: 100vw;

position: relative;

left: 50%;

right: 50%;

margin-left: -50vw;

margin-right: -50vw;

}

@if $support-type == ‘translate’ {

width: 100vw;

transform: translateX(calc((#{$min-width} - 100vw)/2));

}

}

有了上述定義的混合宏,在實際使用的時候,只需要向下面這樣呼叫:

。full-width {

@include full-width(margin,960px);

}

使用

vw

calc()

函式來實現限寬容器中任何一個單一元素實現全屏佈局。另外,

vw

還可以配合偽元素、

padding

或者說百分比和

padding

也可以實現一些類似的佈局效果:

有關於這方面更詳細的介紹可以閱讀:

如何在限寬的容器中實現全屏效果

Full Browser Width Bars

The “Inside” Problem

關於display屬性的一二

在Web技巧第四期中末尾向大家介紹了CSS中重要的屬性之一

display

,在未來的

display

中可以使用兩個值。而@Rachel Andrew花了三篇文章的篇幅來介紹CSS的

display

屬性:

Digging Into The Display Property: The Two Values Of Display

Digging Into The Display Property: Box Generation

Digging Into The Display Property: Grids All The Way Down

如果想對

display

有一個深入的瞭解,那麼這幾篇文章對你是有較大的參考價值或者文章中相關的內容是非常值得我們去深挖。當然,想更深入的把

display

聊的清楚一些,那麼我們很有必要花更多的時間來梳理。如果你感興趣的話,歡迎關注後續相關的更新,我將會花一到兩篇的篇幅和大家重新來聊

display

。如果你不想等的太久,除了上面的文章之外,下面這幾篇文章也是有助於你更好的理解

display

CSS的display:contents

CSS的display:flow-root

More accessible markup with display: contents

Display: Contents Is Not a CSS Reset

字型圖示使用的相容性

在《Web中的圖示》一文中主要和大家一起聊了聊Web中的圖示(Icon圖示)如何應該,應該怎麼去選擇。雖然SVG的Icon在實際使用中已經非常的成熟了:

如何在Vue專案中使用SVG Icon

SVG Sprite

Inline SVG vs Icon Fonts

但還是有很多同學在使用字型圖示,而且有關於字型圖示相關的介紹也非常的多:

@font-face製作Web Icon

自定義Font Icon

如何把你的圖示轉換成Web字型

為什麼要用和如何使用字型圖示

如何製作自己的網頁字型圖示

但字型圖示的使用過程中會存在很多的問題。@zachleat在《The Scoville Scale of Web Font Loading Opinions》為Web字型載入做了一個主題的介紹,而且有關於這方面的優秀教程,在網際網路上大把:

Delivering Octicons with SVG

Seriously, Don’t Use Icon Fonts

Death to Icon Fonts

Making the Switch Away from Icon Fonts to SVG: Converting Font Icons to SVG

而字型圖示和字型載入存在一定的相容性問題。簡單地說,字型圖示似乎存在Web標準之外。換句話說就是

font-display

沒有與圖示字型相容的有效值。

載入字型圖示時,通常不希望有一個降級文字(回退文字)渲染。它不是典型的無樣式文字(FOUT)場景。如果字型圖示沒有回退文字渲染,誰都不知道字型載入未成功的時候會看到什麼。

你可有在訪問有字型圖示的Web頁面時,字型未載入或載入失敗時看不到圖示,而是一個帶顏色的方框

Web技巧(09)

使用字型圖示都會藉助CSS的

@font-face

屬性,在

@font-face

指令中使用

font-display

來載入自定義字型。這個屬性可以新增以下的值:

auto

:預設值。典型的瀏覽器字型載入的行為會發生,也就是使用自定義字型的文字會先被隱藏,直到字型載入結束才會顯示

swap

:後備文字立即顯示直到自定義字型載入完成後再使用自定義字型渲染文字。在大多數情況下,這就是我們所追求的效果

fallback

:這個可以說是

auto

swap

的一種折中方式。需要使用自定義字型渲染的文字會在較短的時間不可見,如果自定義字型還沒有載入結束,那麼就先載入無樣式的文字。一旦自定義字型載入結束,那麼文字就會被正確賦予樣式

optional

:效果和

fallback

幾乎一樣,都是先在極短的時間內文字不可見,然後再載入無樣式的文字。不過

optional

選項可以讓瀏覽器自由決定是否使用自定義字型,而這個決定很大程度上取決於瀏覽器的連線速度。如果速度很慢,那你的自定義字型可能就不會被使用

block

:為字型提供一個短暫的阻塞週期和無限的交換週期,它將使用不可見的文字長達

3s

,並顯示回退文字,直到Web字型載入完成。這是最佳選項,但仍然不是很好

有關於

font-display

更詳細的介紹可以閱讀《

font-display的用法》一文。

要解決這些問題,可以使用CSS字型載入API強制不可見的文字,直到圖示字型成功載入。或者使用使用SVG圖示。

七個有用的JavaScript小技巧

@David Walsh整理了使用JavaScript的幾個小技巧。

獲取陣列的唯一值

透過

。。。new Set()

得到一個唯一值的陣列:

var j = [。。。new Set([1, 2, 3, 3])]

>> [1, 2, 3]

陣列和

布林值

透過

map

filter

來過濾掉陣列中的布林值(比如

0

undefined

null

false

等):

myArray。map(item => {

//。。。

})。filter(Boolean)

比如:

[0, undefined, false, 1, 23]。map(item=>{ return item })。filter(Boolean)

>> [1, 23]

建立空物件

可以使用

{}

來建立一個

看起來像空的物件

,但該物件仍然有一個

__proto__

hasOwnProperty

和其他物件方法。然而,有一種方法可以建立一個純“

dictionary

”物件:

let dict = Object。create(null)

dict。__proto__ === “undefined”

>> false

合併物件

在JavaScript中合併多個物件的需求一直存在,特別是當我們開始建立類和帶有選項的元件時:

const person

= {

name: ‘David Walsh’,

gender: ‘Male’

}

const tools = {

computer: ‘Mac’,

editor: ‘Atom’

}

const attributes = {

handsomeness: ‘Extreme’,

hair: ‘Brown’,

eye: ‘Blue’

}

const summary = {。。。person, 。。。tools, 。。。attributes}

Web技巧(09)

需要函式引數

能夠為函式引數設定預設值是JavaScript的一個很棒的功能,但看看這個技巧,它要求為給定的引數傳遞值:

const isRequired = () => {

throw new Error(‘param is required’)

}

const hello = (name = isRequired()) => {

console。log(`hello ${name}`)

}

Web技巧(09)

解構的別名

解構是一個非常受歡迎的JavaScript,但有時我們更喜歡用其他的名稱引用這些屬性,所以我們可以利用別名:

const obj = { x: 1}

const { x } = obj

const {x: otherName} = obj

獲取查詢

字串

引數

多年來,我們編寫粗糙的正則表示式來獲取查詢字串值,但那些日子已經一去不復返了,輸入

URLSearchParams

API即可:

// Assuming “?post=1234&action=edit”

var urlParams = new URLSearchParams(window。location。search);

console。log(urlParams。has(‘post’)); // true

console。log(urlParams。get(‘action’)); // “edit”

console。log(urlParams。getAll(‘action’)); // [“edit”]

console。log(urlParams。toString()); // “?post=1234&action=edit”

console。log(urlParams。append(‘active’, ‘1’)); // “?post=1234&action=edit&active=1”

有關於陣列和物件更多的介紹可以點選:

陣列相關的教程

物件相關的教程

總結

這一期中我們主要一起聊了聊如何在限寬的容器中讓某部分實現全屏顯示,除了在結構上實現所需的效果之外,還可以在單個元素上藉助一些CSS的特性來完成,比如負

margin

和正

padding

、或者負

margin

border

這樣的互負抵銷的方式;也可以使用

vw

calc()

讓事情變得還更簡單。

display

是CSS的重要內容之一,@Rachel Andrew的三篇博文,讓我們對CSS的

display

有了一個更深層次的理解,在今年的佈局或者在使用

display

會變得更明瞭。另外圖示是Web中常用的一部分,這裡羅列了字型圖示使用的一些教程以及如何藉助

font-display

來讓字型載入讓使用者有一個更好的體驗。雖然

font-display

可以對字型載入做一些最佳化,但使用字型圖示依舊是有一些缺陷的,建議大家還是考慮使用SVG圖示。

最後,把@David Walsh整理的幾個JavaScript小技巧列入到這一期,希望這些小技巧能在實際開發中給大家帶來一些幫助。