การสร้างคอมโพเนนต์แถบเลื่อนสื่อ

ภาพรวมพื้นฐานของวิธีสร้าง Scroll View แนวนอนที่ปรับเปลี่ยนตามอุปกรณ์สำหรับทีวี โทรศัพท์ เดสก์ท็อป ฯลฯ

ในโพสต์นี้ ฉันต้องการแชร์ความคิดเกี่ยวกับวิธีสร้างการเลื่อนแนวนอน ในการใช้งานเว็บที่เรียบง่าย ตอบสนองความต้องการ เข้าถึงได้ และทำงานข้ามได้ เบราว์เซอร์และแพลตฟอร์ม (เช่น ทีวี) ทดลองใช้ การสาธิต

สาธิต

หากต้องการดูวิดีโอ โปรดใช้โพสต์นี้ในเวอร์ชัน YouTube

ภาพรวม

เราจะสร้างรูปแบบการเลื่อนแนวนอนสำหรับโฮสต์ภาพขนาดย่อของ สื่อหรือผลิตภัณฑ์ คอมโพเนนต์เริ่มต้นเป็นรายการ <ul> ที่เรียบง่ายแต่ ด้วย CSS เพื่อมอบประสบการณ์การเลื่อนที่ราบรื่นและน่าพึงพอใจ รูปภาพและจัดพอดีกับตารางกริด มีการเพิ่ม JavaScript เพื่ออำนวยความสะดวก การโต้ตอบกับดัชนีการนำทาง ช่วยให้ผู้ใช้แป้นพิมพ์ข้ามผ่านของรายการกว่า 100 รายการได้ นอกจากนี้คุณยังใช้คำค้นหาสื่อทดลอง prefers-reduced-data เพื่อเปลี่ยน เครื่องมือเลื่อนสื่อแบบเลื่อนผ่านชื่อได้ไม่ซับซ้อน

เริ่มต้นด้วยมาร์กอัปที่เข้าถึงได้

เครื่องมือเลื่อนสื่อประกอบด้วยคอมโพเนนต์หลัก 2 ส่วน ได้แก่ ชุดรายการที่ประกอบด้วยรายการ ต ในรูปแบบที่ง่ายที่สุด สามารถเดินทางได้ทั่วโลก และ ที่ทุกคนใช้งาน ผู้ใช้ที่ไปถึงหน้านี้สามารถเรียกดูรายการและคลิกลิงก์ได้ เพื่อดูรายการ นี่คือฐานที่เข้าถึงได้ง่าย

ส่งรายการที่มีองค์ประกอบ <ul>:

<ul class="horizontal-media-scroller">
  <li></li>
  <li></li>
  <li></li>
  ...
<ul>

ทำให้รายการโต้ตอบด้วยองค์ประกอบ <a>

<li>
  <a href="#">
    ...
  </a>
</li>

ใช้องค์ประกอบ <figure> เพื่อแสดงภาพและคําบรรยายภาพอย่างมีความหมาย:

<figure>
  <picture>
    <img alt="..." loading="lazy" src="https://picsum.photos/500/500?1">
  </picture>
  <figcaption>Legends</figcaption>
</figure>

โปรดสังเกตแอตทริบิวต์ alt และ loading ใน <img> ข้อความแสดงแทนสำหรับสื่อ คือโอกาสด้าน UX ที่จะช่วยให้ภาพขนาดย่อมีบริบทเพิ่มเติม หรือ ข้อความสำรองหากรูปภาพไม่โหลด หรือมี UI แบบเสียงพูดสำหรับผู้ใช้ ที่ต้องอาศัยเทคโนโลยีความช่วยเหลือพิเศษ เช่น โปรแกรมอ่านหน้าจอ ดูข้อมูลเพิ่มเติมกับ Five golden กฎสำหรับ Alt ที่เป็นไปตามข้อกำหนด ข้อความ

แอตทริบิวต์ loading ยอมรับคีย์เวิร์ด lazy เป็นวิธีส่งสัญญาณรูปภาพนี้ ควรดึงข้อมูลแหล่งที่มาเมื่อรูปภาพอยู่ภายในวิวพอร์ตเท่านั้น ประเภท เหมาะมากสำหรับรายการขนาดใหญ่ เพราะผู้ใช้จะดาวน์โหลดเฉพาะภาพของรายการที่พวกเขา เลื่อนเข้ามาในมุมมอง

