Ringkasan dasar tentang cara membuat komponen tab yang mirip dengan yang ada di aplikasi iOS dan Android.
Dalam postingan ini, saya ingin berbagi pemikiran tentang cara membuat komponen Tab untuk web yang responsif, mendukung beberapa input perangkat, dan berfungsi di seluruh browser. Coba demo.
Jika Anda lebih suka menonton video, berikut versi YouTube dari postingan ini:
Ringkasan
Tab adalah komponen umum sistem desain, tetapi dapat memiliki banyak bentuk dan
format. Pertama, ada tab desktop yang dibuat pada elemen <frame>
, dan sekarang kita memiliki komponen seluler yang lancar yang menganimasikan konten berdasarkan properti fisika.
Semuanya mencoba melakukan hal yang sama: menghemat ruang.
Saat ini, elemen penting dari pengalaman pengguna tab adalah area navigasi tombol yang mengalihkan visibilitas konten dalam frame tampilan. Banyak area konten yang berbeda berbagi ruang yang sama, tetapi ditampilkan secara bersyarat berdasarkan tombol yang dipilih di navigasi.

Taktik Web
Secara keseluruhan, saya merasa komponen ini cukup mudah dibuat, berkat beberapa fitur platform web penting:
scroll-snap-points
untuk interaksi geser dan keyboard yang elegan dengan posisi penghentian scroll yang sesuai- Deep link melalui hash URL untuk browser yang menangani dukungan berbagi dan penautan scroll dalam halaman
- Dukungan pembaca layar dengan markup elemen
<a>
danid="#hash"
prefers-reduced-motion
untuk mengaktifkan transisi crossfade dan scroll dalam halaman instan- Fitur web
@scroll-timeline
dalam draf untuk menggarisbawahi dan mengubah warna tab yang dipilih secara dinamis
HTML
Pada dasarnya, UX di sini adalah: klik link, buat URL merepresentasikan status halaman bertingkat, lalu lihat area konten diperbarui saat browser men-scroll ke elemen yang cocok.
Ada beberapa anggota konten struktural di sana: link dan :target
. Kita memerlukan daftar link, yang sangat cocok untuk <nav>
, dan daftar elemen <article>
, yang sangat cocok untuk <section>
. Setiap hash link akan cocok dengan bagian,
sehingga browser dapat men-scroll item melalui penautan.
Misalnya, mengklik link akan otomatis memfokuskan artikel :target
di
Chrome 89, tanpa memerlukan JS. Pengguna kemudian dapat men-scroll konten artikel dengan perangkat input seperti biasa. Konten ini adalah konten pelengkap, seperti yang ditunjukkan dalam markup.
Saya menggunakan markup berikut untuk mengatur tab:
<snap-tabs>
<header>
<nav>
<a></a>
<a></a>
<a></a>
<a></a>
</nav>
</header>
<section>
<article></article>
<article></article>
<article></article>
<article></article>
</section>
</snap-tabs>
Saya dapat membuat hubungan antara elemen <a>
dan <article>
dengan
properti href
dan id
seperti ini:
<snap-tabs>
<header>
<nav>
<a href="#responsive"></a>
<a href="#accessible"></a>
<a href="#overscroll"></a>
<a href="#more"></a>
</nav>
</header>
<section>
<article id="responsive"></article>
<article id="accessible"></article>
<article id="overscroll"></article>
<article id="more"></article>
</section>
</snap-tabs>
Selanjutnya, saya mengisi artikel dengan jumlah lorem yang bervariasi, dan link dengan judul yang memiliki panjang dan set gambar yang bervariasi. Dengan konten yang akan digunakan, kita dapat memulai tata letak.
Tata letak scroll
Ada 3 jenis area scroll yang berbeda dalam komponen ini:
- Navigasi (merah muda) dapat di-scroll secara horizontal
- Area konten (biru) dapat di-scroll secara horizontal
- Setiap item artikel (hijau) dapat di-scroll secara vertikal.

