我們今天要來做幾份漢堡選單。

原理和 Day14 今天我想來點… 純 CSS 的開關 一樣,都是用 inputcheckbox 來儲存狀態好讓其他元素可以抓到。而他本身的狀態使用 label 來遠端遙控。

我先不要一次跳太多步驟。這是一個基本還未完成的版面。

1<input type="checkbox" id="menu" />
2<label for="menu">
3    <div></div>
4    <div></div>
5    <div></div>
6    <span class="cover"></span>
7</label>
1label {
2    width: 3rem;
3    height: 3rem;
4    background: #00c3ff;
5    display: block;
6    border-radius: 50%;
7    display: flex;
8    flex-direction: column;
9    align-items: center;
10    justify-content: center;
11    gap: 0.25em;
12    position: relative;
13}
14
15label div {
16    width: 1.5rem;
17    height: 0.25rem;
18    background: #fff;
19    border-radius: 0.25rem;
20}
21.cover {
22    position: absolute;
23    display: block;
24    top: 50%;
25    left: 50%;
26    transform: translate(-50%, -50%);
27    width: 100vmax;
28    height: 100vmax;
29    border-radius: 50%;
30    background: #80e1ff;
31    z-index: -1;
32}

可以看到我們已經有了漢堡選單的樣子。<label> 使用 flex 來垂直排列並且置中,gap 來設定間距,並設定 position: relative 來讓 position: absolute.cover 可以定位到相同位置。

如果已經看不懂的話可以複習:

藍色圓形我們希望能夠填滿整個畫面,所以我們使用 100vmax 來選擇 vwvh 之間比較大的值,這樣可以確保能夠蓋滿畫面但是長寬還是依樣來保持圓形。你會發現只有蓋住螢幕一半是因為我們把她往左上角移動了一半,所以只有一半的圓形在畫面上。沒關係我們為了安全起見設定大一點。最後使用 z-index 來讓他在最底層。

把原本的勾選框隱藏起來再加上內文。漢堡選單裡面當然就是要放漢堡配料,效果如下

漢堡配料 In
漢堡配料 In

1<input type="checkbox" id="menu" checked />
2<label for="menu">
3    <div></div>
4    <div></div>
5    <div></div>
6    <span class="cover">
7        <ul>
8            <li>麵包</li>
9            <li>肉排</li>
10            <li>青菜</li>
11            <li>麵包</li>
12        </ul>
13    </span>
14</label>
1body {
2    overflow: hidden;
3    font-family: system-ui;
4}
5input[type="checkbox"] {
6    display: none;
7}
8label {
9    width: 3rem;
10    height: 3rem;
11    background: #00c3ff;
12    display: block;
13    border-radius: 50%;
14    display: flex;
15    flex-direction: column;
16    align-items: center;
17    justify-content: center;
18    gap: 0.25em;
19    position: relative;
20    cursor: pointer;
21}
22
23label div {
24    width: 1.5rem;
25    height: 0.25rem;
26    background: #fff;
27    border-radius: 0.25rem;
28    transition: all 0.3s;
29}
30.cover {
31    position: absolute;
32    display: block;
33    top: 50%;
34    left: 50%;
35    transform: translate(-50%, -50%);
36    width: 0;
37    height: 0;
38    border-radius: 50%;
39    background: #80e1ff;
40    z-index: -1;
41    transition: all 0.3s;
42    overflow: hidden;
43}
44input:checked ~ label > .cover {
45    width: 250vmax;
46    height: 250vmax;
47    border-radius: 50%;
48}
49
50ul {
51    position: absolute;
52    top: 50%;
53    left: 50%;
54    width: 100vw;
55    color: #fff;
56    font-size: 3em;
57    list-style: none;
58    font-weight: 700;
59}

最後是漢堡動畫,這裡就要發揮你自己的創意了。原理不難,這裡提供一個我現在想到的做法。我想要最上面的和最下面的旋轉 45 度,中間的變短到消失。所以我們先把中間的設定 width: 0; height: 0; ,然後我們把最上面的和最下面的設定 transform: rotate(45deg);,這樣就會旋轉 45 度了。這樣能夠做出一個箭頭:

箭頭
箭頭

1input:checked ~ label > div:first-child {
2    transform: rotate(-45deg);
3}
4input:checked ~ label > div:nth-child(2) {
5    width: 0;
6}
7input:checked ~ label > div:nth-child(3) {
8    transform: rotate(45deg);
9}

再來做一個也很常見的打叉,為了方便我們乾脆全部使用 absolute 定位。成果如下:

https://codepen.io/edit-mr/pen/zYyyEgz

打叉
打叉