รองรับค่ากำหนดรูปแบบสีของผู้ใช้

ใช้ color-scheme เป็นแท็ก <meta> เพื่อส่งสัญญาณให้เบราว์เซอร์ทราบว่าหน้าเว็บของคุณ ต้องการสไตล์ User Agent ที่มีให้ทั้งสว่างและมืด เป็นโหมดมืดฟรี หรือโหมดสว่าง ขึ้นอยู่กับว่าคุณมองอย่างไร

<meta name="color-scheme" content="dark light">

เมตาแท็กจะให้สัญญาณเร็วที่สุดเท่าที่จะเป็นไปได้ ดังนั้นเบราว์เซอร์ เลือกสีแคนวาสเริ่มต้นแบบสีเข้มหากผู้ใช้ต้องการธีมมืด ซึ่งหมายความว่าการไปยังหน้าต่างๆ ของเว็บไซต์จะไม่แสดงพื้นที่สีขาว ระหว่างการโหลด ธีมสีเข้มที่ราบรื่นระหว่างการโหลด ซึ่งดีกว่ามาก ดวงตา

ดูข้อมูลเพิ่มเติมจาก Thomas Steiner ที่ https://web.dev/color-scheme/.

เพิ่มเนื้อหา

จากโครงสร้างเนื้อหาข้างต้นของ ul > li > a > figure > picture > img งานต่อไปคือการเพิ่มรูปภาพและชื่อเพื่อเลื่อนดู เราได้เตรียมการสาธิตไว้แล้ว รูปภาพและข้อความตัวยึดตำแหน่งแบบคงที่ แต่คุณสามารถเพิ่มประสิทธิภาพได้จาก แหล่งข้อมูลที่ชื่นชอบ

เพิ่มสไตล์ด้วย CSS

ตอนนี้ถึงเวลาที่ CSS จะนำรายการเนื้อหาทั่วไปนี้มาเปลี่ยนเป็น ประสบการณ์การใช้งาน Netflix, App Store รวมถึงเว็บไซต์และแอปอื่นๆ อีกมากมายใช้แนวนอน พื้นที่ที่เลื่อนได้เพื่อแพ็ควิวพอร์ตด้วยหมวดหมู่และตัวเลือก

การสร้างเลย์เอาต์แถบเลื่อน

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

2 ครั้ง
แสดงแถวแบบเลื่อน โดยรูปหนึ่งไม่มีจุดไข่ปลา ซึ่งหมายความว่าแต่ละรูปสูงกว่า
ต้องอ่านได้ชัดเจน อีกรายการหนึ่งสั้นกว่า และเนื้อหาหลายรายการจะถูกตัดออกด้วย
จุดไข่ปลา

คอนเทนเนอร์อนุญาตให้ลบล้างขนาดคอลัมน์โดยระบุขนาดเริ่มต้นเป็น คุณสมบัติที่กำหนดเอง เลย์เอาต์แบบตารางกริดนี้อิงตามขนาดของคอลัมน์ จัดการระยะห่างและทิศทางเท่านั้น

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2); /* parent owned value for children to be relative to*/
  margin: 0;
}

จากนั้นองค์ประกอบ <picture> จะใช้คุณสมบัติที่กำหนดเองเพื่อสร้างสัดส่วนภาพฐานซึ่งก็คือช่องต่อไปนี้

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  & picture {
    inline-size: var(--size);
    block-size: var(--size);
  }
}

ใช้รูปแบบเล็กๆ น้อยๆ เพิ่มเติมเพื่อทำให้ตัวเลื่อนสื่อสมบูรณ์:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  & > li {
    display: inline-block; /* removes the list-item bullet */
  }

  & picture {
    inline-size: var(--size);
    block-size: var(--size);
  }
}

การตั้งค่า overflow เป็นการตั้งค่า <ul> เพื่ออนุญาตการเลื่อนและการนําทางด้วยแป้นพิมพ์ ผ่านรายการ องค์ประกอบย่อย <li> โดยตรงแต่ละรายการจะถูกนำออก ::marker โดยการรับ inline-block ประเภทจอแสดงผลใหม่

แต่รูปภาพยังไม่ตอบสนอง และปรากฏขึ้นทันทีตั้งแต่เริ่มต้น อยู่ด้านใน ให้เชื่องัดด้วยขนาด ความพอดี รูปแบบเส้นขอบ และ การไล่ระดับสีของพื้นหลังสำหรับการโหลดแบบ Lazy Loading

