Membuat Kalender dengan Mempertimbangkan Aksesibilitas dan Internasionalisasi | Tips CSS

 – Beragampengetahuan
14 mins read

Membuat Kalender dengan Mempertimbangkan Aksesibilitas dan Internasionalisasi | Tips CSS – Beragampengetahuan

Pencarian cepat di beragampengetahuan mengungkapkan betapa banyak cara berbeda yang dapat Anda lakukan untuk menangani kalender. Beberapa di antaranya menunjukkan bagaimana CSS Grid dapat membuat tata letak secara efisien. Beberapa mencoba memasukkan data aktual ke dalamnya. Beberapa mengandalkan kerangka kerja untuk membantu pengelolaan negara.

Ada banyak pertimbangan saat membuat komponen kalender – jauh lebih banyak daripada yang tercakup dalam artikel yang saya tautkan. Jika Anda memikirkannya, kalender penuh dengan nuansa, mulai dari menangani zona waktu dan format tanggal hingga pelokalan, dan bahkan memastikan tanggal mengalir dari satu bulan ke bulan berikutnya…dan ini bahkan memasukkan aksesibilitas dan pertimbangan Tata Letak lainnya sebelum ditampilkan, dll.

banyak pengembang khawatir Date() melawan dan tetap berpegang pada perpustakaan lama seperti moment.jsNamun terlepas dari semua “gotcha” terkait tanggal dan pemformatan, JavaScript memiliki banyak API keren dan hal-hal lain yang dapat membantu!

Kisi-kisi kalender Januari 2023.

Saya tidak ingin menemukan kembali roda di sini, tetapi saya akan menunjukkan kepada Anda bagaimana kita bisa mendapatkan kalender yang sangat bagus menggunakan vanilla JavaScript.kami akan menyelidiki Aksesibilitasmenggunakan markup semantik dan ramah pembaca layar <time> – label – dan globalisasi Dan formatmenggunakan Intl.Locale, Intl.DateTimeFormat Dan Intl.NumberFormat-lebah.

Dengan kata lain, kita membuat kalender…hanya tanpa dependensi ekstra yang biasanya Anda lihat di tutorial seperti ini, dan dengan beberapa nuansa yang biasanya tidak Anda lihat. Dan, dalam prosesnya, saya harap Anda mendapatkan apresiasi baru untuk hal-hal baru yang dapat dilakukan JavaScript, serta jenis ide yang muncul di kepala saya saat saya menyatukan sesuatu seperti ini.

Contents

Nama depan

Apa yang harus kita sebut komponen kalender kita? Dalam bahasa ibu saya itu akan disebut “elemen kalender”, jadi mari kita gunakan itu dan disingkat menjadi “Kal-El” – juga dikenal sebagai nama Superman di Krypton.

Mari kita buat fungsi untuk menjaga semuanya tetap berjalan:

function kalEl(settings = {}) { ... }

Metode ini akan merender sebulan.Nanti kita akan mulai dengan [...Array(12).keys()] Render selama setahun penuh.

Data awal dan internasionalisasi

Satu hal umum yang dilakukan oleh kalender online biasa adalah menyorot tanggal saat ini. Jadi mari kita buat referensi untuk ini:

const today = new Date();

Selanjutnya, kita akan membuat “objek konfigurasi” yang akan kita gabungkan dengan opsi settings Metode utama objek:

const config = Object.assign(
  {
    locale: (document.documentElement.getAttribute('lang') || 'en-US'), 
    today: { 
      day: today.getDate(),
      month: today.getMonth(),
      year: today.getFullYear() 
    } 
  }, settings
);

Kami memeriksa apakah elemen root (<html>) berisi a lang– atribut dengan Lokal informasi; jika tidak, kami kembali menggunakan en-US.Ini adalah langkah pertama dalam internasionalisasi kalender.

Kita juga perlu menentukan bulan mana yang awalnya ditampilkan saat merender kalender.Itu sebabnya kami memperpanjang config objek dan utama dateJadi, jika settings objek, kita akan menggunakan today Referensi sebagai gantinya:

const date = config.date ? new Date(config.date) : today;