Ada 2 jenis elemen berbeda yang terlibat dalam scrolling:
- Jendela
Kotak dengan dimensi yang ditentukan yang memiliki gaya propertioverflow
. - Permukaan yang terlalu besar
Dalam tata letak ini, yang terlalu besar adalah penampung daftar: link navigasi, artikel bagian, dan konten artikel.
Tata letak <snap-tabs>
Tata letak tingkat atas yang saya pilih adalah flex (Flexbox). Saya menetapkan arah ke
column
, sehingga header dan bagian diurutkan secara vertikal. Ini adalah jendela scroll pertama kita, dan menyembunyikan semuanya dengan overflow tersembunyi. Header dan
bagian akan segera menggunakan overscroll, sebagai zona individual.
<snap-tabs> <header></header> <section></section> </snap-tabs>
snap-tabs { display: flex; flex-direction: column; /* establish primary containing box */ overflow: hidden; position: relative; & > section { /* be pushy about consuming all space */ block-size: 100%; } & > header { /* defend againstneeding 100% */ flex-shrink: 0; /* fixes cross browser quarks */ min-block-size: fit-content; } }
Kembali ke diagram 3 scroll berwarna:
<header>
kini siap menjadi penampung scroll (merah muda)<section>
disiapkan untuk menjadi penampung scroll (biru).
Frame yang telah saya tandai di bawah dengan VisBug membantu kita melihat jendela yang telah dibuat oleh penampung scroll.

Tata letak <header>
tab
Tata letak berikutnya hampir sama: Saya menggunakan flex untuk membuat pengurutan vertikal.
<snap-tabs> <header> <nav></nav> <span class="snap-indicator"></span> </header> <section></section> </snap-tabs>
header { display: flex; flex-direction: column; }
.snap-indicator
harus bergerak secara horizontal dengan grup link, dan tata letak header ini membantu menyiapkan tahap tersebut. Tidak ada elemen yang diposisikan secara mutlak di sini.

Selanjutnya, gaya scroll. Ternyata kita dapat membagikan gaya scroll
di antara 2 area scroll horizontal (header dan bagian), jadi saya membuat class utilitas, .scroll-snap-x
.
.scroll-snap-x {
/* browser decide if x is ok to scroll and show bars on, y hidden */
overflow: auto hidden;
/* prevent scroll chaining on x scroll */
overscroll-behavior-x: contain;
/* scrolling should snap children on x */
scroll-snap-type: x mandatory;
@media (hover: none) {
scrollbar-width: none;
&::-webkit-scrollbar {
width: 0;
height: 0;
}
}
}
Setiap elemen memerlukan overflow pada sumbu x, penampungan scroll untuk menjebak overscroll, scrollbar tersembunyi untuk perangkat sentuh, dan terakhir scroll-snap untuk mengunci area presentasi konten. Urutan tab keyboard kami dapat diakses dan interaksi apa pun memandu fokus secara alami. Penampung paskan scroll juga mendapatkan interaksi gaya carousel yang bagus dari keyboard.
Tata letak header tab <nav>
Link nav harus disusun dalam satu baris, tanpa jeda baris, ditengahkan secara vertikal, dan setiap item link harus di-snap ke penampung scroll-snap. Swift work for 2021 CSS!
<nav> <a></a> <a></a> <a></a> <a></a> </nav>
nav { display: flex; & a { scroll-snap-align: start; display: inline-flex; align-items: center; white-space: nowrap; } }
Setiap link menata dan mengukur dirinya sendiri, sehingga tata letak nav hanya perlu menentukan arah dan alur. Lebar unik pada item nav membuat transisi antar-tab menjadi menyenangkan karena indikator menyesuaikan lebarnya ke target baru. Bergantung pada jumlah elemen di sini, browser akan merender scrollbar atau tidak.

Tata letak <section>
tab
Bagian ini adalah item fleksibel dan harus menjadi konsumen ruang yang dominan. Selain itu, kolom juga perlu dibuat untuk menempatkan artikel. Sekali lagi, kerja
cepat untuk CSS 2021! block-size: 100%
meregangkan elemen ini untuk mengisi
induk sebanyak mungkin, lalu untuk tata letaknya sendiri, ia membuat serangkaian
kolom yang 100%
lebarnya sama dengan induk. Persentase berfungsi dengan baik di sini
karena kita telah menulis batasan yang kuat pada induk.
<section> <article></article> <article></article> <article></article> <article></article> </section>
section { block-size: 100%; display: grid; grid-auto-flow: column; grid-auto-columns: 100%; }
Seolah-olah kita mengatakan "luaskan secara vertikal sebanyak mungkin, dengan cara yang memaksa"
(ingat header yang kita tetapkan ke flex-shrink: 0
: ini adalah pertahanan terhadap dorongan
perluasan ini), yang menetapkan tinggi baris untuk sekumpulan kolom tinggi penuh. Gaya
auto-flow
memberi tahu petak untuk selalu menata turunan dalam baris
horizontal, tanpa wrapping, persis seperti yang kita inginkan; untuk meluap dari jendela induk.

