在之前的一篇文章《默認(rèn)的input標(biāo)簽太丑?教你如何使用CSS寫出帶動(dòng)畫的樣式》中有講過如何實(shí)現(xiàn)一個(gè)漂亮的input標(biāo)簽樣式。
既然已經(jīng)折騰了,今天這篇文章我們就繼續(xù)折騰,看看如何通過CSS3實(shí)現(xiàn)一個(gè)帶動(dòng)畫的checkbox樣式?
CSS3
感興趣的可以自行去github上看源文件,地址如下:
https://github.com/zhouxiongking/article-pages/blob/master/articles/beautifulCheckbox/beautifulCheckbox.html
checkbox作為多選框,在form表單中的使用頻率是非常高的,例如問卷調(diào)查的多選題,個(gè)人興趣愛好的選擇時(shí)都會(huì)用到多選框。
而瀏覽器默認(rèn)的checkbox樣式都很丑,看起來就是一個(gè)小小的方框,雖然Bootstrap已經(jīng)有好看的checkbox樣式,但是它不支持動(dòng)畫,在交互上仍然存在缺陷,所以我們就試圖自己寫出一個(gè)帶動(dòng)畫的checkbox效果。
首先我們來看看checkbox的動(dòng)態(tài)效果圖(中間的黑色圓圈實(shí)際為錄制GIF圖時(shí)產(chǎn)生的,請(qǐng)忽略)
checkbox效果圖
接下來我們具體分析下頁面的元素組成,主要包括以下部分。
默認(rèn)的checkbox標(biāo)簽,將其display設(shè)置為none,隱藏起來。
label標(biāo)簽,表現(xiàn)為實(shí)際顯示的動(dòng)態(tài)選中和未選中效果。
我們需要達(dá)到的效果是,在未選中checkbox時(shí),默認(rèn)為灰色的邊框,白色的背景;在選中checkbox時(shí),改變背景色,出現(xiàn)白色的打勾動(dòng)畫效果。
在這部分,我們來具體分析下頁面的代碼組成。
HTML
首先是頁面的HTML部分代碼,如上一部分所示,頁面其實(shí)只有兩個(gè)元素組成,這兩個(gè)元素放在一個(gè)容器下,故HTML代碼如下所示。
HTML部分代碼
CSS
我們來看看CSS部分的代碼,因?yàn)镃SS部分代碼比較多,我們一一來分析。
首先是外層container的樣式,同時(shí)對(duì)頁面的html和body也做一些簡(jiǎn)單處理,代碼如下所示。
container樣式
其次是checkbox標(biāo)簽的樣式,因?yàn)樵腸heckbox除了在傳輸數(shù)據(jù)時(shí)有用處,在頁面呈現(xiàn)上并沒有作用,故設(shè)置display:none;將其隱藏。
checkbox樣式
然后是最重要的label部分,在未點(diǎn)擊之前l(fā)abel呈現(xiàn)一個(gè)正方形,有基本的樣式。
基本樣式
在點(diǎn)擊方形框后,出現(xiàn)的對(duì)勾是通過偽元素::before和::after實(shí)現(xiàn)的,對(duì)勾實(shí)際為兩個(gè)矩形拼接而成,左側(cè)的矩形用::after元素表示,右側(cè)的矩形用::before元素表示。兩者的通用樣式通過如下代碼實(shí)現(xiàn)。
偽元素實(shí)現(xiàn)
然后是針對(duì)::before和::after所特有的樣式,因?yàn)閮烧叩奈恢煤托D(zhuǎn)的角度不同,代碼也會(huì)出現(xiàn)差異。
特有樣式
然后是定義的打鉤的動(dòng)畫效果,這里使用keyframes關(guān)鍵字定義,考慮到瀏覽器兼容性,定義的動(dòng)畫具有不同的前綴。定義的動(dòng)畫也包括兩部分,首先是右側(cè)的矩形動(dòng)畫效果。
右側(cè)矩形動(dòng)畫效果
然后是左側(cè)矩形的動(dòng)畫效果,同樣考慮到瀏覽器的兼容性,樣式代碼如下。
左側(cè)矩形動(dòng)畫
至此,所有代碼都已講解完畢,如果運(yùn)行之后就會(huì)看到文章開始的動(dòng)畫效果。
本篇文章主要講的是如何使用自定義的動(dòng)畫完成checkbox效果,感興趣的可以直接去github上看源文件代碼,后續(xù)會(huì)寫一個(gè)跟開關(guān)switch有關(guān)的文章,敬請(qǐng)期待~
早 發(fā)自 凹非寺
量子位 報(bào)道 | 公眾號(hào) QbitAI
萬萬沒想到,如此普通的復(fù)選框,竟也能玩出這種高度!
例如點(diǎn)一下復(fù)選框,屏幕就像被投入石子的水面泛出波紋:
設(shè)定好初始狀態(tài),就可以開始展示《生命游戲》的演化過程;
控制上下左右,還能還原經(jīng)典游戲《貪吃蛇》;
這就是一位做前端開發(fā)的小哥Bryan,近期在自己的網(wǎng)站上發(fā)布的有關(guān)checkbox (復(fù)選框)的新玩法。
這個(gè)項(xiàng)目在Hacker News上引來了大量網(wǎng)友評(píng)論。
高贊評(píng)論已經(jīng)給小朋友安排得明明白白了~
而面對(duì)一些諸如“為什么要用復(fù)選框,普通像素就可以達(dá)到這種效果”的質(zhì)疑,也有人為Bryan說話:
回到這件事本身,其實(shí)在去年早些時(shí)候,他就建了一個(gè)名為Checkboxland的JavaScript庫。
它可以將任何內(nèi)容呈現(xiàn)為HTML復(fù)選框。
講真,剛才展示的復(fù)選框效果,只能說是“開胃菜”。
不僅僅是簡(jiǎn)單的動(dòng)畫,日常拍下的照片,記錄的生活vlog,一樣可以成為“復(fù)選框”的素材。
小哥本人也一度以為靈感耗盡,但在參閱了一篇關(guān)于將圖像轉(zhuǎn)化為ASCII的文章之后,Bryan將耐克和蘋果的logo轉(zhuǎn)化了出來(不建議轉(zhuǎn)化迪士尼的logo)。
小哥本人也是老二次元了,《Bad Apple》也是信手拈來:
隨后,自嘲“the CheckBox guy”的小哥賦予了復(fù)選框更多的可能,他又拓展了Checkboxland API,用來加載任何視頻并生成復(fù)選框版本。
下面這個(gè)看起來就像進(jìn)入了《星際穿越》的五維立方體。
而此刻你如果打開攝像頭,Bryan還可以帶領(lǐng)你半只腳踏進(jìn)《黑客帝國》~
趕快學(xué)起來,說不定還能用來畫心形圖,成為你的表白神器(不是)!
看似炫酷的效果實(shí)際制作過程只需分為兩大步,手把手教你!
1.做出原本的圖像。
2.將圖像轉(zhuǎn)化為ASCII文本輸出。
以水波為例,首先要生成這樣動(dòng)態(tài)的水波。
想要生成它,需要以中心為原點(diǎn),在xy平面上建立正弦函數(shù)。
z軸垂直屏幕向外,把z軸的數(shù)值轉(zhuǎn)化為灰度,白色為波峰,黑色為波谷。
然后在圖形計(jì)算器desmos上讓水波動(dòng)起來,這樣第一步就完成了。
第二步,將第一步的成果轉(zhuǎn)化為ASCII碼輸出。
這一步的轉(zhuǎn)化主要涉及到將彩色對(duì)應(yīng)灰度。
采用這個(gè)公式,即使是彩色的圖片,也只不過是五彩斑斕的灰罷了~
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;
};
然后為每個(gè)像素賦灰度值:
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;
};
最后調(diào)整一下圖片大小就大功告成了~更多詳細(xì)內(nèi)容見文后鏈接~
在最近的更新中,Bryan稱,他創(chuàng)造新天地的事情將暫時(shí)告一段落。
但是他不僅留下了復(fù)選框新玩法原理的詳細(xì)介紹,還有自制的豐富的demos。這些足以讓你探索創(chuàng)造。
簡(jiǎn)單的動(dòng)畫,貪吃蛇,通過攝像頭實(shí)時(shí)生成復(fù)選框版圖像(demos中的webcam)…
點(diǎn)擊即可試玩,以貪吃蛇和webcam為例:
點(diǎn)擊snake,鍵盤上下左右即可控制貪吃蛇:
點(diǎn)擊webcam,打開前置攝像頭,可以看到自己的實(shí)時(shí)動(dòng)態(tài):
根據(jù)網(wǎng)友的反饋,似乎在安卓系統(tǒng)中打開會(huì)白屏,但是在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 · 頭條號(hào)簽約
關(guān)注我們,第一時(shí)間獲知前沿科技動(dòng)態(tài)
家好,今天我們將一起學(xué)習(xí)下如何從零開始創(chuàng)建一個(gè)具有縮略圖功能的響應(yīng)式幻燈片。這個(gè)案例我們無需編寫任何 JavaScript 代碼,這里主要運(yùn)用了 CSS checkbox hack 的技術(shù)進(jìn)行實(shí)現(xiàn)。
這篇文章運(yùn)用了復(fù)雜的CSS選擇器、flex box 和 Grid 布局、 CSS checkbox 的偽類選擇器 checked 等技術(shù)
如視頻所示,一個(gè)功能完備漂亮的幻燈片圖片組件。
<script src="https://lf6-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>
1、首先我們準(zhǔn)備3張圖片素材。
2、接下來我們新建3個(gè)radio按鈕,通過name屬性進(jìn)行按鈕分組
<input type="radio" id="image1" name="image" checked>
<input type="radio" id="image2" name="image">
<input type="radio" id="image3" name="image">
3、然后我們創(chuàng)建 .featured-wrapper 和 .thumb-list 兩個(gè)容器,放置內(nèi)容元素
3.1、.featured-wrapper 元素包含3個(gè)列表:
1、一個(gè)大圖列表,一次只能顯示一個(gè)圖片
2、一組箭頭列表,用于大圖切換
3、一組圓圈列表,用于大圖切換
這里我們使用label標(biāo)簽技巧與radio表單進(jìn)行對(duì)應(yīng)代替JS事件點(diǎn)擊,同一個(gè) radio 可以關(guān)聯(lián)多個(gè)與之對(duì)應(yīng)的 label 標(biāo)簽。
3.2、.thumb-list 容器包含一組圖片縮略圖,與大圖對(duì)應(yīng),用于切換大圖。
總而言之,我們說了這么多,我們可以通過箭頭、圈圈、縮略圖進(jìn)行幻燈大圖的切換,整體的 HTML 結(jié)構(gòu)如下圖所示:
基于上圖所示,最終完成的 HTML 代碼結(jié)構(gòu)如下:
<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;
}
這里你會(huì)注意到,我使用了bottom: 0,主要為了防止每次點(diǎn)擊標(biāo)簽時(shí),瀏覽器跳至頁面頂部。雖然不是最佳實(shí)踐,但是這個(gè)方法對(duì)本案例有效,還有一個(gè)更好的做法,我們可以設(shè)置display: none,但是不符合鍵盤可訪問性(accessibility)的標(biāo)準(zhǔn),這里還是推薦 bottom: 0;
2、定義最外層 container 容器的樣式,設(shè)置最大寬度以及讓其水平居中
.container {
max-width: 450px;
padding: 0 20px;
margin: 0 auto;
}
3、定義大圖列表樣式
為了只顯示一張大圖,其他圖片將會(huì)被蓋住并且隱藏,你可能最先想到的是改變文檔正常流,使用position屬性進(jìn)行定位的方法進(jìn)行隱藏,這里你需要注意圖片的寬高比,通常使用固定高度的解決方案,在這個(gè)案例中,我們使用CSS的Grid新布局,將圖片放置在1行1列的單元網(wǎng)格中,示例如下圖所示:
與上圖對(duì)應(yīng)的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 容器底部,點(diǎn)擊相應(yīng)圓圈進(jìn)行切換大圖:
相應(yīng)的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、定義箭頭樣式
接下來我們繼續(xù)定義箭頭切換的樣式,我們將其放置在.featured-wrapper容器,如下圖所示:
這里需要注意的是,這些箭頭與 radio 按鈕一一對(duì)應(yīng)關(guān)聯(lián),這里我們用到了::before 和 ::after偽元素創(chuàng)建圓形元素,示例代碼如下:
/*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、定義縮略圖元素樣式
每個(gè)縮略圖占據(jù)父容器的三分之一,如下圖所示:
在這里,為了將圖片標(biāo)題放置在圖片之上,我們用的不是傳統(tǒng)的CSS定位,這里我們應(yīng)用了CSS Grid技巧。
我們將每個(gè)縮略圖變成單一網(wǎng)格(一行一列),并使用grid垂直居中的技巧 place-items: center 讓文本垂直居中,相關(guān)代碼如下所示:
.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 的技術(shù)模擬JS的點(diǎn)擊事件。
每次點(diǎn)擊縮略圖,相應(yīng)的箭頭和圓圈都會(huì)處于活動(dòng)狀態(tài):
基于以上需求最終完成的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;
}
最終的效果體驗(yàn),大家可以點(diǎn)擊文末了解更多鏈接進(jìn)行體驗(yàn),由于文章篇幅有限,完整的源碼大家可以私信“幻燈片”獲取下載鏈接。
到此我們完成了本案例,通過本案例,我相信你對(duì) CSS checkbox hack 技術(shù)有了更清楚的認(rèn)識(shí),希望你能夠適應(yīng)這項(xiàng)技術(shù),并將其運(yùn)用到自己的項(xiàng)目中。
動(dòng)手練一練,做一個(gè)現(xiàn)代化、響應(yīng)式的后臺(tái)管理首頁
使用 Vanilla JavaScript 框架創(chuàng)建一個(gè)簡(jiǎn)單的天氣應(yīng)用
動(dòng)手練一練,使用 Flexbox 創(chuàng)建一個(gè)響應(yīng)式的表單
動(dòng)手練一練,用純 CSS 制作一款側(cè)滑顯示留言面板的網(wǎng)頁組件
使用 CSS Checkbox Hack 技術(shù)制作一個(gè)手風(fēng)琴組件
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。