Kami memerlukan lebih banyak informasi untuk memformat kalender dengan benar sesuai dengan lokal. Misalnya, kita mungkin tidak mengetahui apakah hari pertama dalam seminggu adalah Minggu atau Senin, bergantung pada wilayah setempat. Alangkah baiknya jika kita memiliki informasi!tetapi jika tidak, kami akan menggunakan Intl.Locale API. API memiliki weekInfo mengembalikan sebuah objek firstDay Properti yang memberi kami apa yang kami cari tanpa hambatan.Kita juga bisa mengetahui hari mana dalam seminggu yang ditetapkan weekend:

if (!config.info) config.info = new Intl.Locale(config.locale).weekInfo || { 
  firstDay: 7,
  weekend: [6, 7] 
};

Demikian juga, kami membuat fallback. “Hari pertama” dalam seminggu en-US adalah hari Minggu, jadi nilai standarnya adalah 7Ini agak membingungkan karena getDay Metode dalam JavaScript mengembalikan tanggal sebagai [0-6]Di mana 0 Ini hari minggu…jangan tanya kenapa.Akhir pekan adalah hari Sabtu dan Minggu, jadi [6, 7].

di mana kita punya Intl.Locale API dan weekInfo metode, sulit untuk membuat kalender internasional tanpa banyak ** objek dan larik yang berisi informasi untuk setiap lokal atau wilayah. Hari-hari ini, itu mudah.Jika kita lewat en-GBmetode mengembalikan:

// en-GB
{
  firstDay: 1,
  weekend: [6, 7],
  minimalDays: 4
}

Di negara-negara seperti Brunei (ms-BN), akhir pekan adalah hari Jumat dan Minggu:

// ms-BN
{
  firstDay: 7,
  weekend: [5, 7],
  minimalDays: 1
}

Anda mungkin bertanya-tanya apa itu minimalDays Property Islands Ini adalah jumlah hari minimum yang diperlukan untuk menghitung minggu pertama dalam sebulan sebagai satu minggu penuh. Di beberapa daerah, mungkin hanya satu hari. Bagi yang lain, mungkin tujuh hari penuh.

Selanjutnya, kita akan membuat render Jalan kita kalEl-metode:

const render = (date, locale) => { ... }

Kami masih membutuhkan lebih banyak data untuk diproses sebelum kami dapat merender apa pun:

const month = date.getMonth();
const year = date.getFullYear();
const numOfDays = new Date(year, month + 1, 0).getDate();
const renderToday = (year === config.today.year) && (month === config.today.month);

yang terakhir adalah Boolean periksa apakah today Ada di bulan yang akan kami hadirkan.

markup semantik

Kami akan menggali rendering nanti. Tapi pertama-tama, saya ingin memastikan bahwa detail yang kami atur memiliki tag HTML semantik yang terkait dengannya. Penyiapan out-of-the-box memberi kami keunggulan aksesibilitas sejak awal.

kemasan kalender

Pertama, kami memiliki pembungkus non-semantik: <kal-el>.baik saja karena tidak ada semantik <calendar> label atau semacamnya. Jika kami tidak membuat elemen khusus, <article> Mungkin elemen yang paling cocok, karena kalender dapat ditempatkan di halamannya sendiri.

nama bulan

ini <time> elemen akan menjadi salah satu yang penting bagi kami, karena membantu mengonversi tanggal menjadi format yang dapat diuraikan oleh pembaca layar dan mesin telusur dengan lebih akurat dan konsisten. Misalnya, inilah cara kami menyampaikan “Januari 2023” di markup kami:

<time datetime="2023-01">January <i>2023</i></time>

nama tanggal

Baris di atas tanggal kalender yang berisi nama hari dalam seminggu bisa jadi rumit. Akan ideal jika kita dapat menulis nama lengkap setiap hari – misalnya Minggu, Senin, Selasa, dll – tetapi itu akan memakan banyak tempat.Jadi, sekarang mari kita ambil a <ol> setiap hari adalah <li>:

<ol>
  <li><abbr title="Sunday">Sun</abbr></li>
  <li><abbr title="Monday">Mon</abbr></li>
  <!-- etc. -->
</ol>

Kita dapat menggunakan CSS untuk mendapatkan yang terbaik dari kedua dunia. Misalnya, jika kita memodifikasi markup seperti ini:

<ol>
  <li>
    <abbr title="S">Sunday</abbr>
  </li>
</ol>

… kami mendapatkan nama lengkap secara default.Lalu kita bisa “menyembunyikan” nama lengkap saat kita kehabisan ruang dan menampilkan title Ubah ke atribut:

@media all and (max-width: 800px) {
  li abbr::after {
    content: attr(title);
  }
}