img {
  /* smash into whatever box it's in */
  inline-size: 100%;
  block-size: 100%;

  /* don't squish but do cover the space */
  object-fit: cover;

  /* soften the edges */
  border-radius: 1ex;
  overflow: hidden;

  /* if empty, show a gradient placeholder */
  background-image:
    linear-gradient(
      to bottom,
      hsl(0 0% 40%),
      hsl(0 0% 20%)
    );
}

ระยะห่างจากขอบในการเลื่อน

การจัดแนวตามเนื้อหาในหน้า รวมถึงพื้นที่พื้นผิวแบบเลื่อนจากขอบถึงขอบ ที่สำคัญต่อการผสมผสานที่ลงตัว และมีองค์ประกอบน้อยที่สุด

เพื่อให้ได้เลย์เอาต์การเลื่อนแบบขอบถึงขอบซึ่งสอดคล้องกับตัวอักษรของเรา และเส้นเลย์เอาต์ ให้ใช้ padding ที่ตรงกับ scroll-padding ดังนี้

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  padding-inline: var(--gap);
  scroll-padding-inline: var(--gap);
  padding-block: calc(var(--gap) / 2); /* make space for scrollbar and focus outline */
}

แก้ไขข้อบกพร่องด้านระยะห่างจากขอบของการเลื่อนในแนวนอน ข้อมูลข้างต้นแสดงให้เห็นว่าสามารถ ใส่คอนเทนเนอร์แบบเลื่อน แต่ยังมีปัญหาด้านความเข้ากันได้ที่เด่นชัด (แต่ใน Chromium 91 ขึ้นไป) โปรดดู ที่นี่สักเล็กน้อย ของประวัติศาสตร์ แต่สรุปก็คือ ระยะห่างจากขอบมักจะไม่ได้รับการนำมาพิจารณาเสมอไป สำหรับ ในมุมมองการเลื่อน

ต
มีการไฮไลต์ที่ส่วนท้ายในบรรทัดของรายการสุดท้าย ซึ่งแสดง
ระยะห่างจากขอบและองค์ประกอบมีความกว้างเท่ากับการสร้างการปรับแนวที่ต้องการ

เพื่อหลอกให้เบราว์เซอร์ใส่ระยะห่างจากขอบท้ายแถบเลื่อน ฉันจะ กำหนดเป้าหมายรูปสุดท้ายในแต่ละรายการ แล้วเพิ่มองค์ประกอบสมมติที่เป็นค่า ของระยะห่างจากขอบที่ต้องการ

.horizontal-media-scroller > li:last-of-type figure {
  position: relative;

  &::after {
    content: "";
    position: absolute;

    inline-size: var(--gap);
    block-size: 100%;

    inset-block-start: 0;
    inset-inline-end: calc(var(--gap) * -1);
  }
}

การใช้คุณสมบัติเชิงตรรกะทำให้ตัวเลื่อนสื่อทำงานได้ในโหมดการเขียน และทิศทางของเอกสาร

การสแนปการเลื่อน

คอนเทนเนอร์แบบเลื่อนที่มีรายการเพิ่มเติมอาจกลายเป็นวิวพอร์ตแบบสแนปที่มี CSS 1 บรรทัด จากนั้นจะอยู่ในหน้าย่อยเพื่อระบุวิธีที่ต้องการให้สอดคล้องกับวิวพอร์ตนั้น

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  padding-inline: var(--gap);
  scroll-padding-inline: var(--gap);
  padding-block-end: calc(var(--gap) / 2);

  scroll-snap-type: inline mandatory;

  & figure {
    scroll-snap-align: start;
  }
}

โฟกัส

แรงบันดาลใจสำหรับคอมโพเนนต์นี้ มาจากความนิยมที่สูงมากในทีวี ใน App Store และอื่นๆ แพลตฟอร์มวิดีโอเกมมากมายใช้ตัวเลื่อนสื่อ คล้ายกับเค้าโครงนี้เป็นเลย์เอาต์หน้าจอหลัก โฟกัสคือ UX ที่ยิ่งใหญ่ ที่นี่ ไม่ใช่แค่ส่วนเล็กๆ ที่เพิ่มเข้ามา ลองนึกภาพว่าคุณใช้แถบเลื่อนสื่อจาก โซฟาของคุณด้วยรีโมต ลองเพิ่มประสิทธิภาพการโต้ตอบเล็กๆ น้อยๆ ดังนี้

