和以往一樣,本次項目也放到了 Github 中,歡迎圍觀 star ~
1. 前言
2. 基本概念
3. REM布局
4. VW布局
實作單邊邊框1px
實作多邊邊框1px
實作邊框圓角
實作容器固定縱橫比
5. REM + VW布局
6. 對比選擇
方案選擇
食用方式
一、前言
說到前端頁面的布局方案,可以從遠古時代的Table布局說起,然後來到 DIV+CSS布局,之後有了Float布局,Flex布局,Column布局,Grid布局等等。
而另一方面,還有一些 布局概念:
1. 靜态布局
直接使用px作為機關
2. 流式布局
寬度使用%百分比,高度使用px作為機關
3. 自适應布局
建立多個靜态布局,每個靜态布局對應一個螢幕分辨率範圍。使用 @media媒體查詢來切換多個布局
4. 響應式布局
通常是糅合了流式布局+彈性布局,再搭配媒體查詢技術使用
5. 彈性布局
通常指的是rem或em布局。rem是相對于html元素的font-size大小而言的,而em是相對于其父元素(非font-size的是相對于自身的font-size)
本文不對這些概念做太多的解釋說明,主要記錄一下整理過程中比較重要的點
如今移動端布局中免不了要支援高清裝置,機型也比較複雜,需要一套比較完善的布局方案來支援(在整體結構上解決多裝置寬的适配問題)。
淘寶的 Flexible 讓REM布局得以流行開來,而此Flexible實作也有一些不足,此外,也湧現出了多種實作REM布局的方案
比如直接使用 html{ font-size:625%; } 基準值,配合JS來設定根元素字型大小
或者使用媒體查詢來設定根元素字型大小
@media screen and (min-width: 320px) {
html,body,button,input,select,textarea {
font-size:12px!important;
}
}
@media screen and (min-width: 374px) {
html,body,button,input,select,textarea {
font-size:14px!important;
}
}
但使用rem來布局的方案并不太正統,它有一些hack的特點
比較規範的方式是使用vw機關,随之而來的就是後起之秀 VW布局
花了一些時間整理了REM布局和VW布局在實際頁面中是如何運用的,如果你有興趣,就往下看吧~
項目位址,歡迎圍觀~
二、基本概念
實體像素(physical pixel)
實體像素又被稱為裝置像素,它是顯示裝置中一個最微小的實體部件。每個像素可以根據作業系統設定自己的顔色和亮度。正是這些裝置像素的微小距離欺騙了我們肉眼看到的圖像效果。
裝置獨立像素(density-independent pixel)
裝置獨立像素也稱為密度無關像素,可以認為是計算機坐标系統中的一個點,這個點代表一個可以由程式使用的虛拟像素(比如說CSS像素),然後由相關系統轉換為實體像素。
CSS像素
CSS像素是一個抽像的機關,主要使用在浏覽器上,用來精确度量Web頁面上的内容。一般情況之下,CSS像素稱為與裝置無關的像素(device-independent pixel),簡稱DIPs。
螢幕密度
螢幕密度是指一個裝置表面上存在的像素數量,它通常以每英寸有多少像素來計算(PPI)。
裝置像素比(device pixel ratio)
裝置像素比簡稱為dpr,其定義了實體像素和裝置獨立像素的對應關系。它的值可以按下面的公式計算得到:
裝置像素比 = 實體像素 / 裝置獨立像素
在Javascript中,可以通過
window.devicePixelRatio
擷取到目前裝置的dpr。
在css中,可以通過
-webkit-device-pixel-ratio
,
-webkit-min-device-pixel-ratio
和
-webkit-max-device-pixel-ratio
進行媒體查詢,對不同dpr的裝置,做一些樣式适配。
或者使用 resolution | min-resolution | max-resolution 這些比較新的标準方式

