10_h5是如何做移动端适配的?折行的时候如何实现不断行
一、百分比适配
1、要点
- 元素的宽度使用了百分比来定宽,根据屏幕的宽度进行自适应
- 适合页面内容结构均匀分配,固定高度,结构不是很复杂,注意要设置viewport视口内容宽度等于设备的宽度
- 使用百分比定宽的元素,百分比参考的是该元素最近的,定了宽度的父元素
2、示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
<title>固定高度,宽度自适应,100%比做适配</title>
<style type="text/css">
*{
padding:0;
margin:0;
}
body{
font-size:16px;
overflow:hidden;
-webkit-box-sizing:border-box;
box-sizing:border-box;
}
/*left start*/
.left{
width:40px; /*两边固定宽度,中间自适应*/
height:40px; /*高度可以不加,由内容填充*/
position:absolute;
left:0;
top:0;
background:red;
text-align:center;
line-height:40px;
}
/*left end*/
/*center start*/
.center{
width:100%; /*宽度不固定*/
background:orange;
height:40px;
margin-left:40px;
}
.center input{
width:100%;
height:40px;
outline:none;
}
/*center end*/
/*right start*/
.right{
width:40px; /*两边固定宽度,中间自适应*/
height:40px; /*高度可以不可,由内容填充*/
text-align:center;
line-height:40px;
position:absolute;
right:0;
top:0;
background:green;
}
/*right end*/
/*banner adv start*/
.banner{
width:100%;
height:200px;
background:pink;
text-align:center;
line-height:200px;
}
/*banner adv end*/
/*list start*/
.list{
overflow:hidden;
}
.list div{
width:20%;
height:90px;
float:left;
text-align:center;
line-height:90px;
}
.list div:nth-of-type(1){
background:orange;
}
.list div:nth-of-type(2){
background:#80B3FF;
}
.list div:nth-of-type(3){
background:#1BA260;
}
.list div:nth-of-type(4){
background:#F2A196;
}
.list div:nth-of-type(5){
background:#FFCE42;
}
.listTwo{
margin:15px 0 0 0;
}
/*list end*/
/*con start*/
.con{
width:100%;
height:200px;
overflow:hidden; /*子元素使用来浮动,父元素记得清除浮动*/
text-align:center;
line-height:200px;
}
.left-80{
width:80%;
height:100%; /*想要一个元素在页面中显示必须得给元素高度,继承父元素*/
float:left;
background:#B0E24A;
}
.right-20{
width:20%;
height:100%; /*高度100%,继承父元素的高度*/
float:right;
background:#6C6863;
}
/*con end*/
</style>
</head>
<body>
<!-- header start -->
<header>
<div class="left">左边</div>
<div class="center">
<form>
<input type="search" name="">
</form>
</div>
<div class="right">右边</div>
</header>
<!-- header end -->
<!-- banner adv start -->
<div class="banner">adv</div>
<!-- banner adv end -->
<!-- 列表list start -->
<div class="list">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
<div class="list listTwo">
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>10</div>
</div>
<!-- 列表list end -->
<!-- con内容开始-->
<div class="con">
<div class="left-80">左边80%</div>
<div class="right-20">右边20%</div>
</div>
<!-- con内容结束-->
</body>
</html>
二、@media 媒体查询适配
1、CSS 语法
(1)@media 媒体类型 and (媒体特性){ 你的样式 }
@media mediatype and|not|only (media feature) {
CSS-Code;
}
(2)针对不同的媒体使用不同 stylesheets
<link rel="stylesheet" media="mediatype and|not|only (media feature)" href="mystylesheet.css">
2、媒体查询功能
(1)最大宽度max-width
“max-width”是媒体特性中最常用的一个特性,其意思是指媒体类型小于或等于指定的宽度时,样式生效。如:
@media screen and (max-width:480px){
.ads {
display:none;
}
}
上面表示的是:当屏幕小于或等于480px时,页面中的广告区块(.ads)都将被隐藏。
(2)最小宽度min-width
“min-width”与“max-width”相反,指的是媒体类型大于或等于指定宽度时,样式生效。
@media screen and (min-width:900px){
.wrapper {width: 980px;}
}
上面表示的是:当屏幕大于或等于900px时,容器“.wrapper”的宽度为980px。
(3)多个媒体特性使用
Media Queries可以使用关键词"and"将多个媒体特性结合在一起。也就是说,一个Media Query中可以包含0到多个表达式,表达式又可以包含0到多个关键字,以及一种媒体类型。
当屏幕在600px~900px之间时,body的背景色渲染为“#f5f5f5”,如下所示。
@media screen and (min-width:600px) and (max-width:900px){
body {background-color:#f5f5f5;}
}
(4)设备屏幕的输出宽度Device Width
在智能设备上,例如iPhone、iPad等,还可以根据屏幕设备的尺寸来设置相应的样式(或者调用相应的样式文件)。同样的,对于屏幕设备同样可以使用“min/max”对应参数,如“min-device-width”或者“max-device-width”。
<link rel="stylesheet" media="screen and (max-device-width:480px)" href="iphone.css" />
上面的代码指的是“iphone.css”样式适用于最大设备宽度为480px,比如说iPhone上的显示,这里的“max-device-width”所指的是设备的实际分辨率,也就是指可视面积分辨率。
(5)not关键词
使用关键词“not”是用来排除某种制定的媒体类型,也就是用来排除符合表达式的设备。换句话说,not关键词表示对后面的表达式执行取反操作,如:
@media not print and (max-width: 1200px){样式代码}
上面代码表示的是:样式代码将被使用在除打印设备和设备宽度小于1200px下所有设备中。
(6)only关键词
only用来指定某种特定的媒体类型,可以用来排除不支持媒体查询的浏览器。其实only很多时候是用来对那些不支持Media Query但却支持Media Type的设备隐藏样式表的。
其主要有:支持媒体特性的设备,正常调用样式,此时就当only不存在;表示不支持媒体特性但又支持媒体类型的设备,这样就会不读样式,因为其先会读取only而不是screen;另外不支持Media Queries的浏览器,不论是否支持only,样式都不会被采用。如
<link rel="stylesheet" media="only screen and (max-device-width:240px)" href="android240.css" />
在Media Query中如果没有明确指定Media Type,那么其默认为all,如:
<link rel="stylesheet" media="(min-width:701px) and (max-width:900px)" href="mediu.css" />
另外在样式中,还可以使用多条语句来将同一个样式应用于不同的媒体类型和媒体特性中,指定方式如下所示。
<link rel="stylesheet" type="text/css" href="style.css" media="handheld and (max-width:480px), screen and (min-width:960px)" />
3、移动端适配用法
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
/*iphone4*/
@media only screen and (max-width: 320px) and (max-width: 480px) {
html, body {
font-size: 12px;
}
.title {
background-color: red;
}
}
/*iphone5*/
@media only screen and (max-width: 320px) and (min-height: 568px) {
html,body {
font-size: 14px;
}
.title {
background-color: blue;
}
}
/*ihpne6,7,8*/
@media only screen and (min-width: 375px) and (max-width: 413px) {
html,body {
font-size: 16px;
}
.title {
background-color: green;
}
}
/*ihpne6,7,8Plus*/
@media only screen and (min-width: 414px) and (max-width: 640px) {
html,body {
font-size: 18px;
}
.title {
background-color: pink;
}
}
三、Flex布局适配
- 适合页面内容结构均匀分配,固定高度,需要设置viewport视口内容宽度等于设备宽度
- 老版本的display:box与新版本的display:flex都可以实现页面的自适应
1、新老版本语法对比
2、示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
<title>Flex布局适配</title>
<style type="text/css">
*{
padding:0;
margin:0;
}
body{
font-family:"微软雅黑";
font-size:16px;
}
.parent{
display:-webkit-flex; /*声明弹性盒模型*/
display:flex;
}
.left,.right{
width:40px;
height:40px;
text-align:center;
line-height:40px;
}
.left{
background:#abcdef;
}
.right{
background:#DD4F43;
}
.center{
-webkit-flex:1; /*一定要注意加上浏览器前缀,否则就会失效*/
flex:1;
}
.center input{
width:100%;
height:40px;
outline:none;
}
.banner-adv{
width:100%;
height:200px;
display:-webkit-box;
display:box;
background:#0D6CB0;
}
.list{
width:100%;
height:90px;
display:-webkit-flex;
display:flex;
}
.list div{
-webkit-flex:1;
flex:1;
text-align:center;
line-height:90px;
}
.list div:nth-of-type(1){
background:#DE5246;
}
.list div:nth-of-type(2){
background:#19A25F;
}
.list div:nth-of-type(3){
background:#FF8080;
}
.list div:nth-of-type(4){
background:#F4CD0B;
}
.list div:nth-of-type(5){
background:#9EDA45;
}
.list-Two{
margin:15px 0 0 0;
}
.list-Two div:nth-of-type(1){
background:#B847FF;
}
.list-Two div:nth-of-type(2){
background:#79B900;
}
.list-Two div:nth-of-type(3){
background:#FF2424;
}
.list-Two div:nth-of-type(4){
background:#D2E4F0;
}
.list-Two div:nth-of-type(5){
background:#4CDF2B;
}
.con{
height:200px;
display:-webkit-flex; /*声明弹性盒模型*/
display:flex;
}
.con div:nth-of-type(1){
-webkit-flex:8; /*根据父元素分成8等分,占80%*/
flex:8;
background:#80B3FF;
}
.con div:nth-of-type(2){
-webkit-flex:2; /*根据父元素分成2等分,占20%*/
flex:2;
background:#CD8B37;
}
</style>
</head>
<body>
<header class="parent">
<div class="left">左边</div>
<div class="center">
<form>
<input type="search" name="">
</form>
</div>
<div class="right">右边</div>
</header>
<div class="banner-adv"></div>
<section class="list">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</section>
<section class="list list-Two">
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>9</div>
</section>
<div class="con">
<div></div>
<div></div>
</div>
</body>
</html>
四、动态 rem 方案
1、rem/em/vw/vh的比较
(1)em
em作为font-size的单位时,其代表父元素的字体大小,em作为其他属性单位时,代表自身字体大小——MDN
比如父元素font-size:12px;
自身元素如果写成:font-sise:2em;则自身元素用px表示就是24px(相对父元素字体大小);
但是自身元素设置:width:2em,那么自身元素用px表示就是48px(相对自身字体大小);
(2)rem
rem作用于非根元素时,相对于根元素字体大小;rem作用于根元素字体大小时,相对于其出初始字体大小——MDN
比如根元素(html)设置font-size=12px; 非根元素设置width:2rem;则换成px表示就是24px;
如果根元素设置成font-size=1rem;则根元素换成px就是相对于初始字体大小,一般是12px;
(3)vm/vh
vw : 视口宽度的 1/100;vh :视口高度的 1/100 —— MDN
在pc端,视口宽高就是浏览器得宽高;
在移动端,这个还不太一样,不过一般设置:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
代码以显示网页的屏幕宽度定义了视窗宽度。网页的比例和最大比例被设置为100%。
2、剖析rem布局原理
其实好好理解上面的概念,rem的原理也就很简单了。
假设我们将屏幕平局分为10份,每一份宽度用一个a表示,即a=屏幕宽度/10,那么:
div {width: 5a} /* 屏幕宽度的50% */
但是css中没有a这个单位,这时我们可以借助rem代替上面的a。如:
html {font-size: 12px}
div {width: 2rem} /* 24px*/
html {font-size: 16px}
div {width: 2rem} /* 32px*/
新的问题来?怎么让html元素字体大小恒等于屏幕的1/10呢?如ipone6宽是375px,font-size:37.5px;
html {fons-size: width / 10}
div {width: 5rem} /* 5rem = 5a = 屏幕宽度的50% */
我们用js很容易动态的设置html的font-size恒等屏幕的1/10;我们可以在页面dom ready、resize和屏幕旋转中设置:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
如何把设计稿的像素单位换成以rem为单位?可以用一个比例来计算:如设计稿宽度为750px,某个元素量得75px,那么:
75px/750px = 计算所得rem/10rem,所以计算所得rem=75px;所以我们在样式中写width:1rem;实际宽度是75px;同理,如果设计稿总宽度是640px,则1rem=64px。
预处理函数可以简化:
$ue-width: 750; /* 设计稿图的宽度 */
@function px2rem($px) {
@return #{$px/$ue-width*10}rem;
}
div {
width: px2rem(100);/*编译后: p{width:1.5625rem}*/
}
3、rem布局方案
rem是一种弹性布局,它强调等比缩放,100%还原。它和响应式布局不一样,响应式布局强调不同屏幕要有不同的显示,比如媒体查询。
最佳方案:rem+flexbox+js的方案
实现步骤:
- 引入相关flexible.js文件
- 根据设计图计算元素rem值
- 切换不同移动端视窗查看效果
示例1:网易考拉
(function(win) {
var remCalc = {};
var docEl = win.document.documentElement,
tid;
function refreshRem() {
var width = docEl.getBoundingClientRect().width;
if (width > 640) {
width = 640
}
var rem = width / 10;
docEl.style.fontSize = rem + "px";
remCalc.rem = rem;
var actualSize = parseFloat(window.getComputedStyle(document.documentElement)["font-size"]);
if (actualSize !== rem && actualSize > 0 && Math.abs(actualSize - rem) > 1) {
var remScaled = rem * rem / actualSize;
docEl.style.fontSize = remScaled + "px"
}
}
function dbcRefresh() {
clearTimeout(tid);
tid = setTimeout(refreshRem, 100)
}
win.addEventListener("resize",
function() {
dbcRefresh()
},
false);
win.addEventListener("pageshow",
function(e) {
if (e.persisted) {
dbcRefresh()
}
},
false);
refreshRem();
remCalc.refreshRem = refreshRem;
remCalc.rem2px = function(d) {
var val = parseFloat(d) * this.rem;
if (typeof d === "string" && d.match(/rem$/)) {
val += "px"
}
return val
};
remCalc.px2rem = function(d) {
var val = parseFloat(d) / this.rem;
if (typeof d === "string" && d.match(/px$/)) {
val += "rem"
}
return val
};
win.remCalc = remCalc
})(window); (function(win, doc) {
var type = navigator.userAgent.match(/(iPhone|iPod|iPad)/i) ? "ios": "aos";
win.deviceType = type
})(window, document);
示例2:
;(function (doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if (clientWidth >= 750) {
docEl.style.fontSize = '100px';
} else {
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
五、 css实现单行、多行文本超出显示省略号
1、单行文本省略
<p class="ellipsis-line">在使用的时候,有时候发现不会出现省略标记效果,经过测试发现,使用ellipsis的时候,必须配合overflow:hidden; white-space:nowrap; width:具体值;这三个样式共同使用才会有效果。</p>
.ellipsis-line {
border: 1px solid #f70505;
padding: 8px;
width: 400px;
overflow: hidden;
text-overflow: ellipsis; /*文本溢出显示省略号*/
white-space: nowrap; /*文本不会换行*/
}
语法:text-overflow:clip/ellipsis;
- 默认值:clip
- 适用于:所有元素
- clip: 当对象内文本溢出时不显示省略标记(...),而是将溢出的部分裁切掉。
- ellipsis: 当对象内文本溢出时显示省略标记(...)。
注:在使用的时候,有时候发现不会出现省略标记效果,经过测试发现,使用ellipsis的时候,必须配合overflow:hidden; white-space:nowrap; width:具体值;这三个样式共同使用才会有效果。
2、多行文本省略
(1)直接用css属性-webkit-line-clamp:n;设置
在WebKit浏览器或移动端(绝大部分是WebKit内核的浏览器)的页面实现比较简单,可以直接使用WebKit的CSS扩展属性(WebKit是私有属性)-webkit-line-clamp ;注意:这是一个 不规范的属性(unsupported WebKit property),它没有出现在 CSS 规范草案中。
-webkit-line-clamp用来限制在一个块元素显示的文本的行数。 为了实现该效果,它需要组合其他的WebKit属性。常见结合属性:
- display: -webkit-box; 必须结合的属性 ,将对象作为弹性伸缩盒子模型显示 。
- -webkit-box-orient 必须结合的属性 ,设置或检索伸缩盒对象的子元素的排列方式 。
- text-overflow: ellipsis;,可以用来多行文本的情况下,用省略号“…”隐藏超出范围的文本。
这个属性只合适WebKit浏览器或移动端(绝大部分是WebKit内核的)浏览器
<p class="multi-line">在WebKit浏览器或移动端(绝大部分是WebKit内核的浏览器)的页面实现比较简单,可以直接使用WebKit的CSS扩展属性(WebKit是私有属性)-webkit-line-clamp ;注意:这是一个 不规范的属性(unsupported WebKit property),它没有出现在 CSS 规范草案中。</p>
.multi-line {
border: 1px solid #f70505;
width: 400px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
效果优点:
- 响应式截断,根据不同宽度做出调整
- 文本超出范围才显示省略号,否则不显示省略号
- 浏览器原生实现,所以省略号位置显示刚好
但是缺点也是很直接,因为 -webkit-line-clamp 是一个不规范的属性,它没有出现在 CSS 规范草案中。也就是说只有 webkit 内核的浏览器才支持这个属性,像 Firefox, IE 浏览器统统都不支持这个属性,浏览器兼容性不好。
使用场景:多用于移动端页面,因为移动设备浏览器更多是基于 webkit 内核,除了兼容性不好,实现截断的效果不错。
(2)利用定位和伪类元素
p {
position: relative;
width:400px;
line-height: 20px;
max-height: 60px;
overflow: hidden;
}
p::after {
content: "...";
position: absolute;
bottom: 0;
right: 0;
padding-left: 40px;
background: -webkit-linear-gradient(left, transparent, #fff 55%);
background: -o-linear-gradient(right, transparent, #fff 55%);
background: -moz-linear-gradient(right, transparent, #fff 55%);
background: linear-gradient(to right, transparent, #fff 55%);
}
适合场景:文字内容较多,确定文字内容一定会超过容器的,那么选择这种方式不错。但文字未超出行的情况下也会出现省略号,可结合js优化该方法。
注:
- 将height设置为line-height的整数倍,防止超出的文字露出。
- 给p::after添加渐变背景可避免文字只显示一半。
- 由于ie6-7不显示content内容,所以要添加标签兼容ie6-7(如:<span>…<span/>);兼容ie8需要将::after替换成:after。
(3)结合js优化代码
css:
p {
position: relative;
width: 400px;
line-height: 20px;
overflow: hidden;
}
.p-after:after {
content: "...";
position: absolute;
bottom: 0;
right: 0;
padding-left: 40px;
background: -webkit-linear-gradient(left, transparent, #fff 55%);
background: -moz-linear-gradient(left, transparent, #fff 55%);
background: -o-linear-gradient(left, transparent, #fff 55%);
background: linear-gradient(to right, transparent, #fff 55%);
}
js:
<script src="https://cdn.bootcss.com/jquery/3.5.0/jquery.min.js"></script>
<script>
$(function(){
//获取文本的行高,并获取文本的高度,假设我们规定的行数是五行,那么对超过行数的部分进行限制高度,并加上省略号
$('p').each(function(i, obj){
var lineHeight = parseInt($(this).css("line-height"));
var height = parseInt($(this).height());
if((height / lineHeight) >3 ){
$(this).addClass("p-after")
$(this).css("height","60px");
}else{
$(this).removeClass("p-after");
}
});
})
</script>