「链接和长图失效,请大家点击阅读原文查看详情」

前言

曾发表《妙用CSS变量,让你的CSS变得更心动》[1]一文,使用全部篇幅介绍「CSS变量」。变量作为CSS体系里最厉害的特性无之一,随着浏览器日益完善,变量可大范围在项目里使用,无需关注其兼容性。

虽说变量可在纯CSS里起到领头羊的作用,但变量的设计初衷是为了更便利CSS与JS间的联系。CSS使用变量有如下好处。

  • 减少样式代码的重复性

  • 增加样式代码的扩展性

  • 提高样式代码的灵活性

  • 增多一种CSS与JS的通讯方式

  • 不用深层遍历DOM改变某个样式

本文主题是结合另一个特性calc()玩出更多花样,主要是基于变量与JS通讯简化基于JS逻辑的效果。因此废话不多,想了解更多CSS变量细节可回看《妙用CSS变量,让你的CSS变得更心动》[2]

为了让大家感受变量与calc()的完美契合,笔者设计了一个「放大镜」效果展现其搭配使用的魅力。

动态计算

calc()用于动态计算单位,数值长度角度时间百分比都能作为参数。由于执行数学表达式后返回运算后的计算值,所以可减少大量人工计算甚至无需人工计算。

calc()饥不择食,所有计量单位都能作为参数参加整个动态计算。

  • 「数值」整数浮点数

  • 「长度」pxemremvwvh

  • 「角度」degturn

  • 「时间」sms

  • 「百分比」%

calc()虽然好用,但新手难免会遇到一些坑,谨记以下特点,相信就能玩转calc()了。

  • 四则运算:只能使用+-*/作为运算符号

  • 运算顺序:遵循加减乘除运算顺序,可用()提升运算等级

  • 符号连接:每个运算符号必须使用空格间隔起来

  • 混合计算:可混合不同计量单位动态计算

第三点尤为重要,若未能遵守,浏览器直接忽略该属性。

在SPA里有遇过因为有滚动条或无滚动条而导致页面路由在跳转过程里发生向左或向右的抖动吗?这让强迫症患者很难受,此时可用calc()巧妙解决该问题。

.elem {padding-right: calc(100vw - 100%);
}

不直接声明padding-right为滚动条宽度是因为每个浏览器的默认滚动条宽度都可能不一致。100vw是视窗宽度,100%内容宽度,那么100vw - 100%就是滚动条宽度,声明padding-right用于保留滚动条出现的位置,这样滚动条出不出现都不会让页面抖动了。

另外在移动端开发里,若不考虑低版本浏览器兼容性,完全可用一行CSS代码秒杀所有移动端的伸缩方案。

/* 基于UI width=750px DPR=2的网页 */
html {font-size: calc(100vw / 7.5);
}

上述font-size:calc(100vw / 7.5)其实就是根据设计图与浏览器视窗的比例动态计算<html>font-size100/750 = x/100vw

放大镜

传统的放大镜效果需依赖大部分JS逻辑,移动和显示的效果均依赖JS,通过JS计算偏移量再渲染样式。

本次使用变量简化这些JS逻辑,将计算偏移量的逻辑整合到变量里,calc()用于动态计算单位,是本次改造的核心用法。

放大镜

基于上述需求,实时获取鼠标的左偏移量上偏移量即可,而这两个偏移量是相对父节点的。通过左偏移量上偏移量结合calc()即可计算放大镜显示内容相对父节点的显示位置。

event提供以下八个偏移量,若不了解其概念很易发生混淆。

  • 「screenX/screenY」:相对屏幕区域左上角定位,若发生滚动行为,则相对该区域定位

  • 「pageX/pageY」:相对网页区域左上角定位

  • 「clientX/clientY」:相对浏览器可视区域左上角定位

  • 「offsetX/offsetY」:相对父节点区域左上角定位,若无父节点则相对<html><body>定位

罗列出这些偏移量概念,发现offsetX/offsetY是最符合需求的,所以使用其作为放大镜显示内容相对父节点的显示位置。

<div class="magnifier" id="magnifier"></div>
document.getElementById("magnifier").addEventListener("mousemove", e => {e.target.style.setProperty("--x", `${e.offsetX}px`);e.target.style.setProperty("--y", `${e.offsetY}px`);
});

接下来使用sass构建放大镜效果。放大镜显示内容其实就是将原图像放大N倍,通过上述偏移量按照比例截取一定区域显示内容。

先定义相关Sass变量。设定放大倍率为2倍,那么被放大图像的宽高也是原来宽高的2倍。声明两个变量,分为为--x--y

背景选用了笔者最爱的广州珠江新城CBD全家福,不喜欢可自行替换背景哈!

$ratio: 2;
$box-w: 600px;
$box-h: 400px;
$box-bg: "https://static.yangzw.vip/codepen/gz.jpg";
$outbox-w: $box-w * $ratio;
$outbox-h: $box-h * $ratio;
.magnifier {--x: 0;--y: 0;overflow: hidden;position: relative;width: $box-w;height: $box-h;background: url($box-bg) no-repeat center/100% 100%;cursor: pointer;
}