Terkadang, saya merasa sulit memahami hal ini. Elemen bagian ini muat dalam kotak, tetapi juga membuat sekumpulan kotak. Semoga visualisasi dan penjelasan ini membantu.
Tata letak <article>
tab
Pengguna harus dapat men-scroll konten artikel, dan scrollbar hanya akan muncul jika ada konten yang meluap. Elemen artikel ini berada di posisi yang rapi. Mereka secara bersamaan adalah induk scroll dan turunan scroll. Browser benar-benar menangani beberapa interaksi sentuh, mouse, dan keyboard yang rumit untuk kita di sini.
<article> <h2></h2> <p></p> <p></p> <h2></h2> <p></p> <p></p> ... </article>
article { scroll-snap-align: start; overflow-y: auto; overscroll-behavior-y: contain; }
Saya memilih agar artikel terpasang dalam scroller induknya. Saya sangat menyukai cara item link navigasi dan elemen artikel di-snap ke inline-start dari masing-masing penampung scroll. Terlihat dan terasa seperti hubungan yang harmonis.

Artikel adalah turunan petak, dan ukurannya telah ditentukan sebelumnya sebagai area viewport yang ingin kita berikan UX scroll. Artinya, saya tidak memerlukan gaya tinggi atau lebar di sini, saya hanya perlu menentukan cara meluapnya. Saya menyetel overflow-y ke auto, lalu juga menjebak interaksi scroll dengan properti overscroll-behavior yang praktis.
Ringkasan 3 area scroll
Di bawah, saya telah memilih di setelan sistem saya untuk "selalu menampilkan scrollbar". Menurut saya, tata letak harus berfungsi dengan setelan ini diaktifkan, karena saya harus meninjau tata letak dan orkestrasi scroll.

Saya rasa melihat gutter scrollbar dalam komponen ini membantu menunjukkan dengan jelas di mana area scroll berada, arah yang didukung, dan cara berinteraksi satu sama lain. Pertimbangkan bagaimana setiap frame jendela scroll ini juga merupakan induk flex atau petak untuk tata letak.
DevTools dapat membantu kita memvisualisasikannya:

