เปรียบเทียบและเปรียบเทียบคำบรรยาย

แอตทริบิวต์ lang จะเชื่อมโยงกับภาษาได้เพียงภาษาเดียวเท่านั้น ซึ่งหมายความว่าแอตทริบิวต์ <html> ต้องมีภาษาเดียวเท่านั้น แม้ว่าหน้าเว็บจะมีหลายภาษาก็ตาม ตั้งค่า lang เป็นภาษาหลักของหน้า

ไม่ควรทำ
<html lang="ar,en,fr,pt">...</html>
ระบบไม่รองรับหลายภาษา
ควรทำ
<html lang="ar">...</html>
ตั้งค่าเฉพาะภาษาหลักของหน้า ในกรณีนี้ ภาษาคืออาหรับ

ลิงก์จะได้รับชื่อสำหรับการช่วยเหลือพิเศษจากเนื้อหาข้อความเป็นหลัก ซึ่งคล้ายกับปุ่ม เคล็ดลับดีๆ ในการสร้างลิงก์คือใส่ข้อความที่มีความหมายมากที่สุดลงในลิงก์แทนที่จะใส่คำเชื่อม เช่น "ที่นี่" หรือ "อ่านเพิ่มเติม"

มีคำอธิบายไม่เพียงพอ
Check out our guide to web performance <a href="/guide">here</a>.
เนื้อหาที่เป็นประโยชน์
Check out <a href="/guide">our guide to web performance</a>.

ตรวจสอบว่าภาพเคลื่อนไหวทริกเกอร์เลย์เอาต์หรือไม่

ภาพเคลื่อนไหวที่ย้ายองค์ประกอบโดยใช้อย่างอื่นที่ไม่ใช่ transform มีแนวโน้มที่จะทำงานช้า ในตัวอย่างต่อไปนี้ เราได้รับผลลัพธ์ภาพเดียวกันจากภาพเคลื่อนไหว top และ left และใช้ transform

ไม่ควรทำ
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

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

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

คุณสามารถทดสอบได้ในตัวอย่าง Glitch 2 รายการต่อไปนี้ และสำรวจประสิทธิภาพโดยใช้เครื่องมือสำหรับนักพัฒนาเว็บ

เมื่อใช้มาร์กอัปเดียวกันนี้ เราสามารถแทนที่ padding-top: 56.25% ด้วย aspect-ratio: 16 / 9 โดยตั้งค่า aspect-ratio เป็นอัตราส่วน width / height ที่ระบุ

การใช้ padding-top
.container {
  width: 100%;
  padding-top: 56.25%;
}
การใช้ aspect-ratio
.container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

การใช้ aspect-ratio แทน padding-top นั้นชัดเจนกว่ามาก และไม่ต้องแก้ไขพร็อพเพอร์ตี้การเว้นวรรคเพื่อทําสิ่งที่อยู่นอกขอบเขตปกติ

ใช่ ฉันใช้ reduce เพื่อต่อเชื่อมลำดับของ Promise ฉันฉลาดมาก แต่นี่เป็นการเขียนโค้ดที่ฉลาดมากซึ่งคุณควรหลีกเลี่ยง

อย่างไรก็ตาม เมื่อแปลงโค้ดข้างต้นเป็นฟังก์ชันที่ทำงานแบบไม่พร้อมกัน คุณอาจเรียงลำดับการทำงานมากเกินไป

ไม่แนะนำเนื่องจากมีลำดับมากเกินไป
async function logInOrder(urls) {
  for (const url of urls) {
    const response = await fetch(url);
    console.log(await response.text());
  }
}
ดูเรียบร้อยกว่ามาก แต่การดึงข้อมูลครั้งที่ 2 จะไม่เริ่มต้นจนกว่าการดึงข้อมูลครั้งแรกจะอ่านจนจบ และอื่นๆ ซึ่งช้ากว่าตัวอย่าง Promise ที่ดึงข้อมูลพร้อมกัน แต่โชคดีที่ยังมีวิธีกลางๆ ที่เหมาะเจาะ
แนะนํา - วางขนานกัน
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);
  }
}
ในตัวอย่างนี้ ระบบจะดึงข้อมูลและอ่าน URL พร้อมกัน แต่จะใช้บิต "อัจฉริยะ" reduce แทนการวนซ้ำ for มาตรฐานที่อ่านได้และน่าเบื่อ