在该场景下很明显无需插入子节点作为放大镜的容器,可使用::before代替。

放大镜在使用时宽高为100px,不使用时宽高为0px。通过绝对定位布局放大镜随鼠标移动的位置,即声明lefttop,再通过声明transform:translate(-50%,-50%)将放大镜补位,使放大镜中心与鼠标光标位置一致。由于声明lefttop定位放大镜的位置,那么还需声明will-change改善lefttop因改变而引发的性能问题。

.magnifier {&::before {--size: 0;position: absolute;left: var(--x);top: var(--y);border-radius: 100%;width: var(--size);height: var(--size);box-shadow: 1px 1px 3px rgba(#000, .5);content: "";will-change: left, top;transform: translate(-50%, -50%);}&:hover::before {--size: 100px;}
}

接下来使用background实现放大镜显示内容。依据放大倍率为2倍,那么声明size:$outbox-w $outbox-h,通过声明position-xposition-y移动背景即可,最终连写成background:#333 url($box-bg) no-repeat $scale-x $scale-y/$outbox-w $outbox-h,而$scale-x$scale-y对应position-xposition-y,用于随着鼠标移动而改变背景位置。

水平方向偏移量 = offsetX * 倍率 - 放大镜宽度 / 倍率
垂直方向偏移量 = offsetY * 倍率 - 放大镜高度 / 倍率

基于background-position正负值问题,上述两条公式还需乘以-1,则变成以下公式。

水平方向偏移量 = 放大镜宽度 / 倍率 - offsetX * 倍率
垂直方向偏移量 = 放大镜高度 / 倍率 - offsetY * 倍率

此时将两条公式代入到$scale-x$scale-y两个Sass变量里,若在calc()里使用Sass变量,需使用#{}的方式包含Sass变量,否则会按照字符串的方式解析。

$scale-x: calc(var(--size) / #{$ratio} - #{$ratio} * var(--x));
$scale-y: calc(var(--size) / #{$ratio} - #{$ratio} * var(--y));

最终的scss文件如下。

$ratio: 2;
$box-w: 600px;
$box-h: 400px;
$box-bg: "https://static.yangzw.vip/codepen/gz.jpg";
$outbox-w: $box-w * $ratio;
$outbox-h: $box-h * $ratio;
.magnifier {--x: 0;--y: 0;overflow: hidden;position: relative;width: $box-w;height: $box-h;background: url($box-bg) no-repeat center/100% 100%;cursor: pointer;&::before {--size: 0;$scale-x: calc(var(--size) / #{$ratio} - #{$ratio} * var(--x));$scale-y: calc(var(--size) / #{$ratio} - #{$ratio} * var(--y));position: absolute;left: var(--x);top: var(--y);border-radius: 100%;width: var(--size);height: var(--size);background: #333 url($box-bg) no-repeat $scale-x $scale-y/$outbox-w $outbox-h;box-shadow: 1px 1px 3px rgba(#000, .5);content: "";will-change: left, top;transform: translate(-50%, -50%);}&:hover::before {--size: 100px;}
}

  • 在线演示:Here[3]

  • 在线源码:Here[4]

总结

小小的变量与calc()也能如此玩耍,相信还会有更多CSS技巧可发掘。

很多同学可能觉得CSS很简单,但真正玩起来也能与JS有得一比。笔者从事前端领域多年,一直致力于CSS技术的研究与应用,当然真的不是为了玩,而是在玩的过程里将实践到的知识充分应用于工作上。

JS重要但CSS同样重要,希望喜欢CSS的同学多多关注笔者,相信你一定会有更多CSS方面的收获。在你不太愿意学习CSS时,请浏览以下网站,相信你会有不同的体验。

  • 个人官网[5]:暂时支持PC端浏览,拒绝支持IExplorer

  • 特效专辑[6]:暂时支持PC端浏览,拒绝支持IExplorer,查看源码请戳这里[7]

笔者更多的CSS开发经验已撰写成掘金小册《玩转CSS的艺术之美》[8],作为一本小众的小册同时也是掘金社区里唯一一本关于CSS的小册,相信关注CSS的你一定会喜欢。笔者已向小册姐姐申请了100份小册「6折」优惠码「OGecoefC」,喜欢CSS的同学可了解下喔。

参考资料

[1]

《妙用CSS变量,让你的CSS变得更心动》: https://juejin.cn/post/6844904084936327182

[2]

《妙用CSS变量,让你的CSS变得更心动》: https://juejin.cn/post/6844904084936327182

[3]

Here: https://codepen.io/JowayYoung/pen/oNbGzPy

[4]

Here: https://github.com/JowayYoung/idea-css/blob/master/icss/src/components/component/放大镜.vue

[5]

个人官网: https://yangzw.vip

[6]

特效专辑: https://yangzw.vip

[7]

这里: https://github.com/JowayYoung/idea-css

[8]

《玩转CSS的艺术之美》: https://juejin.cn/book/6850413616484040711

1. JavaScript 重温系列(22篇全)

2. ECMAScript 重温系列(10篇全)

3. JavaScript设计模式 重温系列(9篇全)

4. 正则 / 框架 / 算法等 重温系列(16篇全)

5. Webpack4 入门(上)|| Webpack4 入门(下)

6. MobX 入门(上) ||  MobX 入门(下)

7. 120+篇原创系列汇总

回复“加群”与大佬们一起交流学习~

点击“阅读原文”查看 120+ 篇原创文章

【CSS】1104- 惊!妙用CSS变量和calc()实现放大镜效果相关推荐

  1. 妙用CSS变量,让你的CSS变得更心动

    作者:JowayYoung 仓库:Github.CodePen 博客:掘金.思否.知乎.简书.头条.CSDN 公众号:IQ前端 联系我:关注公众号后有我的微信哟 特别声明:原创不易,未经授权不得对此文 ...

  2. html的选择器child,css child选择器妙用

    css child选择器妙用:倒数第n,奇数列,偶数列,倍数列,第n个到最后,第一个到n 1.first-child first-child表示选择列表中的第一个标签. 2.last-child la ...

  3. 【CSS】小妙招,各种问题总结方法处理

    1.实现div文字溢出自动省略号截取 overflow:hidden; /*超过部分不显示*/ text-overflow:ellipsis; /*超过部分用点点表示*/ white-space:no ...

  4. css表格排序,纯CSS实现表格排序-利用CSS 变量和Flexbox

    1.引子 今天闲逛知名前端资讯站Front-End Front,发现一个比较有意思的效果,给大家分享下,希望可以对大家有所启发. 纯CSS实现表格排序 心急的同学,先看效果,我放在codepen上. ...

  5. 【前端实例代码】霓虹灯按钮动画效果悬停2| html CSS特效 惊艳| 前端开发 网页制作 基础入门教程

    b站视频演示效果: [web前端特效源码]霓虹灯按钮动画效果悬停2| html CSS特效 惊艳| 前端开发 网页制作 基础入门教程 效果图: 完整代码: <!DOCTYPE html> ...

  6. 【前端实例代码】霓虹灯按钮动画效果悬停| html CSS特效 惊艳| 前端开发 网页制作 基础入门教程

    b站视频演示效果: [web前端特效源码]霓虹灯按钮动画效果悬停| html CSS特效 惊艳| 前端开发 网页制作 基础入门教程 效果图: 完整代码: <!DOCTYPE html> & ...

  7. css 图片自适应_104道 CSS 面试题,助你查漏补缺(下)

    (给前端大全加星标,提升前端技能) 作者:CavsZhouyou https://github.com/CavsZhouyou/Front-End-Interview-Notebook/blob/ma ...

  8. css img重复_20 个 CSS 快速提升技巧

    code小生 一个专注大前端领域的技术平台公众号回复Android加入安卓技术群转载自:http://www.javanx.cn/20190321/css-skill/本文涵盖了20个css技巧,可以 ...

  9. html css 水平时间轴,纯css+js水平时间轴

    自定义,并自动加载时间节点 当前时间节点居中,突出显示 时间动态无痕添加 效果图: 初始状态 时间左走到一定2016.1月后 html: + - 对应 JS 设置处理: var left = docu ...

最新文章

  1. linux路由介绍,Linux的路由表详细介绍
  2. iphone分辨率_iPhone 的屏幕为什么比安卓更丝滑?
  3. Java多线程之线程间协作 notify与wait的使用
  4. 如何正确的在一个循环中删除ArrayList中的元素。
  5. PowerDesigner--创建业务流程模型
  6. 【QT】QT从零入门教程(九):QT常用控件 [QSlider、QSpinBox、QComboBox、QRadioButton]
  7. MySQL Workbench给其他IP用户分配权限
  8. pscad仿真数据提取方法
  9. 柱坐标系下的流体力学控制方程组的微分形式的推导
  10. centos7安装tree命令
  11. 日期插件datepicker的使用
  12. [渝粤题库]西北工业大学离散数学
  13. php表单时间控件,phpcmsV9中表单向导在js调用里日期控件在IE下报Calendar未定义的解决办法...
  14. word文档中表格顶头怎么调整_教你用Word制作专用信纸,轻松几步就完成
  15. python和pyqt5入门之简易汇率转换器
  16. Windows 10 安装使用TensorFlow-GPU
  17. CPU(AMD)2020.10购买推荐
  18. idea有时不进断点的原因
  19. 修改nginx web服务器默认目录结构,Nginx更改Web根目录导致403 Forbidden
  20. forrtl: severe (174): SIGSEGV, segmentation fault occurred

热门文章

  1. 后浪推前浪,一浪比一浪高;来自老鸟们的分享
  2. mc神奇宝贝服务器网站,我的世界1.12.2 master 神奇宝贝服务器
  3. word表格公式 计算机应用基础(5)
  4. arcgis中字段的说明
  5. C语言基础:强制类型转换
  6. 【c4d常用知识点】倒角工具
  7. 2022年智能轨道,交通与运输工程国际会议(ICSTTE 2022)
  8. 产品的思路——来自腾讯张小龙的分享
  9. MS51FB9AE驱动WS2812
  10. Ps裁剪工具及其附属工具的用法