与CSS相关的三个小页面。
前言
近期对前端有些手痒, 正好有三个小页面可以拿来练手, 记录实现过程中学到的若干与CSS相关的知识。
- 替代word做简易海报, 实现自动填充海报内容;
- 以简易动画的形式绘制站点URL来由;
- 个人页面增加悬浮照片。
知识点概况
其中涉及到的CSS知识点包括:
- SVG Path:
stroke-dasharray|stroke-dashoffset @keyframes|animationnth-child@media|screen|max-widthposition|relative|float|top
学习CSS布局
这篇教程快速地介绍了CSS中常用的布局关键词, 适合初学与备查。
替代word做简易海报
动机
老婆单位需要每周表彰业绩标兵, 制作喜报; 喜报格式很简单, A4大小, 之前用word制作了一版。每周需要根据当周的情况修改标兵姓名, 然后导出为图片格式; 由于有多个业务种类, 是重复性高的一项工作。考虑通过网页实现此功能, 将每周的标兵数据保存为json文件, 直接读取并显示到页面即可, 通过浏览器的打印功能一键出图, 一劳永逸。
相关CSS知识点
单个页面是A4大小, 设计page对象的样式如下1:
page {
background: white;
background-image: url("background-images/individual.png");
background-size: cover;
background-repeat: no-repeat;
display: block;
margin: 0 auto;
box-shadow: 0 0 0.5cm rgba(0,0,0,0.5);
}
page[size="A4"] {
width: 21cm;
height: 29.7cm;
}
其中用到的CSS相关属性包括:
background-image, 通过url指定背景图片的位置;background-size, 通过设置此属性为cover可以让图片覆盖整个page对象; 再结合backgroud-repeat: no-repeat控制背景图片不会重复;width|height分别设置对象的宽度和高度为A4纸张的大小。
如此, 单个页面和背景就完成了; 接下来只需要在上面合适的位置摆放表彰内容即可; 设计一个div对象存储表彰内容, 并定义其class=content_placer, 相应地.content_placer的样式设计如下:
.content_placer {
position: relative;
width: 18cm;
margin: 0 auto;
top: 36%;
font-family: "Microsoft YaHei";
font-size: 44;
font-weight: bold;
text-shadow: 1px 2px rgba(255, 191, 0, 0.60);
color: gold;
line-height: 1.8em;
}
其中用到的CSS相关属性包括:
position: relative, 指明对象的位置是相对于其父对象的, 相对地如果设定为absolute则是相对整个浏览器页面的;top: 36%, 表明对象位置上方空出的空间占父对象高度的36%, 相当于将对象下移;line-height: 1.8em, 表示对象的行高为1.8倍的字体高度;text-shadow, 设置文本的阴影效果。
另一方面, 喜报整体上分为两个类型: 个人和团队, 布局上会有少许差别, 这里可以用到CSS样式”继承”的概念, 如下:
.content_placer.group {
top: 46%;
text-shadow: 1.5px 2px rgba(255, 0, 0, 0.5);
color: rgb(255, 229, 153);
line-height: 1.5em;
}
默认的.content_placer类适用于个人, 团队的样式整体上与个人类似, 但有若干属性需要调整, 那么可以在HTML中为团队类型增加一个class: group, 与content_placer组合起来, 并如上在.content_placer.group中改写相应的属性即可; 在HTML中定义团队的标签如下:
<div class="content_placer group"></div>
效果图
个人版
团队版人名已做随机处理。
Tips
除了CSS以外, 这个小项目涉及得流程中还包括几个值得记录的点:
- Python创建简易的服务器
由于浏览器的安全性考虑不允许Javascript直接读取本地的文件, 只能考虑创建一个本地服务, 将json文件作为资源host在本地”服务器”上, 再通过GET方法获取该文件。而这一过程可以通过Python 3快速实现2:
cd location/to/the/folder
python -m http.server 8000
其中, 8000为端口号, 可以设定任意未被占用的端口号; 启动后, 在浏览器中通过localhost:8000即可访问; 所创建的服务器根目录将位于location/to/the/folder。
- 一键PDF转PNG
浏览器打印所得的PDF文件可以通过Linux下的软件pdftoppm一键转换为图片3, 并且是每一页对应一张图片, 如下:
pdftoppm input.pdf outputname -png
在Windows下, 可以通过WSL安装Ubuntu系统, 在其上再安装若干实用Linux软件。
SVG简易动画
第二个页面是为了演示本站URL的来历, 效果👉这里。本页的动画受到这个视频的启发。所展示的图像是一个SVG图片, 由多个字母组成, 每个字母单独为一个path顺次并列于svg标签下, SVG图片是在Figma完成的, 这一点在视频中也有介绍。主要用到的CSS知识点包括:
nth-child | stroke-dasharray | stroke-dashoffset | @keyframes
nth-child
如上所述, 每个字母独立为一个path, 可以通过path:nth-child(x)访问到第x个path, 无需使用Javascript。
stroke-dasharray
这是实现动画的关键属性, 属于path, 该值控制图形的虚线化效果的空白区大小, 默认单位是px; 值越大, 空白区越大; 与之配套的还有stroke-dashoffset, 控制起始点的偏移; 两者结合起来常见的用法如下:
path {
stroke-dasharray: 150;
stroke-dashoffset: 0;
}
path {
stroke-dasharray: 150;
stroke-dashoffset: 150;
}
假设当前的path长度为150(可以通过getTotalLength()方法获得path的长度), 那么左边的写法就显示了该path的完整图形, 而右边则完全隐去了该path; 因为通过stroke-dasharray: 150指定了空白区域的长度与path长度等长, 但stroke-dashoffset又等于0, 即空白区域实际上从150-0处才开始, 也就看不到空白区域了; 相反若指定stroke-dashoffset: 150则空白区域从150-150=0处开始, 并且空白区长度与path等长, 故path就被隐去了。
@keyframes 与 animation
接下来就是”动起来”。顾名思义, @keyframes中可以指定关键帧的样式, 再结合animation, CSS将自动根据填补关键帧之间的变化过程从而形成动画效果。@keyframes的使用示例如下:
@keyframes name-one {
from {
stroke-dashoffset: 150;
}
to {
stroke-dashoffset: 0;
}
}
@keyframes name-two {
0%, 50% {
fill: transparent;
}
100% {
fill: red;
}
}
其中, 跟在@keyframes后的为这组关键帧的名称, 方便在animation中调用; 而在一组关键帧中可以指定多个时间节点的特征, 例如左边用from|to两个点表示动画的开始|结束两个时间节点; 也可以像右边通过百分比指定时间节点。因为@keyframes并不决定动画的绝对时长, 只确定相对的节点, 可以方便与animation的控制参数”脱钩”。
结合animation的用例如下:
path:nth-child(1) {
animation:
name-one 1s ease forwards,
name-two 1s ease forwards 1s;
}
如上, 将在为第一个path添加两个动画: name-one和name-two, 分别持续1s, 并且name-two延迟1s后执行, 从而实现两个动画衔接的效果。基于以上的原理, 根据预期实现的效果对应为每个字母设计相应的关键帧与动画即可。
个人页面增加悬浮照片
最后一个页面是为CV页添加悬浮照片, 可以在这里看到效果。用到的CSS知识点如下:
float|display: none@media|screen|max-width
用例如下:
#ID_PHOTO {
position: relative;
float: right;
z-index: 99;
}
@media screen and (max-width: 800px) {
#ID_PHOTO {
display: none !important;
}
}
其中float: right将图片对象放置于其父容器的右侧; 而@media用于控制浏览器窗口大小变化时相应的样式变化, 这里结合max-width: 800px的逻辑是: 当屏幕宽度小于800px时设置#ID_PHOTO对象的显示属性为none, 即隐藏。
移动对象
由于CV页是借由主题提供的模板布局写成, 语言为markdown, 那么新增一个照片对象在其中时, 其父容器也就由插入的位置确定了; 但我想改一下其父对象以达到更合预期的效果, 这时就需要用到一点Javascript了4。
(function () {
document.querySelector(".article__header header").appendChild(
document.querySelector("#ID_PHOTO")
);
})();
以上语法言简意赅, 可以实现需求。