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 pembuatan komponen Tab untuk web yang responsif, mendukung banyak input perangkat, dan berfungsi di berbagai browser. Coba demo.
Jika Anda lebih suka menonton video, berikut versi YouTube untuk postingan ini:
Ringkasan
{i>Tab <i}adalah komponen umum dari sistem desain tetapi bisa
memiliki banyak bentuk dan
formulir. Pertama, ada tab desktop yang dibuat berdasarkan elemen <frame>
, dan sekarang kita punya
komponen seluler yang menarik yang menganimasikan konten berdasarkan properti fisika.
Mereka semua mencoba melakukan hal yang sama: menghemat ruang.
Saat ini, hal-hal penting dari pengalaman pengguna tab adalah area navigasi tombol yang mengubah visibilitas konten di {i>display frame<i}. Banyak area konten memiliki ruang yang sama, tetapi disajikan bersyarat berdasarkan yang dipilih di navigasi.
Taktik Web
Secara keseluruhan, saya menemukan bahwa 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 menangani anchor scroll dalam halaman dan dukungan berbagi
- Dukungan pembaca layar dengan markup elemen
<a>
danid="#hash"
prefers-reduced-motion
untuk mengaktifkan transisi crossfade dan instan scroll dalam halaman- Fitur web
@scroll-timeline
dalam draf untuk memberi garis bawah secara dinamis dan warna mengubah tab yang dipilih
HTML
Pada dasarnya, UX di sini adalah: klik tautan, buat URL mewakili status halaman, lalu lihat area konten diperbarui saat browser men-scroll ke yang sesuai.
Ada beberapa anggota konten struktural di sana: link dan :target
. Rab
memerlukan daftar link, yang cocok untuk <nav>
, dan daftar <article>
elemen yang sangat cocok dengan <section>
. Setiap {i>hash<i} tautan akan
cocok dengan satu bagian,
memungkinkan browser men-scroll berbagai hal melalui anchoring.
Misalnya, mengklik link akan otomatis memfokuskan artikel :target
di
Chrome 89, tanpa JS. Pengguna kemudian dapat men-scroll konten artikel dengan
perangkat input mereka seperti biasa. Konten ini bersifat 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 koneksi 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 beragam, dan tautannya dengan kombinasi panjang dan kumpulan gambar. Dengan konten yang akan dikerjakan, kita bisa mulai tata letak.
Tata letak scroll
Ada 3 jenis area scroll yang berbeda dalam komponen ini:
- Navigasi (pink) secara horizontal dapat di-scroll
- Area konten (biru) berada secara horizontal dapat di-scroll
- Setiap item artikel (hijau) secara vertikal dapat di-scroll.
Ada 2 jenis elemen berbeda yang terlibat dalam scroll:
- Jendela
Kotak dengan dimensi yang ditentukan yang memilikioverflow
gaya properti. - Platform besar
Dalam tata letak ini, yang dimaksud adalah penampung daftar: navigasi tautan, artikel rubrik, dan konten artikel.
Tata letak <snap-tabs>
Tata letak tingkat teratas yang saya pilih adalah {i>flex<i} (Flexbox). saya menetapkan arah ke
column
, sehingga header dan bagian diurutkan secara vertikal. Ini adalah
men-scroll, dan menyembunyikan semua yang overflow. {i>Header<i} dan
akan segera menerapkan 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; } }
Mengarahkan kembali ke diagram 3 scroll penuh warna:
<header>
kini siap menjadi (merah muda) container scroll.<section>
siap menjadi scroll (biru) container.
{i>Frame<i} yang saya soroti di bawah ini dengan VisBug membantu kami melihat jendela yang yang telah dibuat oleh container scroll.
Tata letak tab <header>
Tata letak berikutnya hampir sama: Saya menggunakan {i>flex<i} 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 {i>header<i} ini membantu
mengatur tahap itu. Tidak ada elemen yang diposisikan secara mutlak di sini.
Berikutnya, gaya scroll. Ternyata kita bisa berbagi gaya scroll
di antara 2 area gulir horizontal ({i>header<i} dan bagian) sehingga saya membuat 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;
}
}
}
Masing-masing memerlukan overflow pada sumbu x, scroll containment untuk menjebak overscroll, tersembunyi scrollbar untuk perangkat sentuh dan yang terakhir scroll-snap untuk mengunci konten dan presentasi. Urutan tab keyboard kami dapat diakses dan panduan interaksi apa pun fokus secara alami. Penampung snap scroll juga mendapatkan gaya carousel yang bagus dari {i>keyboard<i} mereka.
Tata letak header tab <nav>
Tautan navigasi harus ditata dalam garis, tanpa pemisah baris, secara vertikal di tengah, dan setiap item tautan harus dipaskan ke kontainer scroll-snap. Swift berfungsi untuk CSS 2021!
<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 gaya dan ukuran tautan itu sendiri, sehingga tata letak navigasi hanya perlu menentukan dengan baik. Lebar unik pada item navigasi membuat transisi antar-tab menyenangkan karena indikator menyesuaikan lebarnya dengan target baru. Tergantung berapa banyak elemen yang ada di sini, browser akan me-render scrollbar atau tidak.
Tata letak tab <section>
Bagian ini adalah item fleksibel dan harus menjadi konsumen ruang yang dominan. Ini
juga perlu membuat kolom untuk
menempatkan artikel. Sekali lagi, cepat
bekerja untuk CSS 2021! block-size: 100%
merentangkan elemen ini untuk mengisi
induk sebanyak mungkin, maka untuk tata
letaknya sendiri, ia membuat serangkaian
kolom yang lebarnya
100%
dari induk. Persentase berfungsi dengan baik di sini
karena kita telah menulis
batasan yang kuat pada induknya.
<section> <article></article> <article></article> <article></article> <article></article> </section>
section { block-size: 100%; display: grid; grid-auto-flow: column; grid-auto-columns: 100%; }
Ini seperti mengatakan "perluas secara vertikal sebanyak mungkin, dengan cara yang memaksa"
(ingatlah header yang kita tetapkan ke flex-shrink: 0
: ini adalah perlindungan terhadap
push ekspansi), yang menetapkan tinggi baris untuk satu set kolom tinggi penuh. Tujuan
Gaya auto-flow
memberi tahu petak untuk selalu meletakkan turunan secara horizontal
{i>line<i}, tanpa {i>wrapping<i}, persis
apa yang kita inginkan; untuk memenuhi jendela induk.
Aku kadang-kadang sulit memahami hal ini! Elemen bagian ini pas ke dalam sebuah kotak, tetapi juga membuat satu set kotak. Saya harap visual dan penjelasan akan sangat membantu.
Tata letak tab <article>
Pengguna harus dapat men-scroll konten artikel, dan scrollbar harus hanya muncul jika ada overflow. Elemen artikel ini ditampilkan dalam posisi Anda. Keduanya merupakan induk scroll dan turunan scroll. Tujuan browser benar-benar menangani beberapa interaksi sentuh, mouse, dan {i>keyboard<i} yang rumit bagi 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; }
Aku memilih untuk memasukkan artikel dalam scroller induk mereka. Saya sangat suka cara item tautan navigasi dan elemen artikel terhubung dengan awalan di penampung scrollnya masing-masing. Terlihat dan terasa seperti harmonis hubungan.
Artikel ini adalah turunan petak, dan ukurannya telah ditentukan sebagai area tampilan area yang ingin kita berikan UX scroll. Ini berarti saya tidak membutuhkan tinggi atau lebar di sini, saya hanya perlu menentukan bagaimana overflow. Saya mengatur {i> overflow-y<i} ke {i>auto<i}, dan juga menjebak interaksi scroll dengan perilaku overscroll yang praktis saat ini.
Rangkuman 3 area scroll
Di bawah ini saya memilih "selalu tampilkan scrollbar" di setelan sistem saya. Sepertinya sangat penting bagi tata letak agar berfungsi dengan mengaktifkan setelan ini, karena adalah langkah untuk meninjau tata letak dan orkestrasi scroll.
Menurut saya, melihat gutter scrollbar di komponen ini membantu menunjukkan dengan jelas di mana area scroll, arah yang didukung, dan cara area tersebut berinteraksi sama lain. Pertimbangkan bagaimana setiap bingkai jendela {i>scroll<i} ini lentur atau induk petak ke tata letak.
DevTools dapat membantu kita memvisualisasikan ini:
Tata letak scroll sudah lengkap: snapping, deep linkable, dan keyboard dapat diakses. Fondasi yang kuat untuk peningkatan, gaya, dan kesenangan UX.
Sorotan fitur
Scroll yang dipaskan mempertahankan posisi terkuncinya selama pengubahan ukuran. Artinya JavaScript tidak perlu menampilkan apa pun pada rotasi perangkat atau browser ubah ukuran. Coba di Chromium DevTools Perangkat Mode menurut memilih mode apa pun selain Responsive, lalu mengubah ukuran bingkai perangkat. Perhatikan elemen tetap terlihat dan terkunci dengan kontennya. Hal ini telah tersedia sejak Chromium memperbarui implementasinya agar sesuai dengan spesifikasi. Berikut postingan blog tentang hal itu.
Animasi
Tujuan kerja animasi di sini adalah untuk secara jelas menautkan interaksi dengan UI masukan. Hal ini membantu memandu atau membantu pengguna melaluinya (semoga) penemuan semua konten dengan lancar. Saya akan menambahkan {i>motion <i}dengan tujuan dan bersyarat. Pengguna kini dapat menentukan gerakan mereka preferensi dalam sistem operasinya, dan saya senang merespons preferensi mereka dalam antarmuka saya.
Saya akan menautkan tab garis bawah dengan posisi scroll artikel. {i>Snapping<i} bukan
hanya kerataan yang bagus, tetapi juga menambatkan awal dan akhir animasi.
Ini akan mempertahankan <nav>
, yang bertindak seperti
peta mini, yang terhubung ke konten.
Kita akan memeriksa preferensi gerakan pengguna dari CSS dan JS. Terdapat
beberapa tempat bagus untuk dipertimbangkan!
Perilaku scroll
Ada peluang untuk meningkatkan perilaku gerakan :target
dan
element.scrollIntoView()
. Secara default, instan. Browser hanya menyetel
posisi scroll. Nah, bagaimana jika kita ingin
bertransisi ke posisi {i>scroll<i},
alih-alih berkedip di sana?
@media (prefers-reduced-motion: no-preference) {
.scroll-snap-x {
scroll-behavior: smooth;
}
}
Karena kita memperkenalkan {i>motion <i}di sini, dan {i>motion <i}yang tidak dikontrol pengguna (seperti menggulir), kita hanya menerapkan gaya ini jika pengguna tidak memiliki preferensi sistem operasi mereka untuk mengurangi gerakan. Dengan cara ini, kami hanya memperkenalkan {i>motion <i}untuk orang-orang yang menerimanya.
Indikator tab
Tujuan animasi ini adalah untuk membantu mengaitkan indikator dengan status
konten tersebut. Saya memutuskan untuk mewarnai gaya border-bottom
crossfade untuk pengguna
yang lebih menyukai gerakan yang dikurangi, dan gerakan geser yang ditautkan + animasi pudar warna
bagi pengguna yang
tidak terbiasa dengan gerakan.
Di Chromium Devtools, saya dapat mengaktifkan/menonaktifkan preferensi dan mendemonstrasikan 2 gaya transisi yang berbeda. Saya sangat senang membuat ini.
@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
ketika pengguna lebih memilih pengurangan gerakan karena saya tidak
membutuhkannya lagi. Lalu saya menggantinya dengan gaya border-block-end
dan
transition
. Perhatikan juga di interaksi tab bahwa item navigasi aktif tidak
hanya memiliki sorotan garis bawah merek, tetapi warna teksnya juga lebih gelap. Tujuan
{i>active element<i} memiliki kontras warna teks yang lebih tinggi dan aksen {i>underlight<i} yang cerah.
Hanya beberapa baris CSS tambahan akan membuat seseorang merasa diperhatikan (dalam arti bahwa kami menghormati preferensi gerakan mereka). Saya menyukainya.
@scroll-timeline
Di bagian atas, saya menunjukkan cara menangani pengurangan crossfade gerakan gaya, dan di bagian ini saya akan menunjukkan cara menautkan indikator dan area scroll bersama-sama. Ini adalah beberapa hal eksperimental yang menyenangkan nanti. Saya harap Anda bersemangat seperti saya.
const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
);
Pertama-tama, saya memeriksa
preferensi gerakan pengguna dari JavaScript. Jika hasil
ini adalah false
, yang berarti pengguna lebih memilih gerakan yang lebih sedikit, maka kita tidak akan menjalankan
dari efek gerakan penautan {i>scroll<i}.
if (motionOK) {
// motion based animation code
}
Pada saat penulisan ini, dukungan browser untuk
@scroll-timeline
bukan satu pun. Ini adalah
draf spesifikasi hanya dengan
implementasi eksperimental. Ini memiliki polyfill, yang saya gunakan dalam
demo.
ScrollTimeline
Meskipun CSS dan JavaScript dapat membuat linimasa scroll, saya memilih untuk ikut serta JavaScript, jadi saya bisa 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 yang lain, dan dengan membuat
ScrollTimeline
Saya menentukan driver link scroll, scrollSource
.
Biasanya animasi di web dijalankan dengan jangka waktu global, tetapi dengan
sectionScrollTimeline
kustom di memori, saya bisa mengubah semua itu.
tabindicator.animate({
transform: ...,
width: ...,
}, {
duration: 1000,
fill: 'both',
timeline: sectionScrollTimeline,
}
);
Sebelum masuk ke dalam keyframe dalam animasi, saya pikir penting untuk
tunjukkan pengikut scroll, tabindicator
, akan dianimasikan berdasarkan
pada garis waktu khusus, gulir bagian kita. Ini melengkapi penautan, tetapi
kehilangan bahan akhir, titik stateful untuk dianimasikan, juga dikenal sebagai
keyframe.
Keyframe dinamis
Ada cara CSS deklaratif murni
yang sangat ampuh untuk dianimasikan
@scroll-timeline
, tetapi animasi yang saya pilih terlalu dinamis. Tidak ada
beralih di antara lebar auto
, dan tidak ada cara untuk membuat secara dinamis
jumlah keyframe berdasarkan panjang turunan.
JavaScript tahu cara mendapatkan informasi itu, jadi kita akan mengulanginya pada 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
, urai posisi offsetLeft
dan tampilkan string
yang menggunakannya sebagai nilai translateX
. Proses ini akan menghasilkan 4 keyframe transformasi untuk
animasi. Hal yang sama dilakukan untuk lebar, masing-masing ditanya berapa lebar dinamisnya
dan digunakan sebagai nilai keyframe.
Berikut ini contoh output, berdasarkan preferensi browser dan font saya:
Keyframe 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)"]
Frame Utama Lebar:
[...tabnavitems].map(({offsetWidth}) =>
`${offsetWidth}px`)
// results in 4 array items, which represent 4 keyframe states
// ["121px", "117px", "226px", "67px"]
Untuk meringkas strategi ini, indikator tab kini akan dianimasikan di 4 keyframe bergantung pada posisi pengepasan scroll dari scroller bagian. Penunjuk posisi membuat pemisahan yang jelas antara keyframe dan menambahkan nuansa animasi yang sinkron.
Pengguna menjalankan animasi dengan interaksi mereka, melihat lebar dan posisi indikator berubah dari satu bagian ke bagian berikutnya, melacak dengan menggulir.
Anda mungkin tidak menyadarinya, tetapi saya sangat bangga dengan transisi warna sebagai item navigasi yang disorot menjadi dipilih.
Abu-abu muda yang tidak dipilih akan terlihat semakin terdorong ke belakang saat {i>item<i} memiliki lebih banyak kontras. Sangat umum untuk mengubah warna teks, seperti saat kursor diarahkan dan saat dipilih, tetapi ini adalah tingkat berikutnya untuk mengubah warna saat menggulir, disinkronkan dengan indikator garis bawah.
Begini 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 scroll yang sama linimasa sebagai indikator garis bawah. Saya menggunakan garis waktu yang sama seperti sebelumnya: sejak perannya adalah memberikan tanda centang pada {i>scroll<i}, kita dapat menggunakan opsi itu dalam animasi yang kita inginkan. Seperti yang saya lakukan sebelumnya, saya membuat 4 keyframe dalam loop, dan kembali 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
itu adalah warna teks standar. Terdapat loop bertingkat di sana sehingga
mudah, karena loop luar adalah setiap item navigasi, dan loop dalam masing-masing
keyframe pribadi navitem. Saya memeriksa apakah elemen loop luar sama dengan
{i>loop <i}dalam satu, dan menggunakannya
untuk mengetahui kapan dipilih.
Saya sangat senang ketika menulis ini. Banyak sekali.
Bahkan lebih banyak penyempurnaan JavaScript
Perlu diingat bahwa inti dari apa yang saya tunjukkan di sini berfungsi tanpa pada JavaScript. Sekarang, mari kita lihat bagaimana kita dapat meningkatkannya yang tersedia.
Deep link
Deep link lebih merupakan istilah seluler, tetapi menurut saya tujuan deep link adalah
bertemu dengan tab di mana Anda dapat
berbagi URL langsung ke konten tab. Tujuan
browser akan membuka ID yang cocok dalam hash URL. aku nemu
pengendali onload
ini membuat efek di seluruh platform.
window.onload = () => {
if (location.hash) {
tabsection.scrollLeft = document
.querySelector(location.hash)
.offsetLeft;
}
}
Sinkronisasi akhir scroll
Pengguna kita tidak selalu mengeklik atau menggunakan {i>keyboard<i}, terkadang mereka hanya scroll bebas, sebagaimana mestinya. Saat scroller bagian berhenti untuk men-scroll, di mana pun halamannya mendarat harus dicocokkan di menu navigasi atas.
Inilah cara saya menunggu scroll berakhir:
js
tabsection.addEventListener('scroll', () => {
clearTimeout(tabsection.scrollEndTimer);
tabsection.scrollEndTimer = setTimeout(determineActiveTabSection, 100);
});
Setiap kali bagian di-scroll, hapus batas waktu bagian jika ada, dan memulai yang baru. Saat bagian berhenti di-scroll, jangan hapus waktu tunggu, dan api 100 md setelah istirahat. Saat diaktifkan, panggil fungsi yang mencari mengetahui posisi pengguna.
const determineActiveTabSection = () => {
const i = tabsection.scrollLeft / tabsection.clientWidth;
const matchingNavItem = tabnavitems[i];
matchingNavItem && setActiveTab(matchingNavItem);
};
Dengan asumsi scroll telah dipaskan, dengan membagi posisi scroll saat ini dari lebar area scroll harus menghasilkan bilangan bulat dan bukan desimal. Saya kemudian mencoba untuk Ambil navitem dari {i>cache<i} melalui indeks yang dihitung, dan jika menemukan sesuatu, saya mengirimkan kecocokan agar diaktifkan.
const setActiveTab = tabbtn => {
tabnav
.querySelector(':scope a[active]')
.removeAttribute('active');
tabbtn.setAttribute('active', '');
tabbtn.scrollIntoView();
};
Pengaturan tab aktif dimulai dengan membersihkan
tab apa pun yang sedang aktif, lalu memberi
item navigasi yang masuk, atribut {i>active state<i}. Panggilan ke scrollIntoView()
memiliki interaksi menyenangkan dengan CSS.
.scroll-snap-x {
overflow: auto hidden;
overscroll-behavior-x: contain;
scroll-snap-type: x mandatory;
@media (prefers-reduced-motion: no-preference) {
scroll-behavior: smooth;
}
}
Dalam CSS utilitas snap scroll horizontal, kita telah
menyusun bertingkat kueri media yang berlaku
smooth
men-scroll jika pengguna tahan gerakan. JavaScript dapat dengan bebas membuat
untuk menggulir elemen ke dalam tampilan, dan CSS dapat mengelola UX secara deklaratif.
Perpaduan kecil yang cukup menyenangkan yang kadang-kadang mereka buat.
Kesimpulan
Sekarang setelah Anda tahu cara saya melakukannya, bagaimana Anda akan melakukannya?! Hal ini membuat suasana menjadi menyenangkan arsitektur komponen! Siapa yang akan membuat versi pertama dengan slot di framework favorit Anda? 🙂
Mari kita diversifikasi pendekatan kami dan mempelajari semua cara untuk membangun di web. Buat Glitch, tweet saya versi Anda, dan akan saya tambahkan ke Remix komunitas di bawah ini.
Remix komunitas
- @devnook, @rob_dodson, dan @DasSurma dengan Komponen Web: artikel.
- @jhvanderschee dengan tombol: Codepen.