Tata letak scroll sudah selesai: menyematkan, dapat di-deep link, dan dapat diakses dengan keyboard. Fondasi yang kuat untuk peningkatan UX, gaya, dan kesenangan.
Sorotan fitur
Turunan yang di-scroll dan disesuaikan mempertahankan posisi terkuncinya selama pengubahan ukuran. Artinya, JavaScript tidak perlu menampilkan apa pun saat perangkat diputar atau ukuran browser diubah. Coba di Mode Perangkat Chromium DevTools dengan memilih mode selain Responsif, lalu mengubah ukuran frame perangkat. Perhatikan bahwa elemen tetap terlihat dan dikunci dengan kontennya. Fitur ini telah tersedia sejak Chromium memperbarui implementasinya agar sesuai dengan spesifikasi. Berikut postingan blog tentang fitur ini.
Animasi
Tujuan pekerjaan animasi di sini adalah untuk menghubungkan interaksi dengan masukan UI secara jelas. Hal ini membantu memandu atau membantu pengguna menemukan semua konten dengan lancar (semoga). Saya akan menambahkan gerakan dengan tujuan dan secara bersyarat. Pengguna kini dapat menentukan preferensi gerakan mereka di sistem operasi mereka, dan saya sangat senang merespons preferensi mereka di antarmuka saya.
Saya akan menautkan garis bawah tab dengan posisi scroll artikel. Penyelarasan bukan hanya untuk tampilan yang bagus, tetapi juga untuk menyematkan awal dan akhir animasi.
Hal ini membuat <nav>
, yang berfungsi seperti
peta mini, tetap terhubung ke konten.
Kita akan memeriksa preferensi gerakan pengguna dari CSS dan JS. Ada beberapa tempat yang tepat untuk menunjukkan perhatian.
Perilaku scroll
Ada peluang untuk meningkatkan perilaku gerakan :target
dan
element.scrollIntoView()
. Secara default, prosesnya instan. Browser hanya menetapkan
posisi scroll. Nah, bagaimana jika kita ingin bertransisi ke posisi scroll tersebut, bukan berkedip di sana?
@media (prefers-reduced-motion: no-preference) {
.scroll-snap-x {
scroll-behavior: smooth;
}
}
Karena kita memperkenalkan gerakan di sini, dan gerakan yang tidak dikontrol pengguna (seperti men-scroll), kita hanya menerapkan gaya ini jika pengguna tidak memiliki preferensi di sistem operasinya terkait gerakan yang dikurangi. Dengan cara ini, kita hanya memperkenalkan gerakan scroll untuk orang-orang yang tidak mempermasalahkannya.
Indikator tab
Tujuan animasi ini adalah untuk membantu mengaitkan indikator dengan status konten. Saya memutuskan untuk memudarkan silang gaya border-bottom
warna bagi pengguna yang lebih memilih gerakan yang dikurangi, dan animasi geser + pudar warna yang terkait dengan scroll bagi pengguna yang tidak masalah dengan gerakan.
Di DevTools Chromium, saya dapat mengganti preferensi dan mendemonstrasikan 2 gaya transisi yang berbeda. Saya sangat menikmati proses pembuatannya.
@media (prefers-reduced-motion: reduce) {
snap-tabs > header a {
border-block-end: var(--indicator-size) solid hsl(var(--accent) / 0%);
transition: color .7s ease, border-color .5s ease;
&:is(:target,:active,[active]) {
color: var(--text-active-color);
border-block-end-color: hsl(var(--accent));
}
}
snap-tabs .snap-indicator {
visibility: hidden;
}
}
Saya menyembunyikan .snap-indicator
saat pengguna memilih gerakan yang dikurangi karena saya tidak
memerlukannya lagi. Kemudian, saya menggantinya dengan gaya border-block-end
dan
transition
. Perhatikan juga pada interaksi tab bahwa item nav aktif tidak hanya memiliki sorotan garis bawah merek, tetapi warna teksnya juga lebih gelap. Elemen
aktif memiliki kontras warna teks yang lebih tinggi dan aksen cahaya bawah yang cerah.
Hanya dengan beberapa baris CSS tambahan, seseorang akan merasa diperhatikan (dalam arti kita menghormati preferensi gerakan mereka dengan cermat). Saya suka.
@scroll-timeline
Di bagian di atas, saya menunjukkan cara menangani gaya crossfade gerakan yang dikurangi, dan di bagian ini, saya akan menunjukkan cara menautkan indikator dan area scroll. Berikutnya akan ada beberapa hal eksperimental yang menyenangkan. Saya harap Anda juga bersemangat seperti saya.
const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
);
Pertama, saya memeriksa preferensi gerakan pengguna dari JavaScript. Jika hasilnya adalah false
, yang berarti pengguna lebih memilih gerakan yang dikurangi, maka kita tidak akan menjalankan efek gerakan penautan scroll apa pun.
if (motionOK) {
// motion based animation code
}
Saat artikel ini ditulis, tidak ada dukungan browser untuk
@scroll-timeline
. Ini adalah
spesifikasi draf dengan hanya
implementasi eksperimental. Namun, ada polyfill yang saya gunakan dalam demo ini.
ScrollTimeline
Meskipun CSS dan JavaScript dapat membuat linimasa scroll, saya memilih JavaScript agar dapat menggunakan pengukuran elemen langsung dalam animasi.
const sectionScrollTimeline = new ScrollTimeline({
scrollSource: tabsection, // snap-tabs > section
orientation: 'inline', // scroll in the direction letters flow
fill: 'both', // bi-directional linking
});
Saya ingin 1 hal mengikuti posisi scroll hal lain, dan dengan membuat
ScrollTimeline
, saya menentukan pendorong link scroll, yaitu scrollSource
.
Biasanya, animasi di web berjalan berdasarkan tanda waktu global, tetapi dengan
sectionScrollTimeline
kustom dalam memori, saya dapat mengubah semuanya.
tabindicator.animate({
transform: ...,
width: ...,
}, {
duration: 1000,
fill: 'both',
timeline: sectionScrollTimeline,
}
);
Sebelum membahas keyframe animasi, menurut saya penting untuk menunjukkan bahwa pengikut scroll, tabindicator
, akan dianimasikan berdasarkan linimasa kustom, yaitu scroll bagian kita. Hal ini melengkapi penautan, tetapi
tidak memiliki bahan akhir, titik stateful untuk dianimasikan di antaranya, yang juga dikenal sebagai
frame utama.
Keyframe dinamis
Ada cara CSS deklaratif murni yang sangat efektif untuk membuat animasi dengan
@scroll-timeline
, tetapi animasi yang saya pilih terlalu dinamis. Tidak ada cara untuk bertransisi antara lebar auto
, dan tidak ada cara untuk membuat sejumlah frame utama secara dinamis berdasarkan panjang anak.
Namun, JavaScript tahu cara mendapatkan informasi tersebut, jadi kita akan mengulangi sendiri elemen turunan dan mengambil nilai yang dihitung saat runtime:
tabindicator.animate({
transform: [...tabnavitems].map(({offsetLeft}) =>
`translateX(${offsetLeft}px)`),
width: [...tabnavitems].map(({offsetWidth}) =>
`${offsetWidth}px`)
}, {
duration: 1000,
fill: 'both',
timeline: sectionScrollTimeline,
}
);
Untuk setiap tabnavitem
, lakukan destrukturisasi posisi offsetLeft
dan tampilkan string
yang menggunakannya sebagai nilai translateX
. Tindakan ini akan membuat 4 keyframe transformasi untuk
animasi. Hal yang sama dilakukan untuk lebar, masing-masing ditanya berapa lebar dinamisnya
lalu digunakan sebagai nilai keyframe.
Berikut contoh output, berdasarkan preferensi font dan browser saya:
Frame Utama TranslateX:
[...tabnavitems].map(({offsetLeft}) =>
`translateX(${offsetLeft}px)`)
// results in 4 array items, which represent 4 keyframe states
// ["translateX(0px)", "translateX(121px)", "translateX(238px)", "translateX(464px)"]
Keyframe Lebar:
[...tabnavitems].map(({offsetWidth}) =>
`${offsetWidth}px`)
// results in 4 array items, which represent 4 keyframe states
// ["121px", "117px", "226px", "67px"]
Untuk meringkas strategi, indikator tab kini akan dianimasikan di 4 frame utama bergantung pada posisi paskan scroll dari peng-scroll bagian. Titik penempelan menciptakan batas yang jelas antara keyframe kita dan benar-benar menambah rasa sinkronisasi animasi.