Namun, kami tidak akan melakukannya karena Intl.DateTimeFormat API juga dapat membantu di sini. Kami akan menyentuh ini saat kami membahas rendering di bagian selanjutnya.

jumlah hari

Setiap tanggal di kisi kalender memiliki nomor. Setiap nomor adalah item daftar (<li>) dalam daftar terurut (<ol>), dan sebaris <time> Label membungkus nomor sebenarnya.

<li>
  <time datetime="2023-01-01">1</time>
</li>

Meskipun saya belum akan melakukan gaya apa pun, saya tahu saya memerlukan beberapa cara untuk menata nomor tanggal. Ini mungkin, tetapi saya juga ingin gaya nomor hari kerja berbeda dari nomor akhir pekan jika diperlukan.Jadi, saya akan memasukkan data-* Properti khusus untuk ini: data-weekend Dan data-today.

nomor minggu

Ada 52 minggu dalam setahun, terkadang 53 minggu. Meskipun ini tidak terlalu umum, sebaiknya tampilkan angka untuk minggu tertentu di kalender untuk konteks lebih lanjut. Saya suka memilikinya sekarang, meskipun pada akhirnya saya tidak menggunakannya. Tapi kami akan menggunakannya persis untuk tutorial ini.

kami akan menggunakan data-weeknumber atribut sebagai pengait gaya dan sertakan dalam markup untuk setiap tanggal (yaitu hari pertama dalam seminggu).

<li data-day="7" data-weeknumber="1" data-weekend="">
  <time datetime="2023-01-08">8</time>
</li>

rendering

Mari letakkan kalender di satu halaman!kita sudah tahu <kal-el> adalah nama elemen kustom kami.Hal pertama yang perlu kita konfigurasikan adalah mengatur firstDay Itu properti sehingga kalender tahu bahwa minggu atau hari lain adalah hari pertama dalam seminggu.

<kal-el data-firstday="${ config.info.firstDay }">

Kami akan menggunakan literal template untuk merender markup.Untuk memformat tanggal untuk audiens internasional, kami akan menggunakan Intl.DateTimeFormat API, lagi menggunakan locale Kami tentukan sebelumnya.

bulan dan tahun

ketika kita menelepon monthKita dapat mengatur apakah kita ingin menggunakan long nama (misalnya Februari) atau short Nama (misalnya Februari).mari kita gunakan long nama, seperti judul di atas kalender:

<time datetime="${year}-${(pad(month))}">
  ${new Intl.DateTimeFormat(
    locale,
    { month:'long'}).format(date)} <i>${year}</i>
</time>

nama hari kerja

Agar hari kerja ditampilkan di atas petak tanggal, kita memerlukan keduanya long (misalnya “Minggu”) dan short (disingkat, atau “Matahari”) nama. Dengan cara ini kita bisa menggunakan nama “pendek” saat kalender kehabisan ruang:

Intl.DateTimeFormat([locale], { weekday: 'long' })
Intl.DateTimeFormat([locale], { weekday: 'short' })

Mari buat metode pembantu kecil untuk membuat pemanggilan setiap metode sedikit lebih mudah:

const weekdays = (firstDay, locale) => {
  const date = new Date(0);
  const arr = [...Array(7).keys()].map(i => {
    date.setDate(5 + i)
    return {
      long: new Intl.DateTimeFormat([locale], { weekday: 'long'}).format(date),
      short: new Intl.DateTimeFormat([locale], { weekday: 'short'}).format(date)
    }
  })
  for (let i = 0; i < 8 - firstDay; i++) arr.splice(0, 0, arr.pop());
  return arr;
}

Inilah cara kami menyebutnya di template:

<ol>
  ${weekdays(config.info.firstDay,locale).map(name => `
    <li>
      <abbr title="${name.long}">${name.short}</abbr>
    </li>`).join('')
  }
</ol>

jumlah hari

Akhirnya, hari itu, terbungkus <ol> elemen:

${[...Array(numOfDays).keys()].map(i => {
  const cur = new Date(year, month, i + 1);
  let day = cur.getDay(); if (day === 0) day = 7;
  const today = renderToday && (config.today.day === i + 1) ? ' data-today':'';
  return `
    <li data-day="${day}"${today}${i === 0 || day === config.info.firstDay ? ` data-weeknumber="${new Intl.NumberFormat(locale).format(getWeek(cur))}"`:''}${config.info.weekend.includes(day) ? ` data-weekend`:''}>
      <time datetime="${year}-${(pad(month))}-${pad(i)}" tabindex="0">
        ${new Intl.NumberFormat(locale).format(i + 1)}
      </time>
    </li>`
}).join('')}