上圖中, Retina為高清裝置螢幕,它的一個css像素對應 了4個實體像素
位圖像素
一個位圖像素是栅格圖像(如:png, jpg, gif等)最小的資料單元。每一個位圖像素都包含着一些自身的顯示資訊(如:顯示位置,顔色值,透明度等)。
理論上,1個位圖像素對應于1個實體像素,圖檔才能得到完美清晰的展示
如上圖:對于dpr=2的retina螢幕而言,1個位圖像素對應于4個實體像素,由于單個位圖像素不可以再進一步分割,是以隻能就近取色,進而導緻圖檔模糊(注意上述的幾個顔色值)。
是以,對于圖檔高清問題,比較好的方案就是
兩倍圖檔
(@2x)。
如:200×300(css pixel)img标簽,就需要提供400×600的圖檔。
縮放比 scale
縮放比:scale = 1/dpr
視窗 viewport
簡單的了解,viewport是嚴格等于浏覽器的視窗。在桌面浏覽器中,viewport就是浏覽器視窗的寬度高度。但在移動端裝置上就有點複雜。
移動端的viewport太窄,為了能更好為CSS布局服務,是以提供了兩個viewport:虛拟的visualviewport和布局的layoutviewport。
viewport的内容比較深,推薦閱讀PPK寫的文章,以及中文翻譯
視窗縮放 viewport scale
在開發移動端頁面,我們可以設定
meta
标簽的viewport scale來對視窗的大小進行縮放定義
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
rem機關
font size of the root element.
rem
就是相對于根元素
<html>
的
font-size
來做計算
視窗機關
- vw : 1vw 等于視窗寬度的1%
- vh : 1vh 等于視窗高度的1%
- vmin : 選取 vw 和 vh 中最小的那個
- vmax : 選取 vw 和 vh 中最大的那個
相容性:在移動端 iOS 8 以上以及 Android 4.4 以上獲得支援
可以去 Can I use 或 css3test 檢視相容情況
三、REM布局
講的太亂了?自己去看代碼
rem布局的核心是設定好根html元素的font-size
一般來說,為了防止在高清螢幕下像素不夠用導緻模糊,我們拿到的設計稿是640px(iphone5 裝置寬為320px)或750px的兩倍稿(iphone6 裝置寬為375px),按照裝置寬度做了兩倍的大小。
那開發的時候在CSS中要設定什麼尺寸呢,如何做到一份設計稿适配到不同機型中
最佳方案是:在photoshop或其他工具中量出某個元素或圖檔或文字的尺寸,然後直接寫到代碼中。額外的适配不需要理會。
width: px2rem(200);
基于此,可以使用SCSS來提供一系列的基礎支援
/* 移動端頁面設計稿寬度 */
$design-width: 750;
/* 移動端頁面設計稿dpr基準值 */
$design-dpr: 2;
/* 将移動端頁面分為10塊 */
$blocks: 10;
/* 縮放所支援的裝置最小寬度 */
$min-device-width: 320px;
/* 縮放所支援的裝置最大寬度 */
$max-device-width: 540px;
/*
rem與px對應關系,1rem代表在JS中設定的html font-size值(為一塊的寬度),$rem即為$px對應占多少塊
$px $rem
------------- === ------------
$design-width $blocks
*/
/* 機關px轉化為rem */
@function px2rem($px) {
@return #{$px / $design-width * $blocks}rem;
}
/* 機關rem轉化為px,可用于根據rem機關快速計算原px */
@function rem2px($rem) {
@return #{$rem / $blocks * $design-width}px;
}
為了便于計算,我們将頁面分為10個塊,根據映射關系,我們隻需要計算某個元素在頁面中占了多少塊($rem),結合html中font-size的大小,就能在頁面上設定好正确的元素大小
在對應的JS檔案中
var docElem = document.documentElement,
metaElem = document.querySelector('meta[name="viewport"]'),
dpr = window.devicePixelRatio || 1,
// 将頁面分為10塊
blocks = 10,
// 需要限制的最小寬度
defaultMinWidth = 320,
// 需要限制的最大寬度
defaultMaxWidth = 540,
// 計算的基準值
calcMaxWidth = 9999999;
将頁面按照clientWidth進行分割成塊,和CSS對應起來
// 設定docElem字型大小
function setFontSize() {
var clientWidth = docElem.clientWidth;
clientWidth = Math.max(clientWidth, defaultMinWidth * dpr)
// 調整計算基準值
if (calcMaxWidth === defaultMaxWidth) {
clientWidth = Math.min(clientWidth, defaultMaxWidth * dpr);
}
docElem.style.fontSize = clientWidth / blocks + 'px';
}
setFontSize();
window.addEventListener(window.orientationchange ? 'orientationchange' : 'resize', setFontSize, false);
1px在高清螢幕中的顯示問題
上圖左邊設定了css為1px的效果,實際上我們需要的是右邊的效果
明顯左邊的粗了一些,因為此時1個css像素包含了4個(dpr為2)實體像素,實際需要的是1px的實體像素,而非css像素
為了解決這個問題,有很多方法
在REM布局中普遍采用的是viewport scale 視窗縮放的方式
視窗縮放很簡單,其實就是直接将meta标簽中的scale進行更改。比如dpr為3,則scale為
但縮放在某些安卓裝置中支援度不太好,我們還需要做其他檢測(檢測了現用的一些機型,應該還不完整哈)
// 大部分dpr為2以下的安卓機型不識别scale,需設定不縮放
if (navigator.appVersion.match(/android/gi) && dpr <= 2) {
dpr = 1;
}
setScale(dpr);
// 企業QQ設定了scale後,不能完全識别scale(此時clientWidth未收到縮放的影響而翻倍),需設定不縮放
if (navigator.appVersion.match(/qq\//gi) && docElem.clientWidth <= 360) {
dpr = 1;
setScale(dpr);
}
docElem.setAttribute('data-dpr', dpr);
// 設定縮放
function setScale(dpr) {
metaElem.setAttribute('content', 'initial-scale=' + 1 / dpr + ',maximum-scale=' + 1 / dpr + ',minimum-scale=' + 1 / dpr + ',user-scalable=no');
}
同時将最終計算的dpr放到html中,供css做一些特殊适配。看看頁面效果
設定容器的最大最小寬度
上圖中,随着拉伸,内容區越來越大,各元素尺寸也越來越大。已經進行了最小寬度的處理。
要控制縮放的程度,關鍵有兩個點:尺寸計算基準、容器寬度
<!DOCTYPE html>
<html>
<head>
<title>REM布局</title>
<meta charset="utf-8">
<meta lang="zh-CN">
<meta name="viewport" data-content-max content="width=device-width,initial-scale=1,user-scalable=no">
<link rel="stylesheet" href="./rem.css">
<script src="./rem.js"></script>
</head>
<body data-content-max>
<section class="container">
尺寸計算基準位于 meta标簽中的 data-content-max,容器寬度位于 body标簽中
在JS中進行比對控制,需要注意的是,因為我們已經進行了視窗的縮放,clientWidth将會比裝置寬度大,要記得以dpr進行翻倍
// 需要限制的最小寬度
var defaultMinWidth = 320,
// 需要限制的最大寬度
defaultMaxWidth = 540,
// 計算的基準值
calcMaxWidth = 9999999;
if (metaElem.getAttribute('data-content-max') !== null) {
calcMaxWidth = defaultMaxWidth;
}
...
// 設定docElem字型大小
function setFontSize() {
var clientWidth = docElem.clientWidth;
clientWidth = Math.max(clientWidth, defaultMinWidth * dpr)
// 調整計算基準值
if (calcMaxWidth === defaultMaxWidth) {
clientWidth = Math.min(clientWidth, defaultMaxWidth * dpr);
}
docElem.style.fontSize = clientWidth / blocks + 'px';
}
在CSS中,簡單地調用一下,核心方法已經抽離
html {
@include root-width();
}
/* html根的寬度定義 */
@mixin root-width() {
body {
@include container-min-width();
&[data-content-max] {
@include container-max-width();
}
}
/* 某些機型雖然裝置dpr大于1,但識别不了scale縮放,這裡需要重新設定最小寬度防止出現橫向滾動條 */
&[data-dpr="1"] body {
min-width: $min-device-width;
}
}
/* 設定容器拉伸的最小寬度 */
@mixin container-min-width() {
margin-right: auto;
margin-left: auto;
min-width: $min-device-width;
@media (-webkit-device-pixel-ratio: 2) {
min-width: $min-device-width * 2;
}
@media (-webkit-device-pixel-ratio: 3) {
min-width: $min-device-width * 3;
}
}
/* 設定容器拉伸的最大寬度 */
@mixin container-max-width() {
margin-right: auto;
margin-left: auto;
max-width: $max-device-width;
@media (-webkit-device-pixel-ratio: 2) {
max-width: $max-device-width * 2;
}
@media (-webkit-device-pixel-ratio: 3) {
max-width: $max-device-width * 3;
}
}
要注意的是,這裡的max-width也要配上dpr系數
看看成果圖
如果僅僅限制計算基準值,容器不限制(将body标簽中的屬性去掉),就可以實作某種流式效果(另一種方案)
文本大小是否用rem機關
有時我們不希望文本在Retina螢幕下變小,另外,我們希望在大屏手機上看到更多文本,以及,現在絕大多數的字型檔案都自帶一些點陣尺寸,通常是16px和24px,是以我們不希望出現13px和15px這樣的奇葩尺寸。
我們可以選擇使用px直接定義
/* 設定字型大小,不使用rem機關, 根據dpr值分段調整 */
@mixin font-size($fontSize) {
font-size: $fontSize / $design-dpr;
[data-dpr="2"] & {
font-size: $fontSize / $design-dpr * 2;
}
[data-dpr="3"] & {
font-size: $fontSize / $design-dpr * 3;
}
}
@include font-size(30px);
當然了,如果要求不嚴格,也可以直接使用rem機關
四、VW布局
REM布局中用到了JS來動态設定html的font-size,可能造成頁面的抖動。
可以考慮比較新的VW布局,無需使用JS,雖說在移動端 iOS 8 以上以及 Android 4.4 以上才獲得支援,不過還是值得一用的。如果需要相容,可以嘗試 viewport-units-buggyfill
在REM布局中處理1px問題是用了視窗縮放的方案,在VW布局中就不用了,轉而使用容器縮放(transform)的方案
調用方式形如
height: px2vw(300);
同樣的,我們需要寫個轉換方法
/* 移動端頁面設計稿寬度 */
$design-width: 750;
/* 移動端頁面設計稿dpr基準值 */
$design-dpr: 2;
/*
vw與px對應關系,100vw為視窗寬度,$vw即為$px對應占多寬
$px $vw
------------- === ------------
$design-width 100vw
*/
/* 機關px轉化為vw */
@function px2vw($px) {
@return ($px / $design-width) * 100vw;
}
/* 機關vw轉化為px,可用于根據vw機關快速計算原px */
@function vw2px($vw) {
@return #{($vw / 100) * $design-width}px;
}
對于高清螢幕邊框1px問題,有三個方面需要考慮
1. 單邊邊框
2. 多邊邊框
3. 邊框的圓角
1. 單邊邊框比較簡單,本質是在目标元素上加個僞類,設定寬度(左|右邊框)或高度(上|下邊框)為1px,然後在高清螢幕下對齊進行縮放
transform-origin: 0 0;
transform: scaleY(.5);
2. 要讓僞類支援設定多邊邊框,已經不能僅僅使用寬度或高度,而應該在這個僞類上設定多邊邊框,然後設定dpr倍的寬高,再進行縮放(自左上方)
width: 200%;
height: 200%;
transform-origin: top left;
transform: scale(.5, .5);
3. 邊框圓角一般作用于多邊邊框,使用了僞類設定邊框之後,元素本身并沒有邊框,是以我們需要對僞類設定圓角,此外,也需要對元素本身設定圓角
否則就會出現這種尴尬的情況
如果隻是需要設定圓角,其實也可以不設定邊框,可以使用背景顔色來營造出這種“邊框”的分界,在VW布局中,顯示地設定邊框可能會造成代碼量太多
另外要注意的是,圓角如果設定為像素值(比如50px),在不同的dpr下它産生的圓角效果還是有差別的,是以最好也把dpr作為系數放在圓角中
針對上面三種情況,我們需要寫好一個scss的1px邊框生成器
先來看看怎麼調用
/* 底部單個邊框 */
.f-border-bottom {
@include border(
$direction: bottom,
$size: 1px,
$color: #ddd,
$style: solid
);
}
/* 正常多邊邊框 */
.f-border {
@include border(
$direction: all,
$size: 1px,
$color: #ddd,
$style: solid
);
}
/* 多個邊框不同的屬性 */
&.hover {
@include border(
$direction: (top, right, bottom, left),
$size: (3px, 2px, 1px),
$color: (#0f0, #ddd),
$style: dotted
);
}
/* 圓角邊框百分比 */
.f-border-radius {
@include border(
$direction: all,
$radius: 50%
);
}
/* 圓角邊框自定義多個角,順序 */
.f-border-radius {
@include border(
$radius: (10px, 20px, 30px, 40px)
);
}
/* 多個邊框調用 */
&:not(.info-item__tel) {
@include border(
$direction: all,
$size: 1px,
$color: #ddd,
$style: solid,
$radius: 50px
);
}
看起來調用方式還是有點複雜的,不過應該也還好吧,實在是實作不了像scale縮放那樣直接寫原生border屬性,除非使用建構工具了
這個 border生成器 是怎麼實作的呢? Show you the code ..
/**
* 元素邊框
* @param {string|list} $direction: all 為all或清單時表示多個方向的邊框,否則為單個邊框
* @param {string|list} $size: 1px 邊框尺寸,為清單時表将按照direction的順序取值
* @param {string|list} $style: solid 邊框樣式,高清裝置下僅支援solid,同上
* @param {string|list} $color: #ddd 邊框顔色,同上
* @param {string} $position: relative 元素定位方式,一般為relative即可
* @param {string} $radius: 0 邊框圓角
*/
@mixin border(
$direction: all,
$size: 1px,
$style: solid,
$color: #ddd,
$position: relative,
$radius: 0
) {
/* 多個邊框 */
@if $direction == all or type-of($direction) == list {
/* 普通裝置 */
@media not screen and (-webkit-min-device-pixel-ratio: 2) {
@include border-radius($radius);
@if $direction == all {
border: $size $style $color;
}
@else {
@for $i from 1 through length($direction) {
$item: nth($direction, $i);
border-#{$item}: getBorderItemValue($size, $i) getBorderItemValue($style, $i) getBorderItemValue($color, $i);
}
}
}
/* 高清裝置 */
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
@include border-multiple(
$direction: $direction,
$size: $size,
$color: $color,
$position: $position,
$radius: $radius
);
}
}
/* 單個邊框 */
@else {
/* 普通裝置 */
@media not screen and (-webkit-min-device-pixel-ratio: 2) {
border-#{$direction}: $size $style $color;
}
/* 高清裝置 */
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
@include border-single(
$direction: $direction,
$size: $size,
$color: $color,
$position: $position
);
}
}
}
入口 mixin 判斷裝置的dpr,然後選擇直接生成border代碼,或者分發到 border-single 和 border-multiple 中進行高清螢幕的處理
/* 實作1實體像素的單條邊框線 */
@mixin border-single(
$direction: bottom,
$size: 1px,
$color: #ddd,
$position: relative
) {
position: $position;
&:after {
content: "";
position: absolute;
#{$direction}: 0;
pointer-events: none;
background-color: $color;
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
/* 上下 */
@if ($direction == top or $direction == bottom) {
left: 0;
width: 100%;
height: $size;
@media only screen and (-webkit-device-pixel-ratio: 2) {
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
}
@media only screen and (-webkit-device-pixel-ratio: 3) {
-webkit-transform: scaleY(.333333333333);
transform: scaleY(.333333333333);
}
}
/* 左右 */
@elseif ($direction == left or $direction == right) {
top: 0;
width: $size;
height: 100%;
@media only screen and (-webkit-device-pixel-ratio: 2) {
-webkit-transform: scaleX(.5);
transform: scaleX(.5);
}
@media only screen and (-webkit-device-pixel-ratio: 3) {
-webkit-transform: scaleX(.333333333333);
transform: scaleX(.333333333333);
}
}
}
}
/* 實作1實體像素的多條邊框線 */
@mixin border-multiple(
$direction: all,
$size: 1px,
$color: #ddd,
$position: relative,
$radius: 0
) {
position: $position;
@include border-radius($radius);
&:after {
content: "";
position: absolute;
top: 0;
left: 0;
pointer-events: none;
box-sizing: border-box;
-webkit-transform-origin: top left;
@media only screen and (-webkit-device-pixel-ratio: 2) {
width: 200%;
height: 200%;
@include border-radius($radius, 2);
-webkit-transform: scale(.5, .5);
transform: scale(.5, .5);
}
@media only screen and (-webkit-device-pixel-ratio: 3) {
width: 300%;
height: 300%;
@include border-radius($radius, 3);
-webkit-transform: scale(.333333333333, .333333333333);
transform: scale(.333333333333, .333333333333);
}
@if $direction == all {
border: $size solid $color;
}
@else {
@for $i from 1 through length($direction) {
$item: nth($direction, $i);
border-#{$item}: getBorderItemValue($size, $i) solid getBorderItemValue($color, $i);
}
}
}
}
在多邊邊框中,pointer-events: none 的使用屬于核心。為了能夠看到僞類的邊框,僞類将會被置于元素上方,如此便導緻了元素被覆寫不可點選,這個css屬性就解除了這個障礙。
圓角如果使用了百分比,就不需要設定dpr系數了
可以看到,不過這麼一來,會造成代碼比較備援的問題,特别是當我們需要再次覆寫之前的邊框屬性時。
實作容器固定縱橫比
縱橫比其實還是第一次聽說,做方案調研設計就一并整合過來了
它主要是用于響應式設計中的iframe、img 和video之類的元素,實作縱橫比有很多方法
這裡使用 padding-top 百分比的方法,實作一下容器内文本區的固定縱橫比
/**
* 實作固定寬高比
* @param {string} $position: relative 定位方式
* @param {string} $width: 100% 容器寬度
* @param {string} $sub: null 容器的目标子元素
* @param {number} $aspectX: 1 容器寬
* @param {number} $aspectY: 1 容器高
*/
@mixin aspect-ratio(
$position: relative,
$width: 100%,
$sub: null,
$aspectX: 1,
$aspectY: 1
) {
overflow: hidden;
position: $position;
padding-top: percentage($aspectY / $aspectX);
width: $width;
height: 0;
@if $sub == null {
$sub: "*";
}
& > #{$sub} {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
}
/* 容器寬高比 */
.header {
@include aspect-ratio(
// $width: px2vw(600),
// $sub: ".header-content",
$aspectX: 375,
$aspectY: 150
)
}
padding的百分比是基于元素寬度的,将容器高度設為0,根據盒子模型,則整個元素最終的高度有padding-top來決定
子元素設定絕對定位防止被擠壓,同時撐滿父級容器,即可實作
從效果圖能夠看出,美中不足是無法設定容器最大最小寬度,vw是根據裝置寬度進行計算的,是以無法解決。
五、REM + VW布局
為了解決純VW布局不能設定最大最小寬度的問題,我們引入REM。
通過配置html根元素的font-size為vw機關,并且配置最大最小的像素px值,在其他css代碼中可以直接使用rem作為機關
調用方式炒雞簡單
html {
@include root-font-size();
}
line-height: px2rem(300);
而scss裡面的實作,同樣是先定義一個映射關系。将頁面寬度進行分塊(隻是為了防止值太大)
/* 移動端頁面設計稿寬度 */
$design-width: 750;
/* 移動端頁面設計稿dpr基準值 */
$design-dpr: 2;
/* 将移動端頁面分為10塊 */
$blocks: 10;
/* 縮放所支援的裝置最小寬度 */
$min-device-width: 320px;
/* 縮放所支援的裝置最大寬度 */
$max-device-width: 540px;
/*
rem與px對應關系,1rem代表html font-size值(為一塊的寬度),$rem即為$px對應占多少塊
$px $rem
------------- === ------------
$design-width $blocks
*/
/* html根元素的font-size定義,簡單地将頁面分為$blocks塊,友善計算 */
@mixin root-font-size() {
font-size: 100vw / $blocks;
body {
@include container-min-width();
}
/* 最小寬度定義 */
@media screen and (max-width: $min-device-width) {
font-size: $min-device-width / $blocks;
}
/* 最大寬度定義 */
&[data-content-max] {
body[data-content-max] {
@include container-max-width();
}
@media screen and (min-width: $max-device-width) {
font-size: $max-device-width / $blocks;
}
}
}
/* 設定容器拉伸的最小寬度 */
@mixin container-min-width() {
margin-right: auto;
margin-left: auto;
min-width: $min-device-width;
}
/* 設定容器拉伸的最大寬度 */
@mixin container-max-width() {
margin-right: auto;
margin-left: auto;
max-width: $max-device-width;
}
這裡的max-width直接使用寬度值,因為使用的是vw,視窗未縮放
而在頁面标簽(html和body)中,簡單地配上屬性代表是否需要限制寬度即可。
<!DOCTYPE html>
<html data-content-max>
<head>
<title>VW-REM布局</title>
<meta charset="utf-8">
<meta lang="zh-CN">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
<link rel="stylesheet" href="./vw-rem.css">
</head>
<body data-content-max>
同樣是計算基準值和容器寬度兩個方面。
如果僅僅限制計算的基準值,也能實作“流式效果”
六、對比選擇
1. 方案選擇
方案是挺多的,可能也不夠完善。要選哪種方案呢?
每個方案都能保證在不同機型下做到一定的适配。
1. 一般來說,可用直接考慮使用REM布局
2. 因REM使用了JS動态設定html的font-size,且scale對安卓機型不太友好,要求極緻的可以選用VW
3. 純VW布局不支援設定容器最大最小寬高,如果需要此功能則選用 REM + VW布局
2. 食用方式
怎麼使用呢?
可在Github中對應目錄的 html,js,css檔案,看看是怎麼調用的
正常方式是引入公共基礎代碼,然後在業務代碼中調用
在html檔案中可以配置 data-content-max 參數來限制最大最小寬度
在scss基礎部分還可以自定義這幾個值(如果是REM布局的,修改這些值還需要在rem.js 檔案中同步修改)
/* 移動端頁面設計稿寬度 */
$design-width: 750;
/* 移動端頁面設計稿dpr基準值 */
$design-dpr: 2;
/* 将移動端頁面分為10塊 */
$blocks: 10;
/* 縮放所支援的裝置最小寬度 */
$min-device-width: 320px;
/* 縮放所支援的裝置最大寬度 */
$max-device-width: 540px;
[-_-]眼睛累了吧,注意勞逸結合呀[-_-]