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

แอตทริบิวต์ 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 ที่ระบุ

การใช้ระยะห่างจากขอบบน
.container {
  width: 100%;
  padding-top: 56.25%;
}
การใช้สัดส่วนภาพ
.container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

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

ใช่แล้ว ฉันใช้ reduce เพื่อเชื่อมโยงสัญญาตามลำดับ ฉันฉลาดมาก แต่นี่เป็นการเขียนโค้ดที่ชาญฉลาด คุณจะมีโอกาสมากขึ้นถ้าไม่ได้เขียนโค้ด

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

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

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

นี่คือตัวอย่างของการตั้งค่าพร็อพเพอร์ตี้ที่กำหนดเอง (เช่น ตัวแปร CSS) แต่ตอนนี้มีไวยากรณ์ (ประเภท) ค่าเริ่มต้น (วิดีโอสำรอง) และบูลีนที่รับค่ามา (ค่าดังกล่าวสืบทอดค่ามาจากระดับบนสุดหรือไม่) วิธีปัจจุบันในการดำเนินการดังกล่าวคือผ่านทาง CSS.registerProperty() ใน JavaScript แต่ใน Chromium 85 ขึ้นไปไฟล์ CSS จะรองรับไวยากรณ์ @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 ตรงที่ เช่น เมื่อต้องการเตือนผู้ใช้ว่าการเปลี่ยนแปลงที่ไม่ได้บันทึก การเปลี่ยนแปลงเหล่านั้นจะสูญหายหากออกจากหน้าเว็บไป ในกรณีนี้ ขอแนะนำให้คุณเพิ่ม Listener beforeunload เท่านั้นเมื่อผู้ใช้มีการเปลี่ยนแปลงที่ยังไม่ได้บันทึก และลบออกทันทีหลังจากที่บันทึกการเปลี่ยนแปลงที่ยังไม่ได้บันทึก

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

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

การใช้งาน

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

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


สามารถใช้ช่องว่างได้ 1 ช่วงซึ่งจะใช้กับทั้งแถวและคอลัมน์

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


ช่องว่างสามารถส่งผ่านความยาวได้ 2 ช่วง ซึ่งจะใช้สำหรับแถวและคอลัมน์

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