Mari kita uraikan:

  1. Kami membuat larik “dummy” berdasarkan variabel “hari”, yang akan kami gunakan untuk iterasi.
  2. kami membuat sebuah day Variabel untuk hari ini dalam iterasi.
  3. Kami memperbaiki perbedaan antara Intl.Locale API dan getDay().
  4. jika day setara todaykami menambahkan a data-* Atribut.
  5. Akhirnya, kami kembali <li> Elemen sebagai string dengan data gabungan.
  6. tabindex="0" Jadikan elemen dapat difokuskan saat bernavigasi dengan keyboard, setelah nilai tabindex positif (catatan: Anda harus mustahil Tambahkan positif nilai indeks tag)

Angka dalam “isi” datetime properti, kami menggunakan beberapa metode pembantu:

const pad = (val) => (val + 1).toString().padStart(2, '0');

nomor minggu

Demikian pula, “nomor minggu” adalah posisi minggu dalam kalender 52 minggu. Kami juga menggunakan beberapa metode pembantu untuk ini:

function getWeek(cur) {
  const date = new Date(cur.getTime());
  date.setHours(0, 0, 0, 0);
  date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
  const week = new Date(date.getFullYear(), 0, 4);
  return 1 + Math.round(((date.getTime() - week.getTime()) / 86400000 - 3 + (week.getDay() + 6) % 7) / 7);
}

ini bukan tulisan saya getWeek-metode. Ini adalah versi yang dibersihkan dari skrip ini.

Itu dia!bersyukur Intl.Locale, Intl.DateTimeFormat Dan Intl.NumberFormat API, sekarang kita dapat dengan mudah mengubah lang– properti dari <html> Ubah elemen konteks kalender sesuai dengan lokal saat ini:

Kisi-kisi kalender Januari 2023.
de-DE
Kisi-kisi kalender Januari 2023.
fa-IR
Kisi-kisi kalender Januari 2023.
zh-Hans-CN-u-nu-hanidec

kalender desain

Anda mungkin ingat bahwa semua hari adalah a <ol> dengan daftar item. Untuk mendesainnya menjadi kalender yang dapat dibaca, kami terjun ke dunia CSS Grid yang menakjubkan.Faktanya, kita dapat menskalakan ulang grid yang sama dari template kalender awal di beragampengetahuan, tetapi diperbarui sedikit :is() semu relasional untuk mengoptimalkan kode.

Perhatikan bahwa saya mendefinisikan variabel CSS yang dapat dikonfigurasi di sepanjang jalan (dan awali dengan ---kalel- untuk menghindari konflik).

kal-el :is(ol, ul) {
  display: grid;
  font-size: var(--kalel-fz, small);
  grid-row-gap: var(--kalel-row-gap, .33em);
  grid-template-columns: var(--kalel-gtc, repeat(7, 1fr));
  list-style: none;
  margin: unset;
  padding: unset;
  position: relative;
}
Menampilkan kisi kalender tujuh kolom dengan garis kisi.

Mari menggambar batas di sekitar nomor tanggal untuk membantu memisahkannya secara visual:

kal-el :is(ol, ul) li {
  border-color: var(--kalel-li-bdc, hsl(0, 0%, 80%));
  border-style: var(--kalel-li-bds, solid);
  border-width: var(--kalel-li-bdw, 0 0 1px 0);
  grid-column: var(--kalel-li-gc, initial);
  text-align: var(--kalel-li-tal, end); 
}

Saat hari pertama bulan itu adalah kisi tujuh kolom berfungsi dengan baik kembali hari pertama dalam seminggu untuk lokal yang dipilih). Tapi ini pengecualian daripada aturannya. Sebagian besar waktu kita perlu menukar hari pertama setiap bulan ke hari kerja lainnya.

Menampilkan bahwa hari pertama bulan itu adalah Kamis.

ingat semua ekstra data-* Atribut yang kita definisikan saat menulis markup? Kami dapat terhubung ke mereka untuk memperbarui kolom kisi mana (--kalel-li-gc) dengan nomor hari pertama bulan itu di:

[data-firstday="1"] [data-day="3"]:first-child {
  --kalel-li-gc: 1 / 4;
}

