Web开发:四角线框效果(HTML、CSS、JavaScript)

目录

一、实现效果

二、完整代码

三、页面准备

1、页面结构

2、初始样式

3、现有效果

三、线框实现

1、需求分析

2、线框结构

3、线框大小

4、线框位置

5、线框样式

6、移动线框

7、添加过渡效果

8、使用CSS变量


一、实现效果

如下图所示,当鼠标移动到某个图片时,就给这个图片添加四角线框;

四角线框效果

二、完整代码

test.html

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>四角线框效果</title><style>:root {/* 定义变量 *//* 图片的宽度 */--img-width: 240px;/* 图片的高度 */--img-height: 160px;/* 图片的间距 */--img-gap: 40px;/* 线框的样式 */--line-box-border: 2px solid #666;}* {/* 清除默认边距 */margin: 0;padding: 0;}body {/* 设为flex布局 */display: flex;/* 设置子元素水平居中 */justify-content: center;/* 设置子元素垂直居中 */align-items: center;width: 100vw;height: 100vh;background-color: #eeffff;caret-color: transparent;}.grid-container {/* 设为相对定位 */position: relative;/* 设为Grid布局 */display: grid;/* 划分3列,列宽为240px */grid-template-columns: repeat(3, var(--img-width));/* 划分3行,行高为160px */grid-template-rows: repeat(3, var(--img-height));/* 元素间距为40px */gap: var(--img-gap);}.one-img {/* 图片大小为其父元素大小 240px * 160px */width: 100%;height: 100%;box-shadow: 0 0 6px 1px #666;border-radius: 6px;}.line-box {/* 设置线框为绝对定位 */position: absolute;/* 距离父元素的上、左距离为0; */top: 0;left: 0;/* 线框盒子的宽度为图片宽度(240px) +  图片的间距(40px) */width: calc(var(--img-width) + var(--img-gap));/* 线框盒子的高度为图片高度(160px) +  图片的间距(40px) */height: calc(var(--img-height) + var(--img-gap));/* 设置线框的margin值 */margin-top: calc(-1 * var(--img-gap) / 2);margin-left: calc(-1 * var(--img-gap) / 2);/* 添加过渡效果 */transition: top 0.4s, left 0.4s;}.line-item {/* 四角边框采用绝对定位 */position: absolute;/* 盒子的宽高均为20px */width: calc(var(--img-gap) / 2);height: calc(var(--img-gap) / 2);}/* 左上角的线框 */.line-item:nth-child(1) {top: 0;left: 0;border-top: var(--line-box-border);border-left: var(--line-box-border);}/* 右上角的线框 */.line-item:nth-child(2) {top: 0;right: 0;border-top: var(--line-box-border);border-right: var(--line-box-border);}/* 左下角的线框 */.line-item:nth-child(3) {bottom: 0;left: 0;border-bottom: var(--line-box-border);border-left: var(--line-box-border);}/* 右下角的线框 */.line-item:nth-child(4) {right: 0;bottom: 0;border-bottom: var(--line-box-border);border-right: var(--line-box-border);}</style>
</head><body><div class="grid-container"><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_1.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_2.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_3.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_4.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_5.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_6.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_7.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_8.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_9.jpg" alt=""></div><div class="line-box"><div class="line-item"></div><div class="line-item"></div><div class="line-item"></div><div class="line-item"></div></div></div>
</body>
<script>// 获取图片元素列表var itemList = document.querySelectorAll(".grid-item");// 获取线框盒子var lineBox = document.querySelector(".line-box");itemList.forEach(item => {// 给每个图片注册鼠标进入事件item.addEventListener("mouseenter", function () {// 获取图片的左、上边距(距离父元素),并赋值给线框作为left、top值lineBox.style.top = item.offsetTop + 'px';lineBox.style.left = item.offsetLeft + 'px';})});
</script></html>

三、页面准备

1、页面结构

(1)结构分析

根据上述效果图,可知:

  • 页面中有一个大容器,在其父容器中水平垂直居中
  • 容器中排列了三行三列,总共9个元素;
  • 每个元素中放一张图片;

(2)结构代码

  • 页面中添加一个Grid布局容器【.grid-container】和9个Grid元素【.grid-item】;
  • 每个Grid元素中添加一个img元素【.one-img】,用来展示图片;
<body><div class="grid-container"><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_1.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_2.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_3.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_4.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_5.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_6.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_7.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_8.jpg" alt=""></div><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_9.jpg" alt=""></div></div>
</body>

2、初始样式

(1)样式分析

根据上述效果图,可知:

  • Grid容器【.grid-container】中的9个Grid元素【.grid-item】,呈现【3行3列】的排列方式;
  • 设置body为Flex布局,使Grid容器在页面中水平垂直居中显示;
  • img元素的大小为父容器Grid元素【.grid-item】的大小;

(2)样式代码

<style>* {/* 清除默认边距 */margin: 0;padding: 0;}body {/* 设为flex布局 */display: flex;/* 设置子元素水平居中 */justify-content: center;/* 设置子元素垂直居中 */align-items: center;width: 100vw;height: 100vh;background-color: #eeffff;caret-color: transparent;}.grid-container {/* 设为Grid布局 */display: grid;/* 划分3列,列宽为240px */grid-template-columns: repeat(3, 240px);/* 划分3行,行高为160px */grid-template-rows: repeat(3, 160px);/* 元素间距为40px */gap: 40px;}.one-img {/* 图片大小为其父元素大小 240px * 160px */width: 100%;height: 100%;box-shadow: 0 0 6px 1px #666;border-radius: 6px;}
</style>

3、基本效果

三、线框实现

1、需求分析

对于上述图中的线框效果,实现步骤如下:

(1)准备线框盒子

需要准备一个盒子【.line-box】,这个盒子要比图片大,包裹住图片,如下图所示:

(2)添加四角小盒子

但是效果图中的边框只在四角出现,这个盒子显然不能实现这样的效果;

这里采用的办法是,给这个线框盒子的四角分别添加一个小盒子【.line-item】,如下图所示:

(3)边框调整

到这里,基本上已经很明显了,只需要去除线框盒子【.line-box】的边框效果,再给四角小盒子【.line-item】分别添加上对应位置的边框,就可以实现了;

注意:线框效果的实现方式有很多,这里仅介绍这种简单粗暴的实现方式;

( 如果有其他更好的实现方式,还希望请各位大佬不吝赐教~!)

2、线框结构

根据上述分析可知:

  • 线框盒子的位置是相对与Grid容器【.grid-container】的;
  • 在Grid容器中添加一个div盒子【.line-box】,与9个图片盒子同级;
  • 在【.line-box】盒子中添加四角小盒子【.line-item】* 4;

注意:这里将线框添加到Grid容器【.grid-container】中,是为了给后续线框的定位做准备;

<body><div class="grid-container"><div class="grid-item"><img class="one-img" src="D:\\test\\zyl-img\\bg_1.jpg" alt=""></div>......<div class="line-box"><div class="line-item"></div><div class="line-item"></div><div class="line-item"></div><div class="line-item"></div></div></div>
</body>

3、线框大小

如何确定线框的大小?

分析效果图可知:它的位置如下图红色框所示:

  • 线框的宽度 = 图片的宽度(240px) +  两图的间距(40px);(左右间距各一半)
  • 线框的高度 = 图片的高度(160px) +  两图的间距(40px);(上下间距各一半)

4、线框位置

如何确定线框位置?

分析效果图可知:

  • 首先,线框需要采用绝对定位,相对其父元素【.grid-container】(脱离标准流,覆盖在图片上);
  • 其次,当线框出现在第一个图片之上时,很明显不能和和它的父元素【.grid-container】的上边界和左边界贴合;

如下图所示,这并不是想要的结果:

这里采用的方式是给线框【.line-box】一个负的margin值(当然也可以采用其他方式);

这样一来,线框中心就会与图片中心重合,在视觉上达到需要的效果,如下图所示:

5、线框样式

根据上述分析可知:

  • 线框【.line-box】采用绝对定位:position: absolute;
  • 父元素【.grid-container】采用相对定位:position: relative;
  • 线框距离父元素的左、上距离均为0(线框的初始位置);
  • 线框设置负的margin值:margin-top: -20px; margin-left: -20px;
  • 四角盒子采用绝对定位,相对于父元素线框【.line-box】:position: absolute;
  • 四角盒子大小为图片间距(40px)的一半:width: 20px;  height: 20px;
  • 分别给每个顶角盒子单独设置位置和样式;

相关元素的样式代码如下:

<style>.......grid-container {/* 设为相对定位 */position: relative;......}.line-box {/* 设置线框为绝对定位 */position: absolute;/* 距离父元素的上、左距离为0; */top: 0;left: 0;/* 线框盒子的宽度为图片宽度(240px) +  图片的间距(40px) */width: 280px;/* 线框盒子的高度为图片高度(160px) +  图片的间距(40px) */height: 200px;/* 设置线框的margin值 */margin-top: -20px;margin-left: -20px;}.line-item {/* 四角边框采用绝对定位 */position: absolute;/* 盒子的宽高均为20px */width: 20px;height: 20px;}/* 左上角的线框 */.line-item:nth-child(1) {top: 0;left: 0;border-top: 2px solid red;border-left: 2px solid red;}/* 右上角的线框 */.line-item:nth-child(2) {top: 0;right: 0;border-top: 2px solid red;border-right: 2px solid red;}/* 左下角的线框 */.line-item:nth-child(3) {bottom: 0;left: 0;border-bottom: 2px solid red;border-left: 2px solid red;}/* 右下角的线框 */.line-item:nth-child(4) {right: 0;bottom: 0;border-bottom: 2px solid red;border-right: 2px solid red;}
</style>

效果如下图所示:

6、移动线框

分析需求可知:

  • 当鼠标移入某个图片时,将线框移动到该图片周围;
  • 分别给每个图片盒子注册鼠标进入事件;
  • 当鼠标进入该图片时,计算其到父盒子【.grid-container】的上边距和左边距,并赋值给线框作为top和left值;
<script>// 获取图片元素列表var itemList = document.querySelectorAll(".grid-item");// 获取线框盒子var lineBox = document.querySelector(".line-box");itemList.forEach(item => {// 给每个图片注册鼠标进入事件item.addEventListener("mouseenter", function () {// 获取图片的左、上边距(距离父元素),并赋值给线框作为left、top值lineBox.style.top = item.offsetTop + 'px';lineBox.style.left = item.offsetLeft + 'px';})});
</script>

7、添加过渡效果

可以给线框添加过渡效果,让它的移动看起来平滑一点;

.line-box {....../* 添加过渡效果 */transition: top 0.4s, left 0.4s;
}

8、使用CSS变量

上述代码中,很多地方都使用了同样的属性值;例如,

  • 顶角盒子边框样式;
  • 根据图片大小和间距计算的线框大小和位置等;

这些内容均可以通过CSS中的变量来实现;具体可以这样修改:

<style>:root{/* 定义变量 *//* 图片的宽度 */--img-width:240px;/* 图片的高度 */--img-height:160px;/* 图片的间距 */--img-gap:40px;/* 线框的样式 */--line-box-border: 2px solid red;}.......grid-container {....../* 划分3列,列宽为240px */grid-template-columns: repeat(3, var(--img-width));/* 划分3行,行高为160px */grid-template-rows: repeat(3, var(--img-height));/* 元素间距为40px */gap: var(--img-gap);}.line-box {....../* 线框盒子的宽度为图片宽度(240px) +  图片的间距(40px) */width: calc(var(--img-width) + var(--img-gap));/* 线框盒子的高度为图片高度(160px) +  图片的间距(40px) */height: calc(var(--img-height) + var(--img-gap));/* 设置线框的margin值 */margin-top: calc(-1 * var(--img-gap) / 2);margin-left: calc(-1 * var(--img-gap) / 2);......}.line-item {....../* 盒子的宽高均为20px */width: calc(var(--img-gap) / 2);height: calc(var(--img-gap) / 2);}/* 左上角的线框 */.line-item:nth-child(1) {......border-top: var(--line-box-border);border-left:var(--line-box-border);}/* 右上角的线框 */.line-item:nth-child(2) {......border-top: var(--line-box-border);border-right: var(--line-box-border);}/* 左下角的线框 */.line-item:nth-child(3) {......border-bottom: var(--line-box-border);border-left: var(--line-box-border);}/* 右下角的线框 */.line-item:nth-child(4) {......border-bottom: var(--line-box-border);border-right: var(--line-box-border);}
</style>

这样一来,如果需要更改图片大小、间距,线框大小、位置、样式等,直接在变量声明的地方统一更改即可,不需要再多做修改;

=========================================================================

每天进步一点点~!

记录一下这个有意思的CSS效果~~!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3247506.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

微服务设计原则——高性能:锁

文章目录 1.锁的问题2.无锁2.1 串行无锁2.2 无锁数据结构 3.减少锁竞争参考文献 1.锁的问题 高性能系统中使用锁&#xff0c;往往带来的坏处要大于好处。 并发编程中&#xff0c;锁带解决了安全问题&#xff0c;同时也带来了性能问题&#xff0c;因为锁让并发处理变成了串行操…

WebStorm 2024.1 最新变化 附问卷调查 AI

WebStorm 2024.1 最新变化 问卷调查项目在线AI WebStorm 2024.1 最新变化关键亮点粘性行快速文档改进全行代码补全默认启用的 Vue Language Server适用于 Vue、Svelte 和 Astro 的组件用法*Language Services*&#xff08;语言服务&#xff09;微件 框架和技术实验性 TypeScrip…

【PPT笔记】1-3节 | 默认设置/快捷键/合并形状

文章目录 说明笔记1 默认设置1.1 OFFICE版本选择1.1.1 Office某某数字专属系列1.1.2 Office3651.1.3 产品信息怎么看 1.2 默认设置1.2.1 暗夜模式1.2.2 无限撤回1.2.3 自动保存&#xff08;Office2013版本及以上&#xff09;1.2.4 图片压缩1.2.5 字体嵌入1.2.6 多格式导出1.2.7…

arcgis怎么选取某个指定区域地方的数据,比如从全国乡镇数据选取长沙市乡镇数据

一共5个步骤&#xff0c;没一句废话&#xff0c;耐心看完。 1、如图&#xff0c;先将数据加载到arcgis里面&#xff0c;我们要选取里面长沙市的范围数据。 2、选取长沙市的语句 “市” like ‘长沙%’ 切记&#xff0c;切记&#xff0c;切记。所有符号要在 输入法英文状态…

5.5 软件工程-系统测试

系统测试 - 意义和目的 系统测试 - 原则 系统测试 - 测试过程 系统测试 - 测试策略 系统测试 - 测试方法 真题 系统测试 - 测试用例设计 黑盒测试 白盒测试 真题 系统测试 - 调试 系统测试 - 软件度量 真题

服务器IP和电脑IP有什么不同

服务器IP和电脑IP有什么不同&#xff1f;在当今的信息化时代&#xff0c;IP地址作为网络世界中不可或缺的元素&#xff0c;扮演着举足轻重的角色。然而&#xff0c;对于非专业人士来说&#xff0c;服务器IP和电脑IP之间的区别往往模糊不清。本文旨在深入探讨这两者之间的不同&a…

Spock单元测试框架使用介绍和实践

背景 单元测试是保证我们写的代码是我们想要的结果的最有效的办法。根据下面的数据图统计&#xff0c;单元测试从长期来看也有很大的收益。 单元测试收益: 它是最容易保证代码覆盖率达到100%的测试。可以⼤幅降低上线时的紧张指数。单元测试能更快地发现问题。单元测试的性…

Flutter动画详解第二篇之显式动画(Explicit Animations)

目录 前言 一、定义 1.AnimationController 1.常用属性 1. value 2. status 3. duration 2.常用方法 1.forward 2.reverse 3.repeat 4.stop 5. reset 6. animateTo(double target, {Duration? duration, Curve curve Curves.linear}) 7.animateBack(double ta…

Qt 快速保存配置的方法

Qt 快速保存配置的方法 一、概述二、代码1. QFileHelper.cpp2. QSettingHelper.cpp 三、使用 一、概述 这里分享一下&#xff0c;Qt界面开发时&#xff0c;快速保存界面上一些参数配置的方法。 因为我在做实验的时候&#xff0c;界面上可能涉及到很多参数的配置&#xff0c;我…

鼠标的发明和鼠标“变形记”

注&#xff1a;机翻&#xff0c;未校对。 Who Invented the Computer Mouse? 谁发明了电脑鼠标&#xff1f; It was technology visionary and inventor Douglas Engelbart (January 30, 1925 – July 2, 2013) who revolutionized the way computers worked, turning it fr…

【数据结构】--- 顺序表

目录 前言&#xff1a; 顺序表 动态顺序表的实现 代码总览&#xff1a; 前言&#xff1a; 数据结构是由“数据”和“结构”两词组合而来。 什么是数据&#xff1f; 常见的数值1、2、3、4.....、教务系统⾥保存的⽤⼾信息&#xff08;姓名、性别、年龄、…

Kafka Producer之ACKS应答机制

文章目录 1. 应答机制2. 等级03. 等级14. 等级all5. 设置等级6. ISR 1. 应答机制 异步发送的效率高&#xff0c;但是不安全&#xff0c;同步发送安全&#xff0c;但是效率低。 无论哪一种&#xff0c;有一个关键的步骤叫做回调&#xff0c;也就是ACKS应答机制。 其中ACKS也分…

Qt QProcess 进程间通信读写数据通信

本文介绍了如何使用Qt的QProcess 进行程序开发&#xff0c;包括启动进程间通信、设置环境变量、通用方法&#xff1b;方便在日常开发中使用&#xff1b; 1.使用Qt进行程序开发&#xff0c;可以通过QProcess类用于启动外部程序并与其进行通信.&#xff1b; 进程A&#xff08;…

CentOS 7 安装MySQL 5.7.30

CentOS 7 安装MySQL卸载&#xff08;离线安装&#xff09; 安装配置MySQL之前先查询是否存在&#xff0c;如存在先卸载再安装 rpm -qa|grep -i mysql rpm -qa|grep -i mariadb rpm -e --nodeps mariadb-libs-5.5.68-1.el7.x86_64如下命令找到直接 rm -rf 删除&#xff08;删除…

代理IP服务中的代理池大小有何影响?

在当今数字化时代&#xff0c;网络爬虫已经成为获取各类信息必不可少的工具。在大规模数据抓取中&#xff0c;使用单一 IP 地址或同一 IP 代理往往会面临抓取可靠性降低、地理位置受限、请求次数受限等一系列问题。为了克服这些问题&#xff0c;构建代理池成为一种有效的解决方…

Java基础笔记(面试题)

一、Tomcat中为什么要使用自定义类加载器 Tomcat中可以放多个Java项目的jar文件&#xff0c;如果每个jar文件中都有一个User的类&#xff0c;那么User类在没有自定义类加载器的情况下是只能加载一次&#xff1b;想要加载多次&#xff0c;只能自定义类加载器 二、JDK、JRE、JVM…

【leetcode】 字符串相乘(大数相乘、相加)

记录一下大数相乘相加方法&#xff1a; 给定两个以字符串形式表示的非负整数 num1 和 num2&#xff0c;返回 num1 和 num2 的乘积&#xff0c;它们的乘积也表示为字符串形式。 注意&#xff1a;不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 示例 1: 输入: nu…

基于嵌入式Linux的高性能车载娱乐系统设计与实现 —— 融合Qt、FFmpeg和CAN总线技术

随着汽车智能化的发展&#xff0c;车载娱乐系统已成为现代汽车的标配。本文介绍了一个基于Linux的车载娱乐系统的设计与实现过程。该系统集成了音视频娱乐、导航、车辆信息显示等功能&#xff0c;旨在提供安全、便捷、丰富的驾驶体验。 1. 项目概述 随着汽车智能化的发展&…

Java对象转换为JSON字符串

0 写在前面 业务中有很多场景需要 把一个带有数据的 Java对象/Java集合转换为JSON 存入数据库中。 在需要的时候还需要吧和这个JSON字符串拿出来再次转换成Java对象/集合 1 Java对象与JSON字符串互转 引入依赖: <dependency><groupId>com.alibaba</groupId&…

【5G Sub-6GHz模块】专为IoT/eMBB应用而设计的RG520NNA、RG520FEB、RG530FNA、RG500LEU 5G模组

推出全新的5G系列模组&#xff1a; RG520NNADB-M28-SGASA RG520NNADA-M20-SGASA RG520FEBDE-M28-TA0AA RG530FNAEA-M28-SGASA RG530FNAEA-M28-TA0AA RG500LEUAA-M28-TA0AA ——明佳达 1、5G RG520N 系列——专为IoT/eMBB应用而设计的LGA封装模块 RG520N 系列是一款专为 IoT…