设计稿尺寸问题
一般有分两种,如:蓝湖
- pc: 一般是
1920px * 1080px - 移动端:
414px * 896px
pc
虽然给的PC是 1920px * 1080px,但实际的高度,往往会因为系统菜单,软件菜单,应用栏等高度占据一定的高度。
实际用户可视高度只有884px, 所以实际开发我们可以按1920px * 884px去调试。
由于设计稿的内容高度1080px超出了调试的高度884px
建议
- 使用固定头部
- 下面内容正常流滚动即可
- 底部跟谁内容滚动
<div>
<header>
</header>
<section>
</section>
<footer>
</footer>
</div>
header{
position:fixed; /* 如果header前面还有其他内容可以使用sticky,滚动后定住 */
top: 0;
}
section {
margin-top:70px;
}
宽度限制
由于虽然设计稿为1920,但是为了兼容更小的尺寸一般给的内容都是包含左右边距的,一般常见实际的宽度可能是1400, 我们可以设置max-width 限制显示的宽度,超过的我们都设置为居中即可。
<div class="container">
<div class="row">
<div>
<div>
.container {
height: calc(100vh - 70px);
overflow: hidden;
}
.row {
max-width: 1400px;
height: inherit;
margin: 0 auto; /* 居中对齐*/
padding: 0 40px; /* 两边留一些边距*/
}
移动端
设计稿尺寸
移动端一般设计稿: 414px * 896px,由于浏览器一般会设置统一视口
<meta name="viewport" content="width=device-width, initial-scale=1.0">,所以最终直接按414px的大小开发即可,手机会自动把高分辨率压缩成对应的独立像素。即 414px
宽度确定 高度动态
由于移动端宽度是确定了,高度无法确定,依然跟pc一致
- 使用头部固定
- 内容自动滚动即可
不同尺寸的断点适配
我们以pc优先来编写
- pc >= 1024
- ipad >= 768 && <= 1023
- mobile < 768
.pc {display: block;}
.ipad {display: none;}
.mobile {display: none;}
@media (max-width: 1920px) {
}
@media (max-width: 1600px) {
}
@media (max-width: 1280px) {
}
@media (max-width: 1080px) {
}
@media (max-width: 1023px) {
.pc {display: none;}
.ipad {display: block;}
.mobile {display: none;}
}
@media (max-width: 768px) {
}
@media (max-width: 767px) {
.pc {display: none;}
.ipad {display: none;}
.mobile {display: block;}
}
使用
<section class='pc'>
</section >
<section class='ipad'>
</section >
<section class='mobile'>
</section >
优化写法
使用sass优化css断点写法
菜单兼容处理
pc:左边logo,右边内容
移动端:左边logo,右边更多按钮,点击显示隐藏的菜单
为了区分逻辑,一般还是分两个写,防止后期代码冲突。
根据上面的断点,处理非pc 只需要针对 class设置为mobile,处理移动端即可(一般ipad跟mobile走一个逻辑)
<div class="pc">
<header :class="['border-b-[1px]','border-gray-400','w-full','flex','justify-center','fixed','top-0' ]">
<div class="flex justify-between ">
<img class=" h-[6.25rem]" src="/assets/logo.png" alt="nrs" />
<ul class="flex items-center ">
<li @click="gotoUrl('/')">
<span >About Us</span>
</li>
<li @click="gotoUrl('/a')">
<span >About Us</span>
</li>
<li @click="gotoUrl('/b')">
<span >About Us</span>
</li>
</ul>
</div>
</header>
</div>
<div class="mobile ipad">
<header >
<div class="flex justify-between ">
<img class="w-[4rem] h-[4rem] ml-8" src="/assets/logo.png" />
<img @click="clickShowMenu(!isShowMenu)" class="w-[2rem] h-[2rem] m-4 mr-8 " :src="isShowMenu ? close : menu" />
</div>
<div v-if="isShowMenu" :class="['absolute','top-18'] ">
<ul class="flex flex-col pt-8 pb-8">
<li @click="gotoUrl('/')">
<span >About Us</span>
</li>
<li @click="gotoUrl('/a')">
<span >About Us</span>
</li>
<li @click="gotoUrl('/b')">
<span >About Us</span>
</li>
</ul>
</div>
</header>
</div>
<script setup lang="ts">
import menu from '@/assets/menu.png'
import close from '@/assets/close.png'
const route = useRoute();
const router = useRouter();
const isShowMenu = ref(false)
const clickShowMenu = (flag:boolean) => {
isShowMenu.value = flag
if(isShowMenu.value == true) {
document.body.classList.add('no-scroll'); // 背景不能滚动
}else {
document.body.classList.remove('no-scroll');
}
}
const gotoUrl = (url:string) => {
clickShowMenu(false)
router.push(url)
}
</script>
单位
元素宽度使用vh
由于在pc端和移动里面,往往宽度是固定的,所以我们要做自适应,建议参照的单位以动态变化的高度为主,
建议使用vh做参照单位
margin,padding使用 vw 和 vh
margin,padding ,左右用vw和 vh ,上下用vh
vw根据宽度动态适应
font-size 可以使用vw做参考单位,em rem也可以
.container .title {
font-size: 4.9vw; /* 94px / 1920px */
}
.container .subtitle {
font-size: 2.917vw; /* 56px / 1920px */
}
全局适配
rem
<style>
html{
font-size: 20px
}
div{
width: 5rem;
height: 5rem;
}
</style>
em
div{
font-size: 15px;
width: 5em;
height: 5em;
}
em rem 使用场景
位于默认font-size为16px不好运算,为了方便运算,我们可以统一把font-size设置成一个好运算的比例值,然后不同断点,设置对应的相对尺寸。
- 当你整个项目的维护者,则直接用rem 设置html的font-size即可。
- 当你们的代码是内嵌在别的框架内,为了避免互相影响,就不能使用rem,只能使用相对的em。
.container {
font-size: 100px;
}
.container .title {
font-size: 0.48em; /* 即设计稿上面如果是48px,只需要往右移两位即可。*/
}
.container .subtitle {
font-size: 0.24em; /* 即设计稿上面如果是24px,只需要往右移两位即可。*/
}
@media (max-width: 1680px) {
.container {
font-size: 85px;
}
}
@media (max-width: 1440px) {
.floor-container {
font-size: 80px;
}
}
@media (max-width: 1080px) {
.floor-container {
font-size: 75px;
}
}
/* ipad端 1023 - 768 */
@media (max-width: 1023px) {
.floor-container {
font-size: 75px;
}
}
/* 移动端767px 注意当尺寸为手机端,可以直接用px设置具体的元素 ,因为已经到了最小尺寸了 */
@media (max-width: 767px) {
.container {
font-size: 70px;
}
}
@media (max-width: 375px) {
}
vw / vw+rem
直接用vw
div{
width:10vw;
height:10vw;
}
html 的font-size用 vw,内容用rem
html{
font-size: 10vw; /* 如果当前是950 , 10vw就是95*/
}
div{
width:1rem; /* 95px*/
height:1rem; /* 95px*/
}
背景图
自适应填满背景图
<div class="container">
<div class="row">
<div class="row-content">
</div>
</div>
</div>
.container {
position: relative;
background: none no-repeat center center;
background-size: cover;
height: calc(100vh - 70px); /*减去固定菜单头部*/
background-color: #000;
background-image: url(xxxxx);
}
调试
插件
可以借助浏览器插件如:Window Resizer microsoftedge.microsoft.com/addons/deta…
默认提供常用的尺寸
浏览器自带调试工具
其他
视频自适应高度
通过视频设置为填满的背景,然后通过cover自适应屏幕当前的尺寸,达到自适应效果
div video {
width: 100%;
height: 100%;
position: absolute;
object-fit: cover;
}
<div>
<video muted="" webkit-playsinline="" playsinline="" preload="auto" name="media" class="video pc" autoplay="" loop="">
<source src="xxxx" type="video/mp4">
</video>
<div class="row">
</div>
</div>
上下居中处理
有些页面需要做垂直居中,建议使用flex 控制
.row {
display: flex;
margin: 0 auto;
align-items: center;
justify-content: space-between;
}
.row .item{
}
上下的高度建议使用vh控制
复杂的响应式布局
扩展概念
常用单位
英寸
就是设备屏幕对角线的长度,物理世界的真实长度。
- 1英寸 = 2.54厘米
- iphone se 尺寸: 4.7英寸
像素
每一个像素具有颜色和位置,硬件上实际显示的点。也叫设备的物理像素
分辨率
屏幕由像素组成分辨率。
英寸 和 分比率关系
手机
我们可以看到相同的手机尺寸会有不同的分辨率
如 :
- 小米XX : 6.5寸 2340* 1080 , 像素点数量: 2,918, 400
- 苹果XX : 6.5寸 2560 * 1440 , 像素点数量:2,527, 200
可以看到相同尺寸拥有不同分布率,分辨率高的会清晰一点
电视机/显示器
相同的尺寸,拥有更多的像素点显示内容会更清晰。 如电视机21寸,1024 *760 就比 800 * 600 要清晰的多。
电脑分辨率 设置
- 当显示器尾1920* 1080 ,设置 960 * 540 时候,显示器会模拟像素点。会把用多个像素模拟单个像素显示(是多个像素模拟一个模糊的像素)
- 苹果最新显示设置 支持 960 * 540 (HiDPI)会把(是多个像素模拟一个高清的像素),
像素点和清晰度的关系(PPI)
PPI:每英寸包含的像素点,ppi越高越清晰 公式:开平方根(水平像毫点数(平方)+垂直像赛点数(平方)) = ppi
独立像素
iphone 不同的尺寸为什么可以达到一样的显示效果。 假设 300 * 300px 的div ,在320 * 480 显示,接近蹭满。 在640*960 手机上,应该只会显示显示一半。
如果不同设备都做兼容,不同设备都要单独开发,成本很高。
为了统一乔布斯引入的独立像素,所有高清设备最终都要转化成独立像素,只要独立开发即可。
ratina屏幕
低分比率:1 * 1个像素 = ratina 高分辨率: 2 * 2 个像素显示。
注意显示的手机分比率都比显示起要高。 所以看起来才感觉高清。
iphone6
- 物理像素 750 * 1334
- 设备独立像素 375 * 667
设备例外: iPhone6 plus
- 物理像素 1080 * 1920
- 设备独立像素 414 * 736
可以通过浏览器模拟手机
还原pc
例子
如果要显示 300 * 300 div 在不同iphone都一样
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
div{
width: 300px;
height: 300px;
background-color: red;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
- div元素 300 * 300
- iphone6 128 * 128
- 布局视口 980
- 设备独立像素 375 * 667
实际显示的div = 设备独立像素宽度 / 布局视口 * div宽度
375 / 980 * 300 = 114
- 当
布局视口 == 设备独立像素, 实际显示的div == css里面设置的 300px - 要做的就是把默认的 980 设置为 375
视口
布局视口
基准视口:无论pc和移动端默认布局宽度 980px, 是一个固定的物理宽度
- document.documentElement.clientWidth(pc不包含滚动条,菜单栏)
- document.innerWidth(pc包含滚动条,菜单栏)
- pc会随着宽度拉大而变化
- 移动端由于不会动态拉大,所以都是一个默认值980
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
div{
width: 970px;
height: 300px;
background-color: red;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
我们可以看到当不特殊声明的时候,在移动端 默认是视口980的宽度,我们设置970基本上快填满
视觉视口
- 尤其是移动端显示的宽,比如 iphone是独立像素宽度是 375 * 667,虽然iphone的尺寸是750 但是实际是按 独立像素显示,所以理想的宽度还是 375
- window.screen.width
理想视口
就是布局视口 == 设备独立像素
通过设置 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 实现
| 属性 | 值 | 描述 |
|---|---|---|
| width | 正整数 或 device-width | 以像素为单位,定义布局视口的宽度,一般默认980px |
| height | 正整数 或 device-height | 以像素为单位,定义布局视口的高度 |
| initial-scale | 允许是小数 | 定义页面初始缩放比例 |
| minimum-scale | 0.0 - 10.0 | 定义缩放的最小值 |
| maximum-scale | 允汻是小数 | 定义缩放的最大值(ios10&ios10+无效) |
| user-scalable | yes / no | 设置是香允许缩放,同上无效 |
-
initial-scale = 等比缩放: 设备独立像素/视觉视口宽度
-
视觉视口宽度 = 设备独立像素 / initial-scale
-
device-width 默认就是 设备独立像素的宽度
-
ios10及 ios10+设置最大缩放值无效
-
initial 和 width 是有冲突的
-
initial 和 最小值 是一致的
-
部分安卓机型,不接受width=具体数值
-
正常情況下,我们会把初始最大都设置为1、不允许用户缩放而而
结论
- meta viewport 标签只对移动端浏览器有效,对 PC 端浏览器是无效的。
- 当移动端的时候,设置
width=device-width后,如iphone, initial-scale的值原来 是 375/980,变成375/375 = 1,达到布局视口 == 视觉视口 == 理想视口
适配
由于iphone也有不同的尺寸,如 iphone se 和 iPhone xr。一个是 375 一个是414 。
方案1 直接写PX + meta设置scale缩放
- 适合已有已经直接写px的项目
- 先根据当前写死px是根据多少尺寸宽度编写,然后拿到比例值
- 在动态运行时,判断当前设备的尺寸,再通过 meta设置scale缩放
«script>
var meta = document. createElement("meta");
var scale = 1 / window. devicePixelRatio;
meta. name = "viewport":
meta.content = "initial-scale" + scale +",minimum-scale"+
scale+",maximum-scale="+ scale+" ,user-scalable=no":
document. head.appendchild(meta);
方案2 视口宽度 + html设置font-size em 或 rem 。
var widths = document.documentElement.clientwidth;
var num = 10;
html.style.fontsize = widths / num + 'px'; //通过当前浏览器布局视口宽度 来动态计算所有元素的宽度。 除于10 方便计算。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
width: 5rem;
height: 5rem;
background-color: red;
}
</style>
</head>
<body>
<div></div>
<script>
var widths = document.documentElement.clientWidth;
var num = 10;
document.documentElement.style.fontSize = widths / num + 'px'; //通过当前浏览器布局视口宽度 来动态计算所有元素的宽度。 除于10 方便计算。
</script>
</body>
</html>
当在iphone se div宽度是187.5px fontsize是37.5px
当在iphone xr div宽度是207px fontsize是41.4px
滚动到顶部
- 滚动按钮默认隐藏
- 监听滚动事件,如果滚动条超过当前屏幕,则显示按钮
- 如果滚动条小于超过当前屏幕,则隐藏按钮
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>backtotop</title>
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<style>
#header {
padding-bottom: 2000px;
border: 1px solid #000;
}
#footer {
padding-bottom: 2000px;
border: 1px solid #000;
}
.container {
position: relative;
font-size: 16px;
/* overflow: hidden; */
}
/* 返回首页 */
.product-back-to-top {
position: fixed;
right: 5vw;
bottom: 5vw;
cursor: pointer;
width: 80px;
height: 80px;
border-radius: 40px;
display: flex;
z-index: 11;
flex-direction: column;
align-items: center;
font-weight: bold;
justify-content: space-evenly;
box-shadow: 0 10px 16px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
opacity: 0.8;
/* 默认不显示 */
visibility: hidden;
}
.product-back-to-top:hover {
opacity: 1;
}
.product-back-to-top i {
transform: rotate(-90deg);
font-size: 32px;
vertical-align: middle;
}
</style>
<body>
<div class="container">
<div class="product-back-to-top">
<span>Top</span>
</div>
<div id="header">
我是header
</div>
<div class="gsap">
我是内容
</div>
<div id="footer">
我是footer
</div>
</div>
<script>
$(document).ready(function() {
let fixedStartVal = 70;
if ($(window).width() < 1023) { // ipad 或移动
fixedStartVal = 52;
}
// 返回顶部
$('.product-back-to-top').click(function () {
var container = $('html');
let offset = $("#header").offset().top - fixedStartVal
container.animate({ scrollTop: offset })
})
checkBackToTopState()
function checkBackToTopState() {
let nowTop = $(window).scrollTop()
let screenHeight = $(window).height()
console.log("nowTop",nowTop,screenHeight)
// if ($(window).width() < 767) { //只有ipad 或 移动端才控制
if (nowTop < screenHeight) {
$('.product-back-to-top').css("visibility", "hidden")
} else {
$('.product-back-to-top').css("visibility", "visible")
}
// }
}
$(window).scroll(function () {
checkBackToTopState()
})
});
</script>
</body>
</html>