Dalam hal ini, kami merentang dari kolom petak pertama ke kolom petak keempat – ini akan secara otomatis “mendorong” item berikutnya (hari ke-2) ke kolom petak kelima, dan seterusnya.

Mari tambahkan sedikit gaya pada tanggal “saat ini” untuk membuatnya menonjol. Ini hanya gaya saya. Anda dapat melakukan apa yang Anda inginkan di sini.

[data-today] {
  --kalel-day-bdrs: 50%;
  --kalel-day-bg: hsl(0, 86%, 40%);
  --kalel-day-hover-bgc: hsl(0, 86%, 70%);
  --kalel-day-c: #fff;
}

Saya suka ide mendesain nomor tanggal akhir pekan berbeda dari hari kerja. Saya akan menggunakan warna kemerahan untuk menatanya.Perhatikan bahwa kita dapat mencapai :not() pseudo-class untuk memilihnya sambil mempertahankan tanggal saat ini saja:

[data-weekend]:not([data-today]) { 
  --kalel-day-c: var(--kalel-weekend-c, hsl(0, 86%, 46%));
}

Oh, dan jangan lupa nomor minggu sebelum nomor hari pertama setiap minggu.kami menggunakan a data-weeknumber di tag, tetapi angkanya tidak akan benar-benar muncul kecuali kita menampilkannya dengan CSS, yang bisa kita lakukan di ::before Elemen semu:

[data-weeknumber]::before {
  display: var(--kalel-weeknumber-d, inline-block);
  content: attr(data-weeknumber);
  position: absolute;
  inset-inline-start: 0;
  /* additional styles */
}

Pada titik ini kita secara teknis selesai! Kami dapat merender kisi kalender yang menampilkan tanggal bulan ini, berhati-hati untuk melokalkan data berdasarkan lokal dan memastikan kalender menggunakan semantik yang benar. Yang kami gunakan hanyalah JavaScript dan CSS biasa!

Tapi mari kita letakkan ini langkah lain

menghasilkan satu tahun penuh

Mungkin Anda perlu menampilkan tanggal setahun penuh! Jadi alih-alih merender bulan ini, Anda mungkin ingin menampilkan kisi semua bulan untuk tahun ini.

Nah, hal yang menyenangkan tentang metode yang kita gunakan adalah kita bisa menelepon render beberapa kali, hanya mengubah bilangan bulat yang mengidentifikasi bulan pada setiap instance. Sebut saja 12 kali berdasarkan tahun berjalan.

semudah menelepon render-metode 12 kali, ubah saja bilangan bulat menjadi monthi:

[...Array(12).keys()].map(i =>
  render(
    new Date(date.getFullYear(),
    i,
    date.getDate()),
    config.locale,
    date.getMonth()
  )
).join('')

Sebaiknya buat pembungkus induk baru untuk tahun yang dirender.Setiap kisi kalender adalah a <kal-el> elemen.Sebut saja pembungkus induk baru <jor-el>dimana Jor-El adalah nama ayah Kal-El.

<jor-el id="app" data-year="true">
  <kal-el data-firstday="7">
    <!-- etc. -->
  </kal-el>

  <!-- other months -->
</jor-el>

kita bisa gunakan <jor-el> Buat kisi untuk kisi kami. Terlalu banyak!

jor-el {
  background: var(--jorel-bg, none);
  display: var(--jorel-d, grid);
  gap: var(--jorel-gap, 2.5rem);
  grid-template-columns: var(--jorel-gtc, repeat(auto-fill, minmax(320px, 1fr)));
  padding: var(--jorel-p, 0);
}

presentasi akhir

Bonus: Kalender Konfeti

Saya membaca sebuah buku bagus berjudul Buat dan hancurkan kisi-kisi Menemukan “Poster Tahun Baru” yang indah ini tempo hari:

sumber: Membuat dan Memecah Grid (versi 2) oleh Timotius Samara

Saya pikir kita bisa melakukan hal serupa tanpa mengubah apa pun di HTML atau JavaScript. Saya mengambil kebebasan untuk memasukkan nama dan nomor bulan penuh alih-alih nama hari agar lebih mudah dibaca. menikmati!

rencana pengembangan website



metode pengembangan website

jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website

#Membuat #Kalender #dengan #Mempertimbangkan #Aksesibilitas #dan #Internasionalisasi #Tips #CSS

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *