Bandingkan & BandingkanTeks

Atribut lang hanya dapat memiliki satu bahasa yang terkait dengannya. Artinya, atribut <html> hanya dapat memiliki satu bahasa, meskipun ada beberapa bahasa di halaman. Setel lang ke bahasa utama halaman.

Larangan
<html lang="ar,en,fr,pt">...</html>
Beberapa bahasa tidak didukung.
Anjuran
<html lang="ar">...</html>
Hanya setel bahasa utama halaman. Dalam hal ini, bahasa yang digunakan adalah bahasa Arab.

Serupa dengan tombol, link terutama mendapatkan nama yang dapat diakses dari konten teksnya. Trik yang bagus saat membuat link adalah dengan memasukkan potongan teks yang paling penting ke dalam link itu sendiri, bukan kata pengisi seperti "Di sini" atau "Baca Selengkapnya."

Tidak cukup deskriptif
Check out our guide to web performance <a href="/guide">here</a>.
Konten yang bermanfaat!
Check out <a href="/guide">our guide to web performance</a>.

Memeriksa apakah animasi memicu tata letak

Animasi yang memindahkan elemen menggunakan selain transform, kemungkinan akan berjalan lambat. Pada contoh berikut, saya telah mencapai hasil visual yang sama yang menganimasikan top dan left, serta menggunakan transform.

Larangan
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     top: calc(90vh - 160px);
     left: calc(90vw - 200px);
  }
}
Anjuran
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     transform: translate(calc(90vw - 200px), calc(90vh - 160px));
  }
}

Anda dapat mengujinya dalam dua contoh Glitch berikut, dan mempelajari performa menggunakan DevTools.

Dengan markup yang sama, kita dapat mengganti: padding-top: 56.25% dengan aspect-ratio: 16 / 9, menetapkan aspect-ratio ke rasio width / height yang ditentukan.

Menggunakan padding-top
.container {
  width: 100%;
  padding-top: 56.25%;
}
Menggunakan rasio aspek
.container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

Menggunakan aspect-ratio, bukan padding-top, jauh lebih jelas, dan tidak memperbaiki properti padding untuk melakukan sesuatu di luar cakupan biasanya.

Ya, benar, saya menggunakan reduce untuk merangkai urutan promise. Saya begitu pintar. Tapi ini adalah coding yang sangat cerdas yang sebaiknya Anda tidak melakukannya.

Namun, saat mengonversi fungsi di atas menjadi fungsi asinkron, Anda mungkin ingin terlalu berurutan:

Tidak disarankan - terlalu berurutan
async function logInOrder(urls) {
  for (const url of urls) {
    const response = await fetch(url);
    console.log(await response.text());
  }
}
Terlihat jauh lebih rapi, tetapi pengambilan kedua saya tidak dimulai hingga pengambilan pertama dibaca sepenuhnya, dan seterusnya. Ini jauh lebih lambat dibandingkan contoh promise yang melakukan pengambilan secara paralel. Untungnya ada jalan tengah yang ideal.
Direkomendasikan - bagus dan paralel
function markHandled(...promises) {
  Promise.allSettled(promises);
}

async function logInOrder(urls) {
  // fetch all the URLs in parallel
  const textPromises = urls.map(async (url) => {
    const response = await fetch(url);
    return response.text();
  });

  markHandled(...textPromises);

  // log them in sequence
  for (const textPromise of textPromises) {
    console.log(await textPromise);
  }
}
Dalam contoh ini, URL diambil dan dibaca secara paralel, tetapi bit reduce "pintar" diganti dengan for-loop yang standar, membosankan, dan dapat dibaca.

Menulis properti kustom Houdini

Berikut ini contoh penetapan properti kustom (misalnya: variabel CSS), tetapi sekarang dengan sintaksis (jenis), nilai awal (fallback), dan boolean pewarisan (apakah mewarisi nilai dari induknya atau tidak?). Cara saat ini untuk melakukannya adalah melalui CSS.registerProperty() di JavaScript, tetapi di Chromium 85 dan yang lebih baru, sintaksis @property akan didukung di file CSS Anda:

File JavaScript terpisah (Chromium 78)
CSS.registerProperty({
  name: '--colorPrimary',
  syntax: '',
  initialValue: 'magenta',
  inherits: false
});
Disertakan dalam file CSS (Chromium 85)
@property --colorPrimary {
  syntax: '';
  initial-value: magenta;
  inherits: false;
}

Sekarang Anda dapat mengakses --colorPrimary seperti properti khusus CSS lainnya, melalui var(--colorPrimary). Namun, perbedaannya di sini adalah --colorPrimary tidak hanya dibaca sebagai string. Data itu ada!

CSS backdrop-filter menerapkan satu atau beberapa efek ke elemen yang transparan atau transparan. Untuk memahaminya, perhatikan gambar di bawah ini.

Tidak ada transparansi latar depan
Segitiga yang tumpang-tindih pada lingkaran. Lingkaran tidak dapat dilihat melalui segitiga.
.frosty-glass-pane {
  backdrop-filter: blur(2px);
}
Transparansi latar depan
Segitiga yang tumpang-tindih pada lingkaran. Segitiga ini tembus cahaya, sehingga lingkaran dapat dilihat melaluinya.
.frosty-glass-pane {
  opacity: .9;
  backdrop-filter: blur(2px);
}