.horizontal-media-scroller a {
  outline-offset: 12px;

  &:focus {
    outline-offset: 7px;
  }

  @media (prefers-reduced-motion: no-preference) {
    & {
      transition: outline-offset .25s ease;
    }
  }
}

การทำเช่นนี้จะทำให้รูปแบบโครงร่างโฟกัส 7px อยู่ห่างจากกล่อง ทำให้เห็นภาพชัดเจน พื้นที่ทำงาน หากผู้ใช้ไม่มีค่ากำหนดการเคลื่อนไหวเกี่ยวกับการลดการเคลื่อนไหว ออฟเซ็ต เปลี่ยนแล้ว โดยให้การเคลื่อนไหวเล็กๆ น้อยๆ กับกิจกรรมที่ต้องการโฟกัส

ดัชนีเส้นทาง

ผู้ใช้เกมแพดและแป้นพิมพ์ต้องให้ความสนใจเป็นพิเศษในรายการเกมแพด เนื้อหาและตัวเลือกที่เลื่อนดูได้ รูปแบบที่พบบ่อยในการแก้ไขปัญหานี้เรียกว่า ดัชนีการเดินทาง เกิดขึ้นเมื่อ คอนเทนเนอร์ของรายการถูกโฟกัสด้วยแป้นพิมพ์ แต่มีผู้เผยแพร่โฆษณาย่อย 1 รายเท่านั้นที่สามารถถือโฟกัสได้ ต่อครั้ง รายการหนึ่งๆ ที่สามารถโฟกัสได้ในแต่ละช่วงเวลาออกแบบมาเพื่อช่วยให้ ข้ามรายการสิ่งของจำนวนมากได้ ซึ่งตรงข้ามกับการกด Tab 50+ กว่าจะถึงตอนจบ

มีสินค้า 300 รายการในแถบเลื่อนแรกของเดโม เราทำได้ดีกว่า นักเรียนจะข้ามผ่านทั้งหมดไปยังส่วนถัดไป

JavaScript จำเป็นต้องสังเกตเหตุการณ์ของแป้นพิมพ์และการโฟกัสเพื่อสร้างประสบการณ์นี้ กิจกรรม ฉันได้สร้างไลบรารีโอเพนซอร์สขนาดเล็กบน npm เพื่อช่วยทำให้ผู้ใช้รายนี้ บรรลุได้ง่าย วิธีใช้ปุ่มสำหรับแถบเลื่อน 3 อย่างมีดังนี้

import {rovingIndex} from 'roving-ux';

rovingIndex({
  element: someElement
});

การสาธิตนี้จะค้นหาเอกสารสำหรับตัวเลื่อนและแต่ละรายการเรียกฟังก์ชัน rovingIndex() ส่ง rovingIndex() องค์ประกอบไปเพื่อออกเดินทาง เช่น คอนเทนเนอร์รายการ และตัวเลือกการค้นหาเป้าหมายในกรณีที่ เป้าหมายโฟกัสไม่ใช่องค์ประกอบสืบทอดโดยตรง

document.querySelectorAll('.horizontal-media-scroller')
  .forEach(scroller =>
    rovingIndex({
      element: scroller,
      target: 'a',
}))

หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับเอฟเฟกต์นี้ โปรดดูที่ไลบรารีโอเพนซอร์ส roving-ux

สัดส่วนภาพ

ขณะที่เขียนโพสต์นี้ ฝ่ายสนับสนุน aspect-ratio อยู่ด้านหลัง การตั้งค่าสถานะใน Firefox แต่ใช้ได้ในเบราว์เซอร์ Chromium หรือ Set-top box ตั้งแต่ เลย์เอาต์แบบตารางกริดของแถบเลื่อนสื่อจะระบุเฉพาะทิศทางและการเว้นระยะห่างเท่านั้น สามารถปรับขนาดได้ ภายในคิวรี่สื่อซึ่งฟีเจอร์จะตรวจสอบการรองรับสัดส่วนภาพ การเพิ่มประสิทธิภาพแบบต่อเนื่องเป็นการเลื่อนสื่อแบบไดนามิกมากขึ้น

ต
กล่องที่มีสัดส่วนภาพ 4:4 แสดงอยู่ถัดจากอัตราส่วนการออกแบบอื่นๆ ที่ใช้ 16:9
และ 4:3