การเขียนพร็อพเพอร์ตี้ที่กำหนดเองของ Houdini

ต่อไปนี้คือตัวอย่างการตั้งค่าพร็อพเพอร์ตี้ที่กำหนดเอง (ลองนึกถึงตัวแปร CSS) แต่ตอนนี้มีไวยากรณ์ (ประเภท) ค่าเริ่มต้น (ค่าสำรอง) และบูลีนการสืบทอด (รับค่ามาจากพร็อพเพอร์ตี้หลักหรือไม่) วิธีปัจจุบันในการทำเช่นนี้คือผ่าน CSS.registerProperty() ใน JavaScript แต่ Chromium 85 ขึ้นไปจะรองรับไวยากรณ์ @property ในไฟล์ CSS ดังนี้

ไฟล์ JavaScript แยกต่างหาก (Chromium 78)
CSS.registerProperty({
  name: '--colorPrimary',
  syntax: '',
  initialValue: 'magenta',
  inherits: false
});
รวมอยู่ในไฟล์ CSS (Chromium 85)
@property --colorPrimary {
  syntax: '';
  initial-value: magenta;
  inherits: false;
}

ตอนนี้คุณเข้าถึง --colorPrimary ได้เช่นเดียวกับพร็อพเพอร์ตี้ที่กำหนดเองอื่นๆ ของ CSS ผ่าน var(--colorPrimary) แต่ความแตกต่างของที่นี่คือ --colorPrimary ไม่ได้อ่านเป็นสตริงเท่านั้น มีข้อมูล

CSS backdrop-filter ใช้เอฟเฟกต์อย่างน้อย 1 รายการกับองค์ประกอบที่โปร่งแสงหรือโปร่งใส โปรดดูภาพด้านล่างเพื่อให้เข้าใจ

ไม่มีความโปร่งใสของพื้นหน้า
สามเหลี่ยมวางซ้อนกันบนวงกลม มองไม่เห็นวงกลมผ่านสามเหลี่ยม
.frosty-glass-pane {
  backdrop-filter: blur(2px);
}
ความโปร่งใสของเบื้องหน้า
สามเหลี่ยมวางซ้อนกันบนวงกลม รูปสามเหลี่ยมเป็นแบบโปร่งแสงเพื่อให้เห็นวงกลมผ่านรูปสามเหลี่ยม
.frosty-glass-pane {
  opacity: .9;
  backdrop-filter: blur(2px);
}

รูปภาพด้านซ้ายแสดงลักษณะที่องค์ประกอบที่ซ้อนกันจะแสดงผลหากไม่ได้ใช้หรือระบบไม่รองรับ backdrop-filter รูปภาพทางด้านขวาใช้เอฟเฟกต์เบลอโดยใช้ backdrop-filter โปรดสังเกตว่าใช้ opacity เพิ่มเติมจาก backdrop-filter หากไม่มี opacity ก็จะไม่มีสิ่งใดให้เบลอ คงไม่ต้องอธิบายให้มากความว่าหากตั้งค่า opacity เป็น 1 (ทึบแสงโดยสมบูรณ์) จะไม่มีผลกับพื้นหลัง

อย่างไรก็ตาม beforeunload มีการใช้งานที่ถูกต้องตามกฎหมาย ซึ่งต่างจากเหตุการณ์ unload เช่น เมื่อต้องการเตือนผู้ใช้ว่ามีการเปลี่ยนแปลงที่ยังไม่ได้บันทึกซึ่งจะหายไปหากออกจากหน้า ในกรณีนี้ เราขอแนะนําให้เพิ่มbeforeunload Listeners เฉพาะเมื่อผู้ใช้มีการเปลี่ยนแปลงที่ไม่ได้บันทึกไว้ แล้วนําออกทันทีหลังจากบันทึกการเปลี่ยนแปลงที่ไม่ได้บันทึกไว้

ไม่ควรทำ
window.addEventListener('beforeunload', (event) => {
  if (pageHasUnsavedChanges()) {
    event.preventDefault();
    return event.returnValue = 'Are you sure you want to exit?';
  }
});
โค้ดด้านบนจะเพิ่มผู้ฟัง beforeunload โดยไม่มีข้อกําหนด
ควรทำ
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);
});
โค้ดด้านบนจะเพิ่มโปรแกรมฟัง beforeunload เฉพาะเมื่อจําเป็นเท่านั้น (และนําออกเมื่อไม่จําเป็น)

