在之前的一篇文章《默认的input标签太丑?教你如何使用CSS写出带动画的样式》中有讲过如何实现一个漂亮的input标签样式。
既然已经折腾了,今天这篇文章我们就继续折腾,看看如何通过CSS3实现一个带动画的checkbox样式?
CSS3
感兴趣的可以自行去github上看源文件,地址如下:
https://github.com/zhouxiongking/article-pages/blob/master/articles/beautifulCheckbox/beautifulCheckbox.html
checkbox作为多选框,在form表单中的使用频率是非常高的,例如问卷调查的多选题,个人兴趣爱好的选择时都会用到多选框。
而浏览器默认的checkbox样式都很丑,看起来就是一个小小的方框,虽然Bootstrap已经有好看的checkbox样式,但是它不支持动画,在交互上仍然存在缺陷,所以我们就试图自己写出一个带动画的checkbox效果。
首先我们来看看checkbox的动态效果图(中间的黑色圆圈实际为录制GIF图时产生的,请忽略)
checkbox效果图
接下来我们具体分析下页面的元素组成,主要包括以下部分。
默认的checkbox标签,将其display设置为none,隐藏起来。
label标签,表现为实际显示的动态选中和未选中效果。
我们需要达到的效果是,在未选中checkbox时,默认为灰色的边框,白色的背景;在选中checkbox时,改变背景色,出现白色的打勾动画效果。
在这部分,我们来具体分析下页面的代码组成。
HTML
首先是页面的HTML部分代码,如上一部分所示,页面其实只有两个元素组成,这两个元素放在一个容器下,故HTML代码如下所示。
HTML部分代码
CSS
我们来看看CSS部分的代码,因为CSS部分代码比较多,我们一一来分析。
首先是外层container的样式,同时对页面的html和body也做一些简单处理,代码如下所示。
container样式
其次是checkbox标签的样式,因为原生的checkbox除了在传输数据时有用处,在页面呈现上并没有作用,故设置display:none;将其隐藏。
checkbox样式
然后是最重要的label部分,在未点击之前label呈现一个正方形,有基本的样式。
基本样式
在点击方形框后,出现的对勾是通过伪元素::before和::after实现的,对勾实际为两个矩形拼接而成,左侧的矩形用::after元素表示,右侧的矩形用::before元素表示。两者的通用样式通过如下代码实现。
伪元素实现
然后是针对::before和::after所特有的样式,因为两者的位置和旋转的角度不同,代码也会出现差异。
特有样式
然后是定义的打钩的动画效果,这里使用keyframes关键字定义,考虑到浏览器兼容性,定义的动画具有不同的前缀。定义的动画也包括两部分,首先是右侧的矩形动画效果。
右侧矩形动画效果
然后是左侧矩形的动画效果,同样考虑到浏览器的兼容性,样式代码如下。
左侧矩形动画
至此,所有代码都已讲解完毕,如果运行之后就会看到文章开始的动画效果。
本篇文章主要讲的是如何使用自定义的动画完成checkbox效果,感兴趣的可以直接去github上看源文件代码,后续会写一个跟开关switch有关的文章,敬请期待~
早 发自 凹非寺
量子位 报道 | 公众号 QbitAI
万万没想到,如此普通的复选框,竟也能玩出这种高度!
例如点一下复选框,屏幕就像被投入石子的水面泛出波纹:
设定好初始状态,就可以开始展示《生命游戏》的演化过程;
控制上下左右,还能还原经典游戏《贪吃蛇》;
这就是一位做前端开发的小哥Bryan,近期在自己的网站上发布的有关checkbox (复选框)的新玩法。
这个项目在Hacker News上引来了大量网友评论。
高赞评论已经给小朋友安排得明明白白了~
而面对一些诸如“为什么要用复选框,普通像素就可以达到这种效果”的质疑,也有人为Bryan说话:
回到这件事本身,其实在去年早些时候,他就建了一个名为Checkboxland的JavaScript库。
它可以将任何内容呈现为HTML复选框。
讲真,刚才展示的复选框效果,只能说是“开胃菜”。
不仅仅是简单的动画,日常拍下的照片,记录的生活vlog,一样可以成为“复选框”的素材。
小哥本人也一度以为灵感耗尽,但在参阅了一篇关于将图像转化为ASCII的文章之后,Bryan将耐克和苹果的logo转化了出来(不建议转化迪士尼的logo)。
小哥本人也是老二次元了,《Bad Apple》也是信手拈来:
随后,自嘲“the CheckBox guy”的小哥赋予了复选框更多的可能,他又拓展了Checkboxland API,用来加载任何视频并生成复选框版本。
下面这个看起来就像进入了《星际穿越》的五维立方体。
而此刻你如果打开摄像头,Bryan还可以带领你半只脚踏进《黑客帝国》~
赶快学起来,说不定还能用来画心形图,成为你的表白神器(不是)!
看似炫酷的效果实际制作过程只需分为两大步,手把手教你!
1.做出原本的图像。
2.将图像转化为ASCII文本输出。
以水波为例,首先要生成这样动态的水波。
想要生成它,需要以中心为原点,在xy平面上建立正弦函数。
z轴垂直屏幕向外,把z轴的数值转化为灰度,白色为波峰,黑色为波谷。
然后在图形计算器desmos上让水波动起来,这样第一步就完成了。
第二步,将第一步的成果转化为ASCII码输出。
这一步的转化主要涉及到将彩色对应灰度。
采用这个公式,即使是彩色的图片,也只不过是五彩斑斓的灰罢了~
GrayScale = 0.21 R + 0.72 G + 0.07 B
提取原图的RGB色彩,输出为灰度:
const toGrayScale = (r, g, b) => 0.21 * r + 0.72 * g + 0.07 * b;
const convertToGrayScales = (context, width, height) => {
const imageData = context.getImageData(0, 0, width, height);
const grayScales = [];
for (let i = 0 ; i < imageData.data.length ; i += 4) {
const r = imageData.data[i];
const g = imageData.data[i + 1];
const b = imageData.data[i + 2];
const grayScale = toGrayScale(r, g, b);
imageData.data[i] = imageData.data[i + 1] = imageData.data[i + 2] = grayScale;
grayScales.push(grayScale);
}
context.putImageData(imageData, 0, 0);
return grayScales;
};
然后为每个像素赋灰度值:
const grayRamp = '$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,"^`\'. ';
const rampLength = grayRamp.length;
const getCharacterForGrayScale = grayScale => grayRamp[Math.ceil((rampLength - 1) * grayScale / 255)];const asciiImage = document.querySelector('pre#ascii');
const drawAscii = (grayScales) => {
const ascii = grayScales.reduce((asciiImage, grayScale) => {
return asciiImage + getCharacterForGrayScale(grayScale);
}, '');
asciiImage.textContent = ascii;
};
最后调整一下图片大小就大功告成了~更多详细内容见文后链接~
在最近的更新中,Bryan称,他创造新天地的事情将暂时告一段落。
但是他不仅留下了复选框新玩法原理的详细介绍,还有自制的丰富的demos。这些足以让你探索创造。
简单的动画,贪吃蛇,通过摄像头实时生成复选框版图像(demos中的webcam)…
点击即可试玩,以贪吃蛇和webcam为例:
点击snake,键盘上下左右即可控制贪吃蛇:
点击webcam,打开前置摄像头,可以看到自己的实时动态:
根据网友的反馈,似乎在安卓系统中打开会白屏,但是在Mac Safari, iPhone Safari, 桌面Chrome上都可以使用。
感兴趣的小伙伴,快来试试吧~
参考链接:
[1]https://www.bryanbraun.com/2021/09/21/i-keep-making-things-out-of-checkboxes/
[2]https://news.ycombinator.com/item?id=28826018
[3]https://www.jonathan-petitcolas.com/2017/12/28/converting-image-to-ascii-art.html
[4]https://www.bryanbraun.com/checkboxland/#demos
[5]https://github.com/bryanbraun/checkboxland
— 完 —
量子位 QbitAI · 头条号签约
关注我们,第一时间获知前沿科技动态
家好,今天我们将一起学习下如何从零开始创建一个具有缩略图功能的响应式幻灯片。这个案例我们无需编写任何 JavaScript 代码,这里主要运用了 CSS checkbox hack 的技术进行实现。
这篇文章运用了复杂的CSS选择器、flex box 和 Grid 布局、 CSS checkbox 的伪类选择器 checked 等技术
如视频所示,一个功能完备漂亮的幻灯片图片组件。
<script src="https://lf6-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>
1、首先我们准备3张图片素材。
2、接下来我们新建3个radio按钮,通过name属性进行按钮分组
<input type="radio" id="image1" name="image" checked>
<input type="radio" id="image2" name="image">
<input type="radio" id="image3" name="image">
3、然后我们创建 .featured-wrapper 和 .thumb-list 两个容器,放置内容元素
3.1、.featured-wrapper 元素包含3个列表:
1、一个大图列表,一次只能显示一个图片
2、一组箭头列表,用于大图切换
3、一组圆圈列表,用于大图切换
这里我们使用label标签技巧与radio表单进行对应代替JS事件点击,同一个 radio 可以关联多个与之对应的 label 标签。
3.2、.thumb-list 容器包含一组图片缩略图,与大图对应,用于切换大图。
总而言之,我们说了这么多,我们可以通过箭头、圈圈、缩略图进行幻灯大图的切换,整体的 HTML 结构如下图所示:
基于上图所示,最终完成的 HTML 代码结构如下:
<div class="container">
<div class="featured-wrapper">
<ul class="featured-list">
<li>
<figure>
<img src="IMG_SRC" alt="">
</figure>
</li>
<!-- other two list items here -->
</ul>
<ul class="arrows">
<li>
<label for="image1"></label>
</li>
<li>
<label for="image2"></label>
</li>
<li>
<label for="image3"></label>
</li>
</ul>
<ul class="dots">
<li>
<label for="image1"></label>
</li>
<li>
<label for="image2"></label>
</li>
<li>
<label for="image3"></label>
</li>
</ul>
</div>
<ul class="thumb-list">
<li>
<label for="image1">
<img src="IMG_SRC" alt="">
<span class="outer">
<span class="inner">...</span>
</span>
</label>
</li>
<!-- other two list items here -->
</ul>
</div>
1、将 radio 按钮移除至屏幕外,示例代码如下:
input[type="radio"] {
position: absolute;
bottom: 0;
left: -9999px;
}
这里你会注意到,我使用了bottom: 0,主要为了防止每次点击标签时,浏览器跳至页面顶部。虽然不是最佳实践,但是这个方法对本案例有效,还有一个更好的做法,我们可以设置display: none,但是不符合键盘可访问性(accessibility)的标准,这里还是推荐 bottom: 0;
2、定义最外层 container 容器的样式,设置最大宽度以及让其水平居中
.container {
max-width: 450px;
padding: 0 20px;
margin: 0 auto;
}
3、定义大图列表样式
为了只显示一张大图,其他图片将会被盖住并且隐藏,你可能最先想到的是改变文档正常流,使用position属性进行定位的方法进行隐藏,这里你需要注意图片的宽高比,通常使用固定高度的解决方案,在这个案例中,我们使用CSS的Grid新布局,将图片放置在1行1列的单元网格中,示例如下图所示:
与上图对应的CSS代码如下:
.featured-wrapper .featured-list {
display: grid;
}
.featured-wrapper .featured-list li {
grid-column: 1;
grid-row: 1;
opacity: 0;
transition: opacity 0.25s;
}
4、定义小圆圈样式
我们需要将小圆圈定位在 .featured-wrapper 容器底部,点击相应圆圈进行切换大图:
相应的CSS代码如下所示:
/*CUSTOM VARIABLES HERE*/
.featured-wrapper {
position: relative;
}
.featured-wrapper .dots {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
display: flex;
}
.featured-wrapper .dots li:not(:last-child) {
margin-right: 8px;
}
.featured-wrapper .dots label {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
border: 1px solid var(--white);
transition: background 0.25s;
}
.featured-wrapper .dots label:hover {
background: currentColor;
}
5、定义箭头样式
接下来我们继续定义箭头切换的样式,我们将其放置在.featured-wrapper容器,如下图所示:
这里需要注意的是,这些箭头与 radio 按钮一一对应关联,这里我们用到了::before 和 ::after伪元素创建圆形元素,示例代码如下:
/*CUSTOM VARIABLES HERE*/
.featured-wrapper .arrows label::before,
.featured-wrapper .arrows label::after {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
border-radius: 50%;
color: var(--black);
background-position: center;
background-repeat: no-repeat;
background-size: 24px 24px;
background-color: var(--white);
opacity: 0.5;
transition: opacity 0.25s;
}
.featured-wrapper .arrows label::before {
left: 10px;
}
.featured-wrapper .arrows label::after {
right: 10px;
}
6、定义缩略图元素样式
每个缩略图占据父容器的三分之一,如下图所示:
在这里,为了将图片标题放置在图片之上,我们用的不是传统的CSS定位,这里我们应用了CSS Grid技巧。
我们将每个缩略图变成单一网格(一行一列),并使用grid垂直居中的技巧 place-items: center 让文本垂直居中,相关代码如下所示:
.thumb-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-column-gap: 20px;
margin-top: 20px;
}
.thumb-list label {
display: grid;
}
.thumb-list img,
.thumb-list .outer {
grid-column: 1;
grid-row: 1;
}
.thumb-list .outer {
display: grid;
place-items: center;
transition: background 0.25s;
}
.thumb-list .inner {
font-size: 18px;
opacity: 0;
transform: translateY(20px);
transition: all 0.25s;
}
接下来是本案例的核心,也是最有趣的地方,我们使用 checkbox hack 的技术模拟JS的点击事件。
每次点击缩略图,相应的箭头和圆圈都会处于活动状态:
基于以上需求最终完成的CSS代码如下:
/*CUSTOM VARIABLES HERE*/
[id="image1"]:checked ~ .container .featured-list li:nth-child(1),
[id="image2"]:checked ~ .container .featured-list li:nth-child(2),
[id="image3"]:checked ~ .container .featured-list li:nth-child(3),
[id^="image"]:checked ~ .container .arrows [for^="image"]:hover::before,
[id^="image"]:checked ~ .container .arrows [for^="image"]:hover::after {
opacity: 1;
}
[id="image1"]:checked ~ .container .arrows [for="image3"]::before,
[id="image2"]:checked ~ .container .arrows [for="image1"]::before,
[id="image3"]:checked ~ .container .arrows [for="image2"]::before {
content: ’’;
background-image: url(arrow-prev-slideshow.svg);
}
[id="image1"]:checked ~ .container .arrows [for="image2"]::after,
[id="image2"]:checked ~ .container .arrows [for="image3"]::after,
[id="image3"]:checked ~ .container .arrows [for="image1"]::after {
content: ’’;
background-image: url(arrow-next-slideshow.svg);
}
[id="image1"]:checked ~ .container .dots [for="image1"],
[id="image2"]:checked ~ .container .dots [for="image2"],
[id="image3"]:checked ~ .container .dots [for="image3"] {
background: currentColor;
}
[id="image1"]:checked ~ .container [for="image1"] .outer,
[id="image2"]:checked ~ .container [for="image2"] .outer,
[id="image3"]:checked ~ .container [for="image3"] .outer {
background: var(--overlay);
}
[id="image1"]:checked ~ .container [for="image1"] .inner,
[id="image2"]:checked ~ .container [for="image2"] .inner,
[id="image3"]:checked ~ .container [for="image3"] .inner {
opacity: 1;
transform: none;
}
最终的效果体验,大家可以点击文末了解更多链接进行体验,由于文章篇幅有限,完整的源码大家可以私信“幻灯片”获取下载链接。
到此我们完成了本案例,通过本案例,我相信你对 CSS checkbox hack 技术有了更清楚的认识,希望你能够适应这项技术,并将其运用到自己的项目中。
动手练一练,做一个现代化、响应式的后台管理首页
使用 Vanilla JavaScript 框架创建一个简单的天气应用
动手练一练,使用 Flexbox 创建一个响应式的表单
动手练一练,用纯 CSS 制作一款侧滑显示留言面板的网页组件
使用 CSS Checkbox Hack 技术制作一个手风琴组件
*请认真填写需求信息,我们会在24小时内与您取得联系。