一、rem和第三方插件
rem
与em不同,rem会根据html的根节点字体大小进行变换,例如1rem就是一个字体大小那么大,比如根大小font size
为12px,那么1rem即12px,大家可以在网上寻找单位换算工具进行换算(从设计稿的px到rem)或是下载相关插件例如gulp-px3rem
,这样在不同分辨率,不同缩放比的电脑下都能够轻松应对了。
使用:
第三方插件,例如做移动端适配的flexible.js,lib-flexible库
,其核心原理就是rem,我们需要做的就是根据不同屏幕计算出不同的fontsize,而页面中元素都是用rem做单位,据此实现了自适应
源码
;(function(win, lib) {var doc = win.document;var docEl = doc.documentElement;var metaEl = doc.querySelector('meta[name="viewport"]');var flexibleEl = doc.querySelector('meta[name="flexible"]');var dpr = 0;var scale = 0;var tid;var flexible = lib.flexible || (lib.flexible = {});if (metaEl) {console.warn('将根据已有的meta标签来设置缩放比例');var match = metaEl.getAttribute('content').match(/initial-scale=([d.]+)/);if (match) {scale = parseFloat(match[1]);dpr = parseInt(1 / scale);}} else if (flexibleEl) {var content = flexibleEl.getAttribute('content');if (content) {var initialDpr = content.match(/initial-dpr=([d.]+)/);var maximumDpr = content.match(/maximum-dpr=([d.]+)/);if (initialDpr) {dpr = parseFloat(initialDpr[1]);scale = parseFloat((1 / dpr).toFixed(2)); }if (maximumDpr) {dpr = parseFloat(maximumDpr[1]);scale = parseFloat((1 / dpr).toFixed(2)); }}}if (!dpr && !scale) {var isAndroid = win.navigator.appVersion.match(/android/gi);var isIPhone = win.navigator.appVersion.match(/iphone/gi);var devicePixelRatio = win.devicePixelRatio;if (isIPhone) {// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3;} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){dpr = 2;} else {dpr = 1;}} else {// 其他设备下,仍旧使用1倍的方案dpr = 1;}scale = 1 / dpr;}docEl.setAttribute('data-dpr', dpr);if (!metaEl) {metaEl = doc.createElement('meta');metaEl.setAttribute('name', 'viewport');metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');if (docEl.firstElementChild) {docEl.firstElementChild.appendChild(metaEl);} else {var wrap = doc.createElement('div');wrap.appendChild(metaEl);doc.write(wrap.innerHTML);}}function refreshRem(){var width = docEl.getBoundingClientRect().width;if (width / dpr > 540) {width = 540 * dpr;}var rem = width / 10;docEl.style.fontSize = rem + 'px';flexible.rem = win.rem = rem;}win.addEventListener('resize', function() {clearTimeout(tid);tid = setTimeout(refreshRem, 300);}, false);win.addEventListener('pageshow', function(e) {if (e.persisted) {clearTimeout(tid);tid = setTimeout(refreshRem, 300);}}, false);if (doc.readyState === 'complete') {doc.body.style.fontSize = 12 * dpr + 'px';} else {doc.addEventListener('DOMContentLoaded', function(e) {doc.body.style.fontSize = 12 * dpr + 'px';}, false);}refreshRem();flexible.dpr = win.dpr = dpr;flexible.refreshRem = refreshRem;flexible.rem2px = function(d) {var val = parseFloat(d) * this.rem;if (typeof d === 'string' && d.match(/rem$/)) {val += 'px';}return val;}flexible.px2rem = function(d) {var val = parseFloat(d) / this.rem;if (typeof d === 'string' && d.match(/px$/)) {val += 'rem';}return val;}})(window, window['lib'] || (window['lib'] = {}));
在实际开发中应用场景不同效果不同,因此不能写死px。
在PC端适配我们可以自动转换rem适配方案(postcss-pxtorem、amfe-flexible),这里以vue3+vite为例子。事实上amfe-flexible是lib-flexible的升级版。
注意: 行内样式px不会转化为rem
npm install postcss postcss-pxtorem --save-dev // 我试过了反正我报错了,版本太高 大家可以指定5.1.1
npm install postcss-pxtorem@^5.1.1
npm i amfe-flexible --save
记得在main.js中引入amfe-flexible
import "amfe-flexible"
相关配置
二、媒体查询
通过查询不同的宽度来执行不同的css代码,最终以达到界面的配置。
在 CSS 中使用 @media
查询来检测屏幕宽度。当屏幕宽度小于 1024px 时,增加 margin-top
以向下移动表格。
.responsive-table {transition: margin-top 0.3s; /* 添加过渡效果 */
}@media (max-width: 1024px) {.responsive-table {margin-top: 200px; /* 向下移动的距离 */}
}
三、弹性布局
创建一个响应式的卡片布局,当屏幕宽度减小时,卡片会自动换行。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Flexbox Example</title><style>body {display: flex;justify-content: center;align-items: center;flex-wrap: wrap;margin: 0;height: 100vh;background-color: #f0f0f0;}.card-container {display: flex;flex-wrap: wrap;justify-content: center;width: 90%;}.card {background-color: white;border: 1px solid #ccc;border-radius: 5px;padding: 20px;margin: 10px;flex: 1 1 300px; /* 基于300px,允许增长和收缩 */box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);transition: transform 0.3s;}.card:hover {transform: translateY(-5px);}</style>
</head>
<body><div class="card-container"><div class="card">Card 1</div><div class="card">Card 2</div><div class="card">Card 3</div><div class="card">Card 4</div><div class="card">Card 5</div></div>
</body>
</html>