ลดการใช้ Cache-Control: no-store

Cache-Control: no-store คือส่วนหัว HTTP ที่เว็บเซิร์ฟเวอร์สามารถตั้งค่าในการตอบกลับเพื่อสั่งให้เบราว์เซอร์ไม่จัดเก็บการตอบกลับไว้ในแคช HTTP ควรใช้กับทรัพยากรที่มีข้อมูลที่ละเอียดอ่อนของผู้ใช้ เช่น หน้าเว็บที่ต้องเข้าสู่ระบบ

เอลิเมนต์ fieldset ซึ่งมีกลุ่มอินพุตแต่ละกลุ่ม (.fieldset-item) ใช้ gap: 1px เพื่อสร้างเส้นขอบบางๆ ระหว่างองค์ประกอบ ไม่มีวิธีแก้ปัญหาเส้นขอบที่ยุ่งยาก

ช่องว่างที่กรอกข้อมูลแล้ว
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
เทคนิคเส้นขอบ
.grid {
  display: grid;

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

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

การตัดตารางกริดให้พอดี

เลย์เอาต์ที่ซับซ้อนที่สุดคือเลย์เอาต์มาโคร ซึ่งเป็นเลย์เอาต์เชิงตรรกะระหว่าง <main> กับ <form>

อินพุต
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
ป้ายกำกับ
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

เอลิเมนต์ fieldset ซึ่งมีกลุ่มอินพุตแต่ละกลุ่ม (.fieldset-item) ใช้ gap: 1px เพื่อสร้างเส้นขอบบางๆ ระหว่างองค์ประกอบ ไม่จำเป็นต้องใช้วิธีแก้ปัญหาเส้นขอบที่ซับซ้อน

ช่องว่างที่กรอกข้อมูลแล้ว
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
เทคนิคเส้นขอบ
.grid {
  display: grid;

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

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

เลย์เอาต์แท็บ <header>

เลย์เอาต์ถัดไปเกือบจะเหมือนกัน ฉันใช้ Flex เพื่อสร้างการจัดเรียงแนวตั้ง

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 ควรเลื่อนไปทางแนวนอนพร้อมกับกลุ่มลิงก์ และเลย์เอาต์ส่วนหัวนี้ช่วยสร้างเวทีนั้น ไม่มีองค์ประกอบที่มีตำแหน่งแบบสัมบูรณ์

Gentle Flex เป็นกลยุทธ์การเน้นเฉพาะที่แท้จริง การดำเนินการนี้นุ่มนวลและเบาเนื่องจากไม่เหมือน place-content: center ตรงที่จะไม่มีการเปลี่ยนขนาดกล่องของช่องสำหรับเด็กในระหว่างการจัดกึ่งกลาง ระบบจะจัดวางรายการทั้งหมดซ้อนกัน จัดกึ่งกลาง และเว้นระยะห่างอย่างเบาที่สุด

.gentle-flex {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1ch;
}
ข้อดี
  • จัดการเฉพาะการจัดแนว ทิศทาง และการเผยแพร่
  • แก้ไขและดูแลรักษาได้ในที่เดียว
  • Gap รับประกันการเว้นระยะห่างเท่าๆ กันระหว่างเด็ก n คน
ข้อเสีย
  • โค้ดหลายบรรทัด

เหมาะสำหรับเลย์เอาต์ทั้งแบบมหภาคและแบบไมโคร

การใช้งาน

gap ยอมรับความยาวหรือเปอร์เซ็นต์ CSS เป็นค่า

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


คุณสามารถส่ง Gap ความยาว 1 ซึ่งจะใช้สำหรับทั้งแถวและคอลัมน์

ชวเลข
.grid {
  display: grid;
  gap: 10px;
}
ตั้งค่าทั้งแถวและคอลัมน์พร้อมกันในครั้งเดียว
ขยายแล้ว
.grid {
  display: grid;
  row-gap: 10px;
  column-gap: 10px;
}


คุณสามารถส่ง Gap ความยาว 2 รายการ ซึ่งจะใช้สำหรับแถวและคอลัมน์

ชวเลข
.grid {
  display: grid;
  gap: 10px 5%;
}
ตั้งค่าทั้งแถวและคอลัมน์แยกกันพร้อมกัน
ขยายแล้ว
.grid {
  display: grid;
  row-gap: 10px;
  column-gap: 5%;
}