@supports (aspect-ratio: 1) {
  .horizontal-media-scroller figure > picture {
    inline-size: auto; /* for a block-size driven ratio */
    aspect-ratio: 1; /* boxes by default */

    @nest section:nth-child(2) & {
      aspect-ratio: 16/9;
    }

    @nest section:nth-child(3) & {
      /* double the size of the others */
      block-size: calc(var(--size) * 2);
      aspect-ratio: 4/3;

      /* adjust size to fit more items into the viewport */
      @media (width <= 480px) {
        block-size: calc(var(--size) * 1.5);
      }
    }
  }
}

หากเบราว์เซอร์รองรับไวยากรณ์ aspect-ratio รูปภาพแถบเลื่อนของสื่อจะเป็น อัปเกรดเป็นการปรับขนาด aspect-ratio แล้ว ใช้ไวยากรณ์การซ้อนฉบับร่างรูปภาพแต่ละรูป จะเปลี่ยนอัตราส่วนกว้างยาวโดยพิจารณาตามแถวแรก แถวที่สอง หรือแถวที่สาม ไวยากรณ์ nest ยังอนุญาตให้ตั้งค่าบางอย่าง การปรับวิวพอร์ตตรงจุดนั้นด้วยตรรกะการปรับขนาดอื่นๆ

เมื่อใช้ CSS ดังกล่าว ฟีเจอร์นี้ใช้ได้กับเครื่องมือเบราว์เซอร์อื่นๆ เพิ่มเติม จัดการได้ แต่เลย์เอาต์จะดึงดูดสายตาได้มากขึ้น

ต้องการข้อมูลที่ลดน้อยลง

แม้ว่าเทคนิคถัดไปนี้จะใช้ได้ หลังธงใน Canary ฉันต้องการแชร์ว่าฉันจะประหยัดเวลาในการโหลดหน้าเว็บลงได้อย่างมากได้อย่างไร กับ CSS ไม่กี่บรรทัด คิวรี่สื่อ prefers-reduced-data จาก ระดับ 5 อนุญาตให้ถามได้ว่าอุปกรณ์อยู่ใน สถานะข้อมูลที่ลดลง เช่น โหมดประหยัดอินเทอร์เน็ต หากใช่ ฉันสามารถแก้ไข เอกสาร และในกรณีนี้ ให้ซ่อนภาพ

ALT_TEXT_HERE

figure {
  @media (prefers-reduced-data: reduce) {
    & {
      min-inline-size: var(--size);

      & > picture {
        display: none;
      }
    }
  }
}

เนื้อหายังไปยังส่วนต่างๆ ได้แต่ไม่มีต้นทุนของรูปภาพขนาดใหญ่ ดาวน์โหลดแล้ว นี่คือเว็บไซต์ก่อนที่จะเพิ่ม CSS ของ prefers-reduced-data

(คำขอ 7 รายการ, ทรัพยากร 100 KB ใน 131 มิลลิวินาที)

ALT_TEXT_HERE

ประสิทธิภาพของเว็บไซต์หลังจากเพิ่ม CSS ของ prefers-reduced-data แล้วมีดังนี้

ALT_TEXT_HERE

(คำขอ 71 รายการ, ทรัพยากร 1.2 MB ใน 1.07 วินาที)

คำขอน้อยลง 64 รายการ ซึ่งก็คือรูปภาพประมาณ 60 ภาพภายในวิวพอร์ต (การทดสอบที่ทำ บนหน้าจอกว้าง) ของแท็บเบราว์เซอร์นี้ การโหลดหน้าเว็บที่เพิ่มขึ้นประมาณ 80% และ 10% ของข้อมูลที่ส่งผ่านสาย CSS ที่มีประสิทธิภาพทีเดียว

บทสรุป

เมื่อรู้แล้วว่าฉันทำแบบนั้นได้อย่างไร คุณจะทำอย่างไร 🙂

มาเพิ่มความหลากหลายให้กับแนวทางของเราและเรียนรู้วิธีทั้งหมดในการสร้างเนื้อหาบนเว็บกัน สร้าง Codepen หรือโฮสต์การสาธิตของคุณเอง ทวีตฉันด้วย แล้วฉันจะเพิ่มลงใน ส่วนรีมิกซ์ของชุมชนด้านล่าง

แหล่งที่มา

รีมิกซ์ในชุมชน

ยังไม่มีอะไรให้ดูที่นี่!