一、什么是宏函数?通过宏定义的函数是宏函数。如下,编译器在预处理阶段会将Add(x,y)替换为((x)*(y))#defineAdd(x,y)((x)*(y))#defineAdd(x,y)((x)*(y))intmain(){inta=10;intb=20;intd=10;intc=Add(a+d,b)*2;cout<
地推话术,如何应对地推过程中家长的拒绝
校师学
相信校长们在做地推的时候经常遇到这种情况:市场专员反馈家长不接单,咨询师反馈难以邀约这些家长上门,校区地推疲软,招生难。为什么?仅从地推层面分析,一方面因为家长受到的信息轰炸越来越多,对信息越来越“免疫”;而另一方面地推人员的专业能力和营销话术没有提高,无法应对家长的拒绝,对有意向的家长也不知如何跟进,眼睁睁看着家长走远;对于家长的疑问,更不知道如何有技巧地回答,机会白白流失。由于回答没技巧和专业
谢谢你们,爱你们!
鹿游儿
昨天家人去泡温泉,二个孩子也带着去,出发前一晚,匆匆下班,赶回家和孩子一起收拾。饭后,我拿出笔和本子(上次去澳门时做手帐的本子)写下了1\2\3\4\5\6\7\8\9,让后让小壹去思考,带什么出发去旅游呢?她在对应的数字旁边画上了,泳衣、泳圈、肖恩、内衣内裤、tapuy、拖鞋……画完后,就让她自己对着这个本子,将要带的,一一带上,没想到这次带的书还是这本《便便工厂》(晚上姑婆发照片过来,妹妹累得
C语言如何定义宏函数?
小九格物
c语言
在C语言中,宏函数是通过预处理器定义的,它在编译之前替换代码中的宏调用。宏函数可以模拟函数的行为,但它们不是真正的函数,因为它们在编译时不会进行类型检查,也不会分配存储空间。宏函数的定义通常使用#define指令,后面跟着宏的名称和参数列表,以及宏展开后的代码。宏函数的定义方式:1.基本宏函数:这是最简单的宏函数形式,它直接定义一个表达式。#defineSQUARE(x)((x)*(x))2.带参
微服务下功能权限与数据权限的设计与实现
nbsaas-boot
微服务java架构
在微服务架构下,系统的功能权限和数据权限控制显得尤为重要。随着系统规模的扩大和微服务数量的增加,如何保证不同用户和服务之间的访问权限准确、细粒度地控制,成为设计安全策略的关键。本文将讨论如何在微服务体系中设计和实现功能权限与数据权限控制。1.功能权限与数据权限的定义功能权限:指用户或系统角色对特定功能的访问权限。通常是某个用户角色能否执行某个操作,比如查看订单、创建订单、修改用户资料等。数据权限:
理解Gunicorn:Python WSGI服务器的基石
范范0825
ipythonlinux运维
理解Gunicorn:PythonWSGI服务器的基石介绍Gunicorn,全称GreenUnicorn,是一个为PythonWSGI(WebServerGatewayInterface)应用设计的高效、轻量级HTTP服务器。作为PythonWeb应用部署的常用工具,Gunicorn以其高性能和易用性著称。本文将介绍Gunicorn的基本概念、安装和配置,帮助初学者快速上手。1.什么是Gunico
小丽成长记(四十三)
玲玲54321
小丽发现,即使她好不容易调整好自己的心态下一秒总会有不确定的伤脑筋的事出现,一个接一个的问题,人生就没有停下的时候,小问题不断出现。不过她今天看的书,她接受了人生就是不确定的,厉害的人就是不断创造确定性,在Ta的领域比别人多的确定性就能让自己脱颖而出,显示价值从而获得的比别人多的利益。正是这样的原因,因为从前修炼自己太少,使得她现在在人生道路上打怪起来困难重重,她似乎永远摆脱不了那种无力感,有种习
学点心理知识,呵护孩子健康
静候花开_7090
昨天听了华中师范大学教育管理学系副教授张玲老师的《哪里才是学生心理健康的最后庇护所,超越教育与技术的思考》的讲座。今天又重新学习了一遍,收获匪浅。张玲博士也注意到了当今社会上的孩子由于心理问题导致的自残、自杀及伤害他人等恶性事件。她向我们普及了一个重要的命题,她说心理健康的一些基本命题,我们与我们通常的一些教育命题是不同的,她还举了几个例子,让我们明白我们原来以为的健康并非心理学上的健康。比如如果
2021年12月19日,春蕾教育集团团建活动感受——黄晓丹
黄错错加油
感受:1.从陌生到熟悉的过程。游戏环节让我们在轻松的氛围中得到了锻炼,也增长了不少知识。2.游戏过程中,我们贡献的是个人力量,展现的是团队的力量。它磨合的往往不止是工作的熟悉,更是观念上契合度的贴近。3.这和工作是一样的道理。在各自的岗位上,每个人摆正自己的位置、各司其职充分发挥才能,并团结一致劲往一处使,才能实现最大的成功。新知:1.团队精神需要不断地创新。过去,人们把创新看作是冒风险,现在人们
Cell Insight | 单细胞测序技术又一新发现,可用于HIV-1和Mtb共感染个体诊断
尐尐呅
结核病是艾滋病合并其他疾病中导致患者死亡的主要原因。其中结核病由结核分枝杆菌(Mycobacteriumtuberculosis,Mtb)感染引起,获得性免疫缺陷综合症(艾滋病)由人免疫缺陷病毒(Humanimmunodeficiencyvirustype1,HIV-1)感染引起。国家感染性疾病临床医学研究中心/深圳市第三人民医院张国良团队携手深圳华大生命科学研究院吴靓团队,共同研究得出单细胞测序
c++ 的iostream 和 c++的stdio的区别和联系
黄卷青灯77
c++算法开发语言iostreamstdio
在C++中,iostream和C语言的stdio.h都是用于处理输入输出的库,但它们在设计、用法和功能上有许多不同。以下是两者的区别和联系:区别1.编程风格iostream(C++风格):C++标准库中的输入输出流类库,支持面向对象的输入输出操作。典型用法是cin(输入)和cout(输出),使用>操作符来处理数据。更加类型安全,支持用户自定义类型的输入输出。#includeintmain(){in
瑶池防线
谜影梦蝶
冥华虽然逃过了影梦的军队,但他是一个忠臣,他选择上报战况。败给影梦后成逃兵,高层亡尔还活着,七重天失守......随便一条,即可处死冥华。冥华自然是知道以仙界高层的习性此信一发自己必死无疑,但他还选择上报实情,因为责任。同样此信送到仙宫后,知道此事的人,大多数人都认定冥华要完了,所以上到仙界高层,下到扫大街的,包括冥华自己,全都准备好迎接冥华之死。如果仙界现在还属于两方之争的话,冥华必死无疑。然而
爬山后遗症
璃绛
爬山,攀登,一步一步走向制高点,是一种挑战。成功抵达是一种无法言语的快乐,在山顶吹吹风,看看风景,这是从未有过的体验。然而,爬山一时爽,下山腿打颤,颠簸的路,一路向下走,腿部力量不够,走起来抖到不行,停不下来了!第二天必定腿疼,浑身酸痛,坐立难安!
C/C++Win32编程基础详解视频下载
择善Zach
编程C++Win32
课题视频:C/C++Win32编程基础详解
视频知识:win32窗口的创建
windows事件机制
主讲:择善Uncle老师
学习交流群:386620625
验证码:625
--
Guava Cache使用笔记
bylijinnan
javaguavacache
1.Guava Cache的get/getIfPresent方法当参数为null时会抛空指针异常
我刚开始使用时还以为Guava Cache跟HashMap一样,get(null)返回null。
实际上Guava整体设计思想就是拒绝null的,很多地方都会执行com.google.common.base.Preconditions.checkNotNull的检查。
2.Guava
解决ora-01652无法通过128(在temp表空间中)
0624chenhong
oracle
解决ora-01652无法通过128(在temp表空间中)扩展temp段的过程
一个sql语句后,大约花了10分钟,好不容易有一个结果,但是报了一个ora-01652错误,查阅了oracle的错误代码说明:意思是指temp表空间无法自动扩展temp段。这种问题一般有两种原因:一是临时表空间空间太小,二是不能自动扩展。
分析过程:
既然是temp表空间有问题,那当
Struct在jsp标签
不懂事的小屁孩
struct
非UI标签介绍:
控制类标签:
1:程序流程控制标签 if elseif else
<s:if test="isUsed">
<span class="label label-success">True</span>
</
按对象属性排序
换个号韩国红果果
JavaScript对象排序
利用JavaScript进行对象排序,根据用户的年龄排序展示
<script>
var bob={
name;bob,
age:30
}
var peter={
name;peter,
age:30
}
var amy={
name;amy,
age:24
}
var mike={
name;mike,
age:29
}
var john={
大数据分析让个性化的客户体验不再遥远
蓝儿唯美
数据分析
顾客通过多种渠道制造大量数据,企业则热衷于利用这些信息来实现更为个性化的体验。
分析公司Gartner表示,高级分析会成为客户服务的关键,但是大数据分析的采用目前仅局限于不到一成的企业。 挑战在于企业还在努力适应结构化数据,疲于根据自身的客户关系管理(CRM)系统部署有效的分析框架,以及集成不同的内外部信息源。
然而,面对顾客通过数字技术参与而产生的快速变化的信息,企业需要及时作出反应。要想实
java笔记4
a-john
java
操作符
1,使用java操作符
操作符接受一个或多个参数,并生成一个新值。参数的形式与普通的方法调用不用,但是效果是相同的。加号和一元的正号(+)、减号和一元的负号(-)、乘号(*)、除号(/)以及赋值号(=)的用法与其他编程语言类似。
操作符作用于操作数,生成一个新值。另外,有些操作符可能会改变操作数自身的
从裸机编程到嵌入式Linux编程思想的转变------分而治之:驱动和应用程序
aijuans
嵌入式学习
笔者学习嵌入式Linux也有一段时间了,很奇怪的是很多书讲驱动编程方面的知识,也有很多书将ARM9方面的知识,但是从以前51形式的(对寄存器直接操作,初始化芯片的功能模块)编程方法,和思维模式,变换为基于Linux操作系统编程,讲这个思想转变的书几乎没有,让初学者走了很多弯路,撞了很多难墙。
笔者因此写上自己的学习心得,希望能给和我一样转变
在springmvc中解决FastJson循环引用的问题
asialee
循环引用fastjson
我们先来看一个例子:
package com.elong.bms;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import co
ArrayAdapter和SimpleAdapter技术总结
百合不是茶
androidSimpleAdapterArrayAdapter高级组件基础
ArrayAdapter比较简单,但它只能用于显示文字。而SimpleAdapter则有很强的扩展性,可以自定义出各种效果
ArrayAdapter;的数据可以是数组或者是队列
// 获得下拉框对象
AutoCompleteTextView textview = (AutoCompleteTextView) this
九封信
bijian1013
人生励志
有时候,莫名的心情不好,不想和任何人说话,只想一个人静静的发呆。有时候,想一个人躲起来脆弱,不愿别人看到自己的伤口。有时候,走过熟悉的街角,看到熟悉的背影,突然想起一个人的脸。有时候,发现自己一夜之间就长大了。 2014,写给人
Linux下安装MySQL Web 管理工具phpMyAdmin
sunjing
PHPInstallphpMyAdmin
PHP http://php.net/
phpMyAdmin http://www.phpmyadmin.net
Error compiling PHP on CentOS x64
一、安装Apache
请参阅http://billben.iteye.com/admin/blogs/1985244
二、安装依赖包
sudo yum install gd
分布式系统理论
bit1129
分布式
FLP
One famous theory in distributed computing, known as FLP after the authors Fischer, Lynch, and Patterson, proved that in a distributed system with asynchronous communication and process crashes,
ssh2整合(spring+struts2+hibernate)-附源码
白糖_
eclipsespringHibernatemysql项目管理
最近抽空又整理了一套ssh2框架,主要使用的技术如下:
spring做容器,管理了三层(dao,service,actioin)的对象
struts2实现与页面交互(MVC),自己做了一个异常拦截器,能拦截Action层抛出的异常
hibernate与数据库交互
BoneCp数据库连接池,据说比其它数据库连接池快20倍,仅仅是据说
MySql数据库
项目用eclipse
treetable bug记录
braveCS
table
// 插入子节点删除再插入时不能正常显示。修改:
//不知改后有没有错,先做个备忘
Tree.prototype.removeNode = function(node) {
// Recursively remove all descendants of +node+
this.unloadBranch(node);
// Remove
编程之美-电话号码对应英语单词
bylijinnan
java算法编程之美
import java.util.Arrays;
public class NumberToWord {
/**
* 编程之美 电话号码对应英语单词
* 题目:
* 手机上的拨号盘,每个数字都对应一些字母,比如2对应ABC,3对应DEF.........,8对应TUV,9对应WXYZ,
* 要求对一段数字,输出其代表的所有可能的字母组合
jquery ajax读书笔记
chengxuyuancsdn
jQuery ajax
1、jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()
JWFD工作流拓扑结构解析伪码描述算法
comsci
数据结构算法工作活动J#
对工作流拓扑结构解析感兴趣的朋友可以下载附件,或者下载JWFD的全部代码进行分析
/* 流程图拓扑结构解析伪码描述算法
public java.util.ArrayList DFS(String graphid, String stepid, int j)
oracle I/O 从属进程
daizj
oracle
I/O 从属进程
I/O从属进程用于为不支持异步I/O的系统或设备模拟异步I/O.例如,磁带设备(相当慢)就不支持异步I/O.通过使用I/O 从属进程,可以让磁带机模仿通常只为磁盘驱动器提供的功能。就好像支持真正的异步I/O 一样,写设备的进程(调用者)会收集大量数据,并交由写入器写出。数据成功地写出时,写入器(此时写入器是I/O 从属进程,而不是操作系统)会通知原来的调用者,调用者则会
高级排序:希尔排序
dieslrae
希尔排序
public void shellSort(int[] array){
int limit = 1;
int temp;
int index;
while(limit <= array.length/3){
limit = limit * 3 + 1;
初二下学期难记忆单词
dcj3sjt126com
englishword
kitchen 厨房
cupboard 厨柜
salt 盐
sugar 糖
oil 油
fork 叉;餐叉
spoon 匙;调羹
chopsticks 筷子
cabbage 卷心菜;洋白菜
soup 汤
Italian 意大利的
Indian 印度的
workplace 工作场所
even 甚至;更
Italy 意大利
laugh 笑
m
Go语言使用MySQL数据库进行增删改查
dcj3sjt126com
mysql
目前Internet上流行的网站构架方式是LAMP,其中的M即MySQL, 作为数据库,MySQL以免费、开源、使用方便为优势成为了很多Web开发的后端数据库存储引擎。MySQL驱动Go中支持MySQL的驱动目前比较多,有如下几种,有些是支持database/sql标准,而有些是采用了自己的实现接口,常用的有如下几种:
http://code.google.c...o-mysql-dri
git命令
shuizhaosi888
git
---------------设置全局用户名:
git config --global user.name "HanShuliang" //设置用户名
git config --global user.email "
[email protected]" //设置邮箱
---------------查看环境配置
git config --li
qemu-kvm 网络 nat模式 (四)
haoningabc
kvmqemu
qemu-ifup-NAT
#!/bin/bash
BRIDGE=virbr0
NETWORK=192.168.122.0
GATEWAY=192.168.122.1
NETMASK=255.255.255.0
DHCPRANGE=192.168.122.2,192.168.122.254
TFTPROOT=
BOOTP=
function check_bridge()
不要让未来的你,讨厌现在的自己
jingjing0907
生活 奋斗 工作 梦想
故事one
23岁,他大学毕业,放弃了父母安排的稳定工作,独闯京城,在家小公司混个小职位,工作还算顺手,月薪三千,混了混,混走了一年的光阴。 24岁,有了女朋友,从二环12人的集体宿舍搬到香山民居,一间平房,二人世界,爱爱爱。偶然约三朋四友,打扑克搓麻将,日子快乐似神仙; 25岁,出了几次差,调了两次岗,薪水涨了不过百,生猛狂飙的物价让现实血淋淋,无力为心爱银儿购件大牌
枚举类型详解
一路欢笑一路走
enum枚举详解enumsetenumMap
枚举类型详解
一.Enum详解
1.1枚举类型的介绍
JDK1.5加入了一个全新的类型的”类”—枚举类型,为此JDK1.5引入了一个新的关键字enum,我们可以这样定义一个枚举类型。
Demo:一个最简单的枚举类
public enum ColorType {
RED
第11章 动画效果(上)
onestopweb
动画
index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/
Eclipse中jsp、js文件编辑时,卡死现象解决汇总
ljf_home
eclipsejsp卡死js卡死
使用Eclipse编辑jsp、js文件时,经常出现卡死现象,在网上百度了N次,经过N次优化调整后,卡死现象逐步好转,具体那个方法起到作用,不太好讲。将所有用过的方法罗列如下:
1、取消验证
windows–>perferences–>validation
把 除了manual 下面的全部点掉,build下只留 classpath dependency Valida
MySQL编程中的6个重要的实用技巧
tomcat_oracle
mysql
每一行命令都是用分号(;)作为结束
对于MySQL,第一件你必须牢记的是它的每一行命令都是用分号(;)作为结束的,但当一行MySQL被插入在PHP代码中时,最好把后面的分号省略掉,例如:
mysql_query("INSERT INTO tablename(first_name,last_name)VALUES('$first_name',$last_name')");
zoj 3820 Building Fire Stations(二分+bfs)
阿尔萨斯
Build
题目链接:zoj 3820 Building Fire Stations
题目大意:给定一棵树,选取两个建立加油站,问说所有点距离加油站距离的最大值的最小值是多少,并且任意输出一种建立加油站的方式。
解题思路:二分距离判断,判断函数的复杂度是o(n),这样的复杂度应该是o(nlogn),即使常数系数偏大,但是居然跑了4.5s,也是醉了。 判断函数里面做了3次bfs,但是每次bfs节点最多
本文是内部的一次分享沉淀,偏向基础但是涉及了一些有意思的细节,文笔有限,才疏学浅,文中若有不正之处,万望告知。
前端的一大工作内容就是去兼容页面在不同内核的浏览器,不同的设备,不同的分辨率下的行为,使页面的能正常工作在各种各样的宿主环境当中。
而本文的主题 -- 移动端开发的兼容适配与性能优化,就是希望能从一些常见的移动端开发问题出发,厘清 Web 移动端开发的前前后后,一些技术的发展过程,一些问题的优化手段以及给出一些常见的兼容性问题的解决方案。
什么是响应式设计
首先先聊聊响应式设计,这个与移动端开发有着密切的联系。
响应式设计即是 RWD,Responsive Web Design。
这里百度或者谷歌一下会有各种各样的答案。这里一段摘自知乎上我觉得很棒的一个答案:什么是响应式布局设计?
根据维基百科及其参考文献,理论上,响应式界面能够适应不同的设备。描述响应式界面最著名的一句话就是“Content is like water”,翻译成中文便是“如果将屏幕看作容器,那么内容就像水一样”。
为什么要设计响应式界面
为什么要费神地尝试统一所有设备呢?
响应式界面的四个层次
响应式界面的基本规则
可伸缩的内容区块:内容区块的在一定程度上能够自动调整,以确保填满整个页面
可自由排布的内容区块:当页面尺寸变动较大时,能够减少/增加排布的列数
适应页面尺寸的边距:到页面尺寸发生更大变化时,区块的边距也应该变化
能够适应比例变化的图片:对于常见的宽度调整,图片在隐去两侧部分时,依旧保持美观可用
能够自动隐藏/部分显示的内容:如在电脑上显示的的大段描述文本,在手机上就只能少量显示或全部隐藏
能自动折叠的导航和菜单:展开还是收起,应该根据页面尺寸来判断
放弃使用像素作为尺寸单位:用dp(对于前端来说,这里可能是rem)尺寸等方法来确保页面在分辨率相差很大的设备上,看起来也能保持一致。同时也要求提供的图片应该比预想的更大,才能适应高分辨率的屏幕
上面一段我觉得已经涵盖了响应式设计的绝大部分,简单总结起来,可以概括为:
响应式 vs. 自适应
响应式设计是 Responsive Web Design(RWD),自适应设计是 Adaptive Web Design(AWD)。经常有人会将两者混为一谈,或者其实根本也区分不了所谓的响应式与自适应。
其实在我写这篇文章的时候,我也无法很好的去区分两者。
RWD 和 AWD 两者都是为了适配各种不同的移动设备,致力于提升用户体验所产生的的技术。核心思想是用技术来使网页适应从小到大(现在到超大)的不同分辨率的屏幕。通常认为,RWD 是 AWD 的子集。
RWD:Ethan Marcote 的文章是大家认为 RWD 的起源。他提出的 RWD 方案是通过 HTML 和 CSS 的媒体查询技术,配合流体布局实现。RWD 倾向于只改变元素的外观布局,而不大幅度改变内容。Jeffrey Zeldman 总结说,我们就把 RWD 定义为一切能用来为各种分辨率和设备性能优化视觉体验的技术。
AWD:Adaptive Design 是 Aaron Gustafson 的书的标题。他认为 AWD 在包括 RWD 的 CSS 媒体查询技术以外,也要用 Javascript 来操作 HTML 来更适应移动设备的能力。AWD 有可能会针对移动端用户减去内容,减去功能。AWD 可以在服务器端就进行优化,把优化过的内容送到终端上。
一图胜千言。
从定义上而言,RWD 是一套代码,适用于所有屏幕。而 AWD 则是多端多套代码。本文不会过多去纠结响应式与自适应区别,我觉得这两者的本质都是致力于适配不同设备,更好地提升用户体验。
Quora - Responsive Design vs. Adaptive Design?
zhihu -- Responsive design 和 Adaptive design 的区别
渐进增强 vs. 优雅降级
渐进增强(progressive enhancement):针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
优雅降级(graceful degradation):一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
区别:优雅降级是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带。
渐进增强/优雅降级通常是 AWD 会牵扯到的另一个技术术语。本质上而言即是随着屏幕的大小的改变,功能会一点一点增强。
也通常会用在一些高级 CSS3 属性上,我们对一些 CSS 属性进行特性检测,甚至不进行特性检测直接使用。后果是在支持它的网页上该属性正常展示,而不支持它的网页该属性不生效,但也不影响用户的基本使用。
典型的例子是 CSS3 逐渐被大众认可并被使用,PC端页面开始由 IE678 向兼容性更好的IE9+,chrome,firefox浏览器转变的时期。我们可以对页面元素直接使用阴影,圆角等属性。对于不支持它的低版本 IE 而言,没有什么损失,而对于支持它的高级浏览器而言,带给了用户更好的交互视觉体验,这就是渐进增强。
移动端屏幕适配方案
下面会针对一些具体的案例,展开讲讲。第一个是高保真还原设计稿,也就是如何适配移动端繁杂的屏幕大小。
通常而言,设计师只会给出单一分辨率下的设计稿,而我们要做的,就是以这个设计稿为基准,去适配所有不同大小的移动端设备。
在此之前,有一些基础概念需要理解。
设备独立像素
以 iPhone6/7/8为例,这里我们打开 Chrome 开发者工具:
这里的
375 * 667
表示的是什么呢,表示的是设备独立像素(DIP),也可以理解为 CSS 像素,也称为逻辑像素:设备独立像素 = CSS 像素 = 逻辑像素
如何记忆呢?这里使用 CSS 像素来记忆,也就是说。我们设定一个宽度为 375px 的 div,刚好可以充满这个设备的一行,配合高度 667px ,则 div 的大小刚好可以充满整个屏幕。
物理像素
OK,那么,什么又是物理像素呢。我们到电商网站购买手机,都会看一看手机的参数,以 JD 上的 iPhone7 为例:
可以看到,iPhone7 的分辨率是
1334 x 750
,这里描述的就是屏幕实际的物理像素。物理像素,又称为设备像素。显示屏是由一个个物理像素点组成的,
1334 x 750
表示手机分别在垂直和水平上所具有的像素点数。通过控制每个像素点的颜色,就可以使屏幕显示出不同的图像,屏幕从工厂出来那天起,它上面的物理像素点就固定不变了,单位为pt。设备像素 = 物理像素
DPR(Device Pixel Ratio) 设备像素比
OK,有了上面两个概念,就可以顺理成章引出下一个概念。DPR(Device Pixel Ratio) 设备像素比,这个与我们通常说的视网膜屏(多倍屏,Retina屏)有关。
设备像素比描述的是未缩放状态下,物理像素和设备独立像素的初始比例关系。
简单的计算公式:
DPR = 物理像素 / 设备独立像素
我们套用一下上面 iPhone7 的数据(取设备的物理像素宽度与设备独立像素宽度进行计算):
iPhone7’s DPR = iPhone7’s 物理像素宽度 / iPhone7's 设备独立像素宽度 = 2
可以得到 iPhone7 的 dpr 为 2。也就是我们常说的视网膜屏幕。
视网膜(Retina)屏幕是苹果公司"发明"的一个营销术语。 苹果公司将
dpr > 1
的屏幕称为视网膜屏幕。在视网膜屏幕中,以 dpr = 2 为例,把 4(2x2) 个像素当 1 个像素使用,这样让屏幕看起来更精致,但是元素的大小本身却不会改变:
OK,我们再来看看 iPhone XS Max:
它的物理像素如上图是
2688 x 1242
,它的 CSS 像素是
896 x 414
,很容易得出 iPhone XS Max 的 dpr 为 3。OK,到这里我们就完成了一个小的里程碑。我们通常说的H5手机适配也就是指的这两个维度:
适配不同屏幕大小
适配不同屏幕大小,也就是适配不同屏幕下的 CSS 像素。最早移动端屏幕 CSS 像素适配方案是CSS媒体查询。但是无法做到高保真接近 100% 的还原。
适配不同屏幕大小其实只需要遵循一条原则,确保页面元素大小的与屏幕大小保持一定比例。也就是:按比例还原设计稿
假设我们现在拿到标注为
375*667
的大小的设计稿,其中一个元素的标注如下:以页面宽度为基准的话,那么,
209/375 = 55.73%
80/375 = 21.33%
这样,无论屏幕的 CSS 像素宽度是 320px 还是 375px 还是 414px,按照等量百分比还原出来的界面总是正确的。
然而,理想很丰满,现实很骨感。实现上述百分比方案的核心需要一个全局通用的基准单位,让所有百分比展示以它为基准,但是在 CSS 中,根据CSS Values and Units Module Level 4的定义:
具体来说:
宽度(width)、间距(maring/padding)支持百分比值,但默认的相对参考值是包含块的宽度;
高度(height)百分比的大小是相对其父级元素高的大小;
边框(border)不支持百分值;
边框圆角半径(border-radius)支持百分比值,但水平方向相对参考值是盒子的宽度,垂直方向相对参考值是盒子的高度;
文本大小(font-size)支持百分比值,但相对参考值是父元素的font-size的值;
盒阴影(box-shadow)和文本阴影(text-shadow)不支持百分比值;
首先,支持百分比单位的度量属性有其各自的参照基准,其次并非所有度量属性都支持百分比单位。所以我们需要另辟蹊径。
rem 适配方案
在 vw 方案出来之前,最被大众接受的就是使用 rem 进行适配的方案,因为 rem 满足上面说的,可以是一个全局性的基准单位。
flexible
基于此,淘宝早年推行的一套以 rem 为基准的适配方案:lib-flexible。其核心做法在于:
标签,设置 viewport 的缩放
元素添加 data-dpr 属性,并且动态改写 data-dpr 的值
document.documentElement.clientWidth
动态修改的 font-size ,页面其他元素使用 rem 作为长度单位进行布局,从而实现页面的等比缩放
hotcss
hotcss 不是一个库,也不是一个框架。它是一个移动端布局开发解决方案。使用 hotcss 可以让移动端布局开发更容易。本质的思想与 flexible 完全一致。
对于 rem 方案的一些总结
使用 flexible/hotcss 作为屏幕宽度适配解决方案,是存在一些问题的:
innerWidth/innerHeight
也会随之发生变化,如果业务逻辑有获取此类高宽进行其他计算的,可能会导致意想不到的错误;vw 适配方案
严格来说,使用 rem 进行页面适配其实是一种 hack 手段,rem 单位的初衷本身并不是用来进行移动端页面宽度适配的。
到了今天,有了一种更好的替代方案,使用 vw 进行适配 。
百分比适配方案的核心需要一个全局通用的基准单位,rem 是不错,但是需要借助 Javascript 进行动态修改根元素的
font-size
,而 vw/vh(vmax/vmin) 的出现则很好弥补 rem 需要 JS 辅助的缺点。根据 CSS Values and Units Module Level 4:
vw
等于初始包含块(html元素)宽度的1%,也就是1vw
等于window.innerWidth
的数值的 1%1vh
等于window.innerHeight
的数值的 1%再以上面设计稿图的元素为例,那么,
209/375 = 55.73% = 55.73vw
80/375 = 21.33% = 21.33vw
根据相关的测试,可以使用 vw 进行长度单位的有:
简单的一个页面,看看效果,完全是等比例缩放的效果:
CodePen Demo(移动端打开):使用 vw 进行页面适配
自动转换插件
当我们使用 rem 作为长度单位的时,通常会有借助 Sass/Less 实现一个转换函数,像是这样:
同理,在 vw 方案下,我们只需要去改写这个方法:
当然,我们还可以借助一些插件包去实现这个自动转换,提高效率,譬如 postcss-px-to-viewport
vw polyfill
vw 现在毕竟还是存在兼容问题的,看看兼容性:
其实已经覆盖了绝大部分设备,那么如果业务使用了且又真的出现了兼容问题,应该怎么处理呢?有两种方式可以进行降级处理:
对于 vw 方案的一些总结
vw 确实看上去很不错,但是也是存在它的一些问题:
当然,两个方案现阶段其实都可以使用甚至一起搭配使用,更多详情可以读读:
1px线
上面说到使用 vw 适配屏幕大小方案,其中有一个缺点就是在 Retina 屏下,无法很好的展示真正的 1px 物理像素线条。
设计师想要的 retina 下
border: 1px
,其实是 1 物理像素宽,而不是 1 CSS 像素宽度,对于 CSS 而言:border-width: 1px
这里的 1px 其实是 1 CSS像素宽度,等于 2 像素物理宽度,设计师其实想要的是border-width: 0.5px
;然而,并不是所有手机浏览器都能识别
border-width: 0.5px
,在 iOS7 以下,Android 等其他系统里,小于 1px 的单位会被当成为 0px 处理,那么如何实现这 0.5px、0.33px 呢?这里介绍几种方法:
Retina 屏幕下 1px 线的实现
图片适配及优化
图像通常占据了网页上下载资源绝的大部分。优化图像通常可以最大限度地减少从网站下载的字节数以及提高网站性能。
通常可以,有一些通用的优化手段:
本文重点关注如何在不同的 dpr 屏幕下,让图片看起来都不失真。
首先就是上述的第二点,尽可能利用 CSS3\SVG 矢量图像替代某些光栅图像。某些简单的几何图标,可以用 CSS3 快速实现的图形,都应该尽量避免使用光栅图像。这样能够保证它们在任何尺寸下都不会失真。
其次,实在到了必须使用光栅图像的地步,也是有许多方式能保证图像在各种场景下都不失真。
无脑多倍图
在移动端假设我们需要一张 CSS 像素为
300 x 200
的图像,考虑到现在已经有了 dpr = 3 的设备,那么要保证图片在 dpr = 3 的设备下也正常高清展示,我们最大可能需要一张900 x 600
的原图。这样,不管设备的 dpr 是否为 3,我们统一都使用 3 倍图。这样即使在 dpr = 1,dpr = 2 的设备上,也能非常好的展示图片。
当然这样并不可取,会造成大量带宽的浪费。现代浏览器,提供了更好的方式,让我们能够根据设备 dpr 的不同,提供不同尺寸的图片。
srcset 配合 1x 2x 像素密度描述符
简单来说,srcset 可以根据不同的 dpr 拉取对应尺寸的图片:
上面
srcset
里的 1x,2x 表示 像素密度描述符,表示images/illustration-small.png
这张图images/illustration-big.png
这张图srcset 属性配合 sizes 属性 w 宽度描述符
上面 1x,2x 的写法比较容易接受易于理解。
除此之外,srcset属性还有一个 w 宽度描述符,配合 sizes 属性一起使用,可以覆盖更多的面。
以下面这段代码为例子:
解析一下:
sizes = “(min-width: 600px) 600px, 300px"
的意思是,如果屏幕当前的 CSS 像素宽度大于或者等于 600px,则图片的 CSS 宽度为 600px,反之,则图片的 CSS 宽度为 300px。也就是 sizes 属性声明了在不同宽度下图片的 CSS 宽度表现。这里可以理解为,大屏幕下图片宽度为 600px,小屏幕下图片宽度为 300px。(具体的媒体查询代码由 CSS 实现)
srcset = “[email protected] 300w, [email protected] 600w, [email protected] 1200w
里面的 300w,600w,900w 叫宽度描述符。怎么确定当前场景会选取哪张图片呢?1. 当前屏幕 dpr = 2 ,CSS 宽度为 375px。
当前屏幕 CSS 宽度为 375px,则图片 CSS 宽度为 300px。分别用上述 3 个宽度描述符的数值除以 300。
上面计算得到的 1、 2、 4 即是算出的有效的像素密度,换算成和 x 描述符等价的值 。这里 600w 算出的 2 即满足 dpr = 2 的情况,选择此张图。
2. 当前屏幕 dpr = 3 ,CSS 宽度为 414px。
当前屏幕 CSS 宽度为 414px,则图片 CSS 宽度仍为 300px。再计算一次:
因为 dpr = 3,2 已经不满足了,则此时会选择 1200w 这张图。
3. 当前屏幕 dpr = 1 ,CSS 宽度为 1920px。
当前屏幕 CSS 宽度为 1920px,则图片 CSS 宽度变为了 600px。再计算一次:
因为 dpr = 1,所以此时会选择 600w 对应的图片。
具体的可以试下这个 Demo:CodePen Demo -- srcset属性配合w宽度描述符配合sizes属性
此方案的意义在于考虑到了响应性布局的复杂性与屏幕的多样性,利用上述规则,可以一次适配 PC 端大屏幕和移动端高清屏,一箭多雕。
了解更多细节,推荐看看:
字体适配方案
字体大小
字体是很多前端开发同学容易忽略的一个点,但是其中也是有很多小知识点。
首先要知道,浏览器有最小字体限制:
如果小于最小字体,那么字体默认就是最小字体。
字体的选择展示
在字体适配上面,我们需要从性能和展示效果两个维度去考虑。
完整的一个字体资源实在太大了,所以我们应该尽可能的使用用户设备上已有的字体,而不是额外去下载字体资源,从而使加载时间明显加快。
而从展示效果层面来说,使用系统字体能更好的与当前操作系统使用的相匹配,得到最佳的展示效果。所以我们在字体使用方面,有一个应该尽量去遵循的原则,也是现在大部分网站在字体适配上使用的策略:
使用各个支持平台上的默认系统字体。
兼顾各个操作系统
常见的操作系统有 Windows、Windows Phone、Mac OS X、iPhone、Android Phone、Linux。当然对于普通用户而言,无须关注 Linux 系统。
下面就以 CSS-Trick 网站最新的 font-family 为例,看看他们是如何在字体选择上做到适配各个操作系统的
font-family 关键字
对于 CSS 中的
font-family
而言,它有两类取值。一类是类似这样的具体的字体族名定义:
font-family: Arial
这里定义了一个具体的字体样式,字体族名为Arial
;一类是通用字体族名,它是一种备选机制,用于在指定的字体不可用时给出较好的字体,类似这样:
font-family: sans-serif
。其中,
sans-serif
表无衬线字体族,例如, "Open Sans", "Arial" "微软雅黑" 等等。关于通用字体族名,在 CSS Fonts Module Level 3 -- Basic Font Properties 中,定义了 5 个,也就是我们熟知的几个通用字体族名:
新增通用字体族关键字
而在 CSS Fonts Module Level 4 -- Generic font families 中,新增了几个关键字:
我们看看用的最多的
system-ui
。system-ui
简单而言,
font-family: system-ui
的目的就是在不同的操作系统的 Web 页面下,自动选择本操作系统下的默认系统字体。默认使用特定操作系统的系统字体可以提高性能,因为浏览器或者 webview 不必去下载任何字体文件,而是使用已有的字体文件。
font-family: system-ui
字体设置的优势之处在于它与当前操作系统使用的字体相匹配,对于文本内容而言,它可以得到最恰当的展示。San Francisco Fonts
OK,简单了解了
system-ui
字体族。但是像-apple-system
、BlinkMacSystemFont
没有在最新的标准里出现。它们又代表什么意思呢?在此之前,先了解下
San Francisco Fonts
。San Francisco Fonts
又叫旧金山字体,是一款西文字体。随着 iOS 9 更新面世,在 WatchOS 中随 Apple Watch 一起悄然发售,并且还将在 Apple TV 上的新 tvOS 中使用。San Francisco Fonts
在 iOS 系统上用于替代升级另外一款西文字体Helvetica Neue
。Apple 做了一些重要的改变,使其成为平台上更好的, 甚至是完美的西文字体。-apple-system/BlinkMacSystemFont
话说回来。正如每个前端开发人员都知道的那样,将一个功能纳入规范是一回事,将其纳入浏览器又是另一回事。
幸运的是,
system-ui
的普及很快。 Chrome 和 Safari 都可以在各种平台上完全支持它。只有 Mozilla 和 Windows 相对落后。看看
system-ui
的兼容性,Can i Use -- system-ui(图片截取日 2019-08-13):仔细看上图的最后两行:
考虑到不同平台及向后兼容,在 macOS 和 iOS 上,我们需要使用
-apple-system
及BlinkMacSystemFont
来兼容适配system-ui
标准。Segoe UI
Segoe UI 是 Windows 从 Vista 开始的默认西文字体族,只有西文,不支持汉字,属于无衬线体。
它也表示一个系列而不是某一款单一字体。使用
font-family: Segoe UI
可以在 Windows 平台及 Windows Phone 上选取最佳的西文字体展示。Roboto
Roboto 是为 Android 操作系统设计的一个无衬线字体家族。Google 描述该字体为“现代的、但平易近人”和“有感情”的。
这个字体家族包含Thin、Light、Regular、Medium、Bold、Black六种粗细及相配的斜体。
总结一下
到此,我们可以总结一下了。以 CSS-Tricks 网站的 font-family 定义为例子:
上述 5 个字体族定义,优先级由高到底,可以看到,它们 5 个都并非某个特定字体,基本的核心思想都是选择对应平台上的默认系统字体。
涵盖了 iOS、MAC OS X、Android、Windows、Windows Phone 基本所有用户经常使用的主流操作系统。
使用系统默认字体的主要原因是性能。字体通常是网站上加载的最大/最重的资源之一。如果我们可以使用用户机器上已有的字体,我们就完全不需要再去获取字体资源,从而使加载时间明显加快。
并且系统字体的优点在于它与当前操作系统使用的相匹配,因此它的文本展示必然也是一个让人舒适展示效果。
当然,上述
font-family
的定义不一定是最佳的。譬如天猫移动端在font-family
最前面添加了"PingFang SC",miui,..
必定也有他们的业务上的考虑。但是一些 fallback 方案向后兼容的思想都是一致的,值得参考学习。更多的关于字体方面的细节知识,可以看看这几篇文章:
前端布局的兼容适配
前端工程师的一大工作内容就是页面布局。无论在PC端还是移动端,页面布局的兼容适配都是重中之重。在整个前端发展的历程中,布局的方法也在不断的推陈出新。
布局发展历程
简单来说,前端的布局发展历程经历了下面几个过程:
表格布局 --> 定位布局 --> 浮动布局 --> flexbox布局 --> gridbox布局
每一种布局在特定时期都发挥了重要的作用,而每一种新的布局方式的出现,往往都是因为现有的布局方式已经在该时期已经无法很好的满足开发者的需求,无法满足越来越潮流的页面布局的方式。
以 Flexbox 的出现为例子,在 Flexbox 被大家广为接受使用之前。我们一直在使用定位+浮动的布局方式。像下面这个布局:
容器宽度不定,内部三个元素,均分排列且占满整个空间,并且垂直居中。如果使用定位+浮动的布局方式,你无法很快想到最佳的解决方式。三个元素并排那么必然需要浮动或者绝对定位,容器宽度不定且中间元素始终居中,需要顾虑的方面就很多了。也许使用
text-align: justufy
可以 hack 实现,等等等等。然而,使用 flexbox 布局的话,只需要:
flexbox 的出现,一次性解决了流动布局,弹性布局,排列方式等多个问题。并且它是简洁的,可控的。
再来看一个例子,水平垂直居中一个元素。使用 flexbox 也许是最便捷的:
最便捷的垂直居中方式
CSS Grid Layout
OK,flexbox 已经足够优秀了,为什么 gird 网格布局的出现又是为什么?它解决了什么 flex 布局无法很好解决的问题?
看看下面这张图:
flexbox 是一维布局,他只能在一条直线上放置你的内容区块;而grid是一个二维布局。它除了可以灵活的控制水平方向之外,还能轻易的控制垂直方向的布局模式。对于上图那样的九宫格布局,它就可以轻而易举的完成。
一图以蔽之,flexbox:
gridbox:
在现阶段,移动端布局应当更多使用 flexbox 去完成(相对那些还在使用 float 布局的),而考虑到未来页面布局的推陈出新。对于 Grid 布局我们应当像前几年对待 flexbox 一样,重视起来,随着兼容性的普及,Grid 布局也会慢慢成为主流。
最后
好了,本文到此结束,希望对你有帮助 :)
更多精彩技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。