Gambar di sebelah kiri menunjukkan cara elemen yang tumpang-tindih dirender jika backdrop-filter tidak digunakan atau didukung. Gambar di sebelah kanan menerapkan efek buram menggunakan backdrop-filter. Perhatikan bahwa kode ini menggunakan opacity selain backdrop-filter. Tanpa opacity, pemburaman tidak akan ada. Hampir tidak perlu dikatakan bahwa jika opacity disetel ke 1 (sepenuhnya buram) tidak akan ada efek pada latar belakang.

Namun, tidak seperti peristiwa unload, ada penggunaan yang sah untuk beforeunload. Misalnya, saat Anda ingin memperingatkan pengguna bahwa perubahan belum disimpan akan hilang jika mereka meninggalkan halaman. Dalam hal ini, sebaiknya Anda hanya menambahkan pemroses beforeunload saat pengguna memiliki perubahan yang belum disimpan, lalu menghapusnya segera setelah perubahan yang belum disimpan disimpan.

Larangan
window.addEventListener('beforeunload', (event) => {
  if (pageHasUnsavedChanges()) {
    event.preventDefault();
    return event.returnValue = 'Are you sure you want to exit?';
  }
});
Kode di atas menambahkan pemroses beforeunload tanpa syarat.
Anjuran
function beforeUnloadListener(event) {
  event.preventDefault();
  return event.returnValue = 'Are you sure you want to exit?';
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  window.addEventListener('beforeunload', beforeUnloadListener);
});

// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
  window.removeEventListener('beforeunload', beforeUnloadListener);
});
Kode di atas hanya menambahkan pemroses beforeunload saat diperlukan (dan menghapusnya jika tidak diperlukan).

Minimalkan penggunaan Cache-Control: no-store

Cache-Control: no-store adalah server web header HTTP yang dapat ditetapkan pada respons yang menginstruksikan browser untuk tidak menyimpan respons dalam cache HTTP apa pun. Kebijakan ini harus digunakan untuk resource yang berisi informasi pengguna sensitif, misalnya halaman yang memerlukan login.

Elemen fieldset, yang berisi setiap grup input (.fieldset-item), menggunakan gap: 1px untuk membuat batas garis rambut di antara elemen. Tidak ada solusi perbatasan yang rumit.

Kekosongan terisi
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Trik batas
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

Penggabungan petak alami

Tata letak yang paling kompleks akhirnya menjadi tata letak makro, yaitu sistem tata letak logis antara <main> dan <form>.

input
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
label
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

Elemen fieldset, yang berisi setiap grup input (.fieldset-item), menggunakan gap: 1px untuk membuat batas garis rambut di antara elemen. Tidak ada solusi perbatasan yang rumit.

Kekosongan terisi
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Trik batas
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

Tata letak <header> tab

Tata letak berikutnya hampir sama: saya menggunakan fleksibilitas untuk membuat pengurutan vertikal.

HTML
<snap-tabs>
  <header>
    <nav></nav>
    <span class="snap-indicator"></span>
  </header>
  <section></section>
</snap-tabs>
CSS
header {
  display: flex;
  flex-direction: column;
}

.snap-indicator harus berpindah secara horizontal bersama grup link, dan tata letak header ini membantu menetapkan tahap tersebut. Tidak ada elemen yang diposisikan secara mutlak di sini!

Gentle Flex adalah strategi khusus pemusatan yang lebih nyata. Teks ini lembut dan lembut karena tidak seperti place-content: center, tidak ada ukuran kotak anak yang berubah selama pemusatan. Sempurna mungkin, semua item ditumpuk, di tengah, dan diberi jarak.

.gentle-flex {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1ch;
}
Kelebihan
  • Hanya menangani perataan, arah, dan distribusi
  • Semua pengeditan dan pemeliharaan ada di satu tempat
  • Kesenjangan menjamin jarak yang sama di antara n turunan
Kekurangan
  • Sebagian besar baris kode

Sangat cocok untuk tata letak makro dan mikro.

Penggunaan

gap menerima semua panjang atau persentase CSS sebagai nilai.

.gap-example {
  display: grid;
  gap: 10px;
  gap: 2ch;
  gap: 5%;
  gap: 1em;
  gap: 3vmax;
}


Celah dapat diteruskan 1 panjang, yang akan digunakan untuk baris dan kolom.

Singkatan
.grid {
  display: grid;
  gap: 10px;
}
Menetapkan baris dan kolom bersama-sama sekaligus
Diperluas
.grid {
  display: grid;
  row-gap: 10px;
  column-gap: 10px;
}


Celah dapat dilewati 2 panjang, yang akan digunakan untuk baris dan kolom.

Singkatan
.grid {
  display: grid;
  gap: 10px 5%;
}
Menetapkan baris dan kolom secara terpisah sekaligus
Diperluas
.grid {
  display: grid;
  row-gap: 10px;
  column-gap: 5%;
}