1body {
2    overflow: hidden;
3    font-family: system-ui;
4}
5input[type="checkbox"] {
6    display: none;
7}
8label {
9    width: 3rem;
10    height: 3rem;
11    background: #00c3ff;
12    display: block;
13    border-radius: 50%;
14    position: relative;
15    cursor: pointer;
16}
17
18label div {
19    position: absolute;
20    width: 1.5rem;
21    height: 0.25rem;
22    background: #fff;
23    border-radius: 0.25rem;
24    transition: all 0.3s;
25    top: 50%;
26    left: 50%;
27    transform: translate(-50%, -50%);
28}
29.cover {
30    position: absolute;
31    display: block;
32    top: 50%;
33    left: 50%;
34    transform: translate(-50%, -50%);
35    width: 0;
36    height: 0;
37    border-radius: 50%;
38    background: #80e1ff;
39    z-index: -1;
40    transition: all 0.3s;
41    overflow: hidden;
42}
43input:checked ~ label > .cover {
44    width: 250vmax;
45    height: 250vmax;
46    border-radius: 50%;
47}
48
49ul {
50    position: absolute;
51    top: 50%;
52    left: 50%;
53    width: 100vw;
54    color: #fff;
55    font-size: 3em;
56    list-style: none;
57    font-weight: 700;
58}
59input:checked ~ label div:first-child {
60    left: 25%;
61    top: 50%;
62    transform: rotate(45deg);
63}
64input:checked ~ label div:nth-child(2) {
65    width: 0;
66}
67input:checked ~ label div:nth-child(3) {
68    left: 25%;
69    top: 50%;
70    transform: rotate(-45deg);
71}
72label > div:first-child {
73    top: calc(50% - 0.5rem);
74}
75label > div:nth-child(3) {
76    top: calc(50% + 0.5rem);
77}

你以為這樣就結束了?還記得我們昨天講的 Day24 CSS 相融黏滯效果 嗎?我們可以把他加上去讓他更有質感。

這是一個會四處噴射漢堡選單

發射漢堡選單
發射漢堡選單

1<input type="checkbox" id="menu" checked />
2<label for="menu">
3    <div>🥩</div>
4    <div>🥬</div>
5    <div>🧀</div>
6    🍔
7</label>
1body {
2    overflow: hidden;
3    font-family: system-ui;
4}
5
6input[type="checkbox"] {
7    display: none;
8}
9
10label {
11    width: 5rem;
12    height: 5rem;
13    background: #00c3ff;
14    display: block;
15    border-radius: 50%;
16    position: relative;
17    cursor: pointer;
18    margin: 1em auto;
19}
20
21div {
22    position: absolute;
23    top: 50%;
24    left: 50%;
25    transform: translate(-50%, -50%);
26    width: 3rem;
27    height: 3rem;
28    border-radius: 50%;
29    background: #00c3ff;
30    z-index: -1;
31    transition: all 0.3s;
32    overflow: hidden;
33}
34
35input:checked ~ label > div:nth-child(1) {
36    left: calc(50% - 5rem);
37}
38
39input:checked ~ label > div:nth-child(2) {
40    top: calc(50% + 5rem);
41}
42input:checked ~ label > div:nth-child(3) {
43    left: calc(50% + 5rem);
44}
45
46label,
47div {
48    display: flex;
49    align-items: center;
50    justify-content: center;
51    font-size: 2.5rem;
52    user-select: none;
53}
54
55div {
56    font-size: 1.5rem;
57}

user-select: none; 可以讓使用者無法選取文字,這樣就不會在點擊時有文字被選取的問題了。

加上昨天的相黏效果,變得更可愛了。

https://codepen.io/edit-mr/pen/NWeeYRq

相黏效果
相黏效果

1body {
2    overflow: hidden;
3    font-family: system-ui;
4    min-height: 100svh;
5}
6input[type="checkbox"] {
7    display: none;
8}
9label {
10    width: 5rem;
11    height: 5rem;
12    display: block;
13    position: absolute;
14    cursor: pointer;
15    left: 50%;
16    transform: translate(-50%, -50%);
17}
18.box div {
19    width: 4rem;
20    height: 4rem;
21}
22.box div,
23label {
24    top: 50%;
25    border-radius: 50%;
26    background: #00c3ff;
27}
28.box div,
29.food,
30.food div {
31    position: absolute;
32    left: 50%;
33    transform: translate(-50%, -50%);
34    transition: 0.3s;
35}
36input:checked ~ .box div:first-child,
37input:checked ~ .food div:first-child {
38    left: calc(50% - 4rem);
39}
40input:checked ~ .box div:nth-child(2),
41input:checked ~ .food div:nth-child(2) {
42    top: calc(50% + 4rem);
43}
44input:checked ~ .box div:nth-child(3),
45input:checked ~ .food div:nth-child(3) {
46    left: calc(50% + 4rem);
47}
48.box div,
49label {
50    user-select: none;
51    filter: blur(10px);
52}
53.box {
54    background: #fff;
55    filter: contrast(20) hue-rotate(45deg);
56    height: 100svh;
57}
58.food,
59.food div {
60    top: 50.3%;
61    user-select: none;
62    pointer-events: none;
63}
64input:checked ~ .food div {
65    font-size: 1.5rem;
66}
67.food div {
68    font-size: 0rem;
69}
70.food div:last-child {
71    font-size: 2rem;
72}

手機版的淘寶之前有使用過類似的效果製作分享選單喔~

因為相黏效果有先模糊,裡面的 Emoji 文字也會被模糊,所以我們在後面又做一個只有文字的 .food 來顯示文字。設定 pointer-events: none 就可以讓他不會被點擊到了,直接穿透去點擊下面的 label

背景顏色一定要記得設定,不然只會糊再一起沒有相黏效果。這是我 debug 半小時之後才想到的...

以上就是我今天的分享,歡迎在 InstagramGoogle 新聞追蹤毛哥EM資訊密技,也歡迎訂閱我新開的YouTube 頻道:網棧

我是毛哥EM,讓我們明天再見。

毛哥EM

一位喜歡把簡單的事,做得不簡單的高三生。