Pengguna menggerakkan animasi dengan interaksinya, melihat lebar dan posisi indikator berubah dari satu bagian ke bagian berikutnya, yang dilacak dengan sempurna saat men-scroll.
Anda mungkin tidak menyadarinya, tetapi saya sangat bangga dengan transisi warna saat item navigasi yang ditandai dipilih.
Abu-abu muda yang tidak dipilih tampak lebih mundur saat item yang disorot memiliki lebih banyak kontras. Transisi warna untuk teks sering digunakan, seperti saat mengarahkan kursor dan saat dipilih, tetapi transisi warna saat men-scroll, yang disinkronkan dengan indikator garis bawah, adalah hal yang lebih canggih.
Berikut cara saya melakukannya:
tabnavitems.forEach(navitem => {
navitem.animate({
color: [...tabnavitems].map(item =>
item === navitem
? `var(--text-active-color)`
: `var(--text-color)`)
}, {
duration: 1000,
fill: 'both',
timeline: sectionScrollTimeline,
}
);
});
Setiap link navigasi tab memerlukan animasi warna baru ini, yang melacak linimasa scroll yang sama dengan indikator garis bawah. Saya menggunakan linimasa yang sama seperti sebelumnya: karena perannya adalah memancarkan tanda centang saat men-scroll, kita dapat menggunakan tanda centang tersebut dalam jenis animasi apa pun yang kita inginkan. Seperti sebelumnya, saya membuat 4 keyframe dalam loop, dan menampilkan warna.
[...tabnavitems].map(item =>
item === navitem
? `var(--text-active-color)`
: `var(--text-color)`)
// results in 4 array items, which represent 4 keyframe states
// [
"var(--text-active-color)",
"var(--text-color)",
"var(--text-color)",
"var(--text-color)",
]
Keyframe dengan warna var(--text-active-color)
menandai link, dan
jika tidak, warna teksnya adalah warna standar. Loop bertingkat di sana membuatnya relatif
sederhana, karena loop luar adalah setiap item nav, dan loop dalam adalah setiap
keyframe pribadi navitem. Saya memeriksa apakah elemen loop luar sama dengan elemen loop dalam, dan menggunakannya untuk mengetahui kapan elemen tersebut dipilih.
Saya sangat menikmati proses penulisan ini. Banyak.
Peningkatan JavaScript lainnya
Perlu diingat bahwa inti dari apa yang saya tunjukkan di sini berfungsi tanpa JavaScript. Dengan demikian, mari kita lihat cara meningkatkannya saat JS tersedia.
Deep link
Deep link lebih merupakan istilah seluler, tetapi menurut saya maksud deep link di sini terpenuhi dengan tab karena Anda dapat membagikan URL langsung ke konten tab. Browser akan melakukan navigasi dalam halaman ke ID yang cocok di hash URL. Saya menemukan handler onload
ini membuat efek di seluruh platform.
window.onload = () => {
if (location.hash) {
tabsection.scrollLeft = document
.querySelector(location.hash)
.offsetLeft;
}
}
Sinkronisasi akhir scroll
Pengguna kami tidak selalu mengklik atau menggunakan keyboard, terkadang mereka hanya men-scroll bebas, seperti yang seharusnya dapat mereka lakukan. Saat penggeser bagian berhenti menggulir, di mana pun posisinya harus cocok dengan posisi di panel navigasi atas.
Berikut cara saya menunggu akhir scroll:
js
tabsection.addEventListener('scroll', () => {
clearTimeout(tabsection.scrollEndTimer);
tabsection.scrollEndTimer = setTimeout(determineActiveTabSection, 100);
});
Setiap kali bagian di-scroll, hapus waktu tunggu bagian jika ada, dan mulai yang baru. Saat bagian berhenti di-scroll, jangan hapus waktu tunggu, dan aktifkan 100 md setelah berhenti. Saat diaktifkan, panggil fungsi yang berupaya mencari tahu tempat pengguna berhenti.
const determineActiveTabSection = () => {
const i = tabsection.scrollLeft / tabsection.clientWidth;
const matchingNavItem = tabnavitems[i];
matchingNavItem && setActiveTab(matchingNavItem);
};
Dengan asumsi scroll di-snap, membagi posisi scroll saat ini dari lebar area scroll akan menghasilkan bilangan bulat, bukan desimal. Kemudian, saya mencoba mengambil item nav dari cache kita melalui indeks yang dihitung ini, dan jika menemukan sesuatu, saya mengirimkan kecocokan untuk ditetapkan sebagai aktif.
const setActiveTab = tabbtn => {
tabnav
.querySelector(':scope a[active]')
.removeAttribute('active');
tabbtn.setAttribute('active', '');
tabbtn.scrollIntoView();
};
Menetapkan tab aktif dimulai dengan menghapus tab yang saat ini aktif, lalu memberikan
atribut status aktif pada item nav yang masuk. Panggilan ke scrollIntoView()
memiliki interaksi yang menyenangkan dengan CSS yang patut diperhatikan.
.scroll-snap-x {
overflow: auto hidden;
overscroll-behavior-x: contain;
scroll-snap-type: x mandatory;
@media (prefers-reduced-motion: no-preference) {
scroll-behavior: smooth;
}
}
Di CSS utilitas pensesuaian scroll horizontal, kita telah
menyematkan kueri media yang menerapkan
scroll smooth
jika pengguna toleran terhadap gerakan. JavaScript dapat dengan bebas melakukan
panggilan untuk men-scroll elemen agar terlihat, dan CSS dapat mengelola UX secara deklaratif.
Terkadang mereka menciptakan kecocokan kecil yang menyenangkan.
Kesimpulan
Sekarang setelah Anda tahu cara saya melakukannya, bagaimana Anda?! Hal ini menghasilkan arsitektur komponen yang menarik. Siapa yang akan membuat versi pertama dengan slot di framework favorit mereka? 🙂
Mari kita diversifikasi pendekatan kita dan pelajari semua cara untuk membangun di web. Buat Glitch, tweet versi Anda kepada saya, dan saya akan menambahkannya ke bagian Remix komunitas di bawah.
Remix komunitas
- @devnook, @rob_dodson, dan @DasSurma dengan Web Components: artikel.
- @jhvanderschee dengan tombol: Codepen.