การสร้างคอมโพเนนต์ปุ่มการทำงานแบบลอย (FAB)

ภาพรวมพื้นฐานของวิธีสร้างคอมโพเนนต์ FAB ที่ปรับเปลี่ยนสี ปรับเปลี่ยนตามอุปกรณ์ และเข้าถึงได้

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

หากชอบวิดีโอ นี่คือโพสต์นี้เวอร์ชัน YouTube

ภาพรวม

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

องค์ประกอบและรูปแบบ

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

คอนเทนเนอร์ FAB

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

มาร์กอัป FAB

เริ่มต้นด้วยคลาส .fabs สำหรับ CSS เพื่อความมีสไตล์ แล้วเพิ่ม role="group" และ aria-label เพื่อที่ว่าไม่ใช่แค่คอนเทนเนอร์ทั่วไป แต่ยังตั้งชื่อแล้วมีประโยชน์ด้วย

<div class="fabs" role="group" aria-label="Floating action buttons">
  <!-- buttons will go here -->
</div>

รูปแบบ FAB

เพื่อให้ FAB สะดวก ตัวมันจะติดอยู่ในวิวพอร์ตตลอดเวลา นี่เป็นกรณีการใช้งานที่ดีสำหรับตำแหน่ง fixed ในตำแหน่งวิวพอร์ตนี้ ผมเลือกใช้ inset-block และ inset-inline ดังนั้นตำแหน่งจะเสริมโหมดเอกสารของผู้ใช้ เช่น ขวาไปซ้ายหรือซ้ายไปขวา นอกจากนี้ พร็อพเพอร์ตี้ที่กำหนดเองยังใช้เพื่อป้องกันการเกิดซ้ำและทำให้มีระยะห่างจากขอบด้านล่างและด้านข้างของวิวพอร์ตเท่ากันด้วย

.fabs {
  --_viewport-margin: 2.5vmin;

  position: fixed;
  z-index: var(--layer-1);

  inset-block: auto var(--_viewport-margin);
  inset-inline: auto var(--_viewport-margin);
}

ต่อไปฉันจะกำหนดการแสดงผลคอนเทนเนอร์ flex และเปลี่ยนทิศทางการจัดวางเป็น column-reverse ซึ่งจะจัดกลุ่มรายการย่อยซ้อนทับกัน (คอลัมน์) และยังกลับลำดับการแสดงอีกด้วย โหมดนี้มีเอฟเฟกต์ในการทำให้องค์ประกอบที่โฟกัสได้รายการแรกกลายเป็นองค์ประกอบด้านล่างแทนที่จะเป็นด้านบนสุด ซึ่งเป็นจุดที่โฟกัสได้ตามปกติต่อเอกสาร HTML การย้อนกลับลำดับภาพเป็นการรวมประสบการณ์การใช้งานทั้งสำหรับผู้ใช้ที่เห็นและแป้นพิมพ์ เนื่องจากการจัดรูปแบบการดำเนินการหลักที่มีขนาดใหญ่กว่าปุ่มขนาดเล็กจะบอกให้ผู้ใช้เห็นว่าเป็นการดำเนินการหลัก และผู้ใช้แป้นพิมพ์จะมุ่งเน้นการดำเนินการหลักเป็นรายการแรกในต้นฉบับ

ปุ่ม FAB 2 ปุ่มแสดงโดยมีเครื่องมือสำหรับนักพัฒนาเว็บวางซ้อนเลย์เอาต์แบบตารางกริด แสดงช่องว่างระหว่างเทมเพลตด้วยลายเส้น และแสดงความสูงและความกว้างที่คำนวณได้

.fabs {
  …

  display: flex;
  flex-direction: column-reverse;
  place-items: center;
  gap: var(--_viewport-margin);
}

ระบบจะจัดกึ่งกลางด้วย place-items และgap เพิ่มพื้นที่ระหว่างปุ่ม FAB ที่วางอยู่ในคอนเทนเนอร์

ปุ่ม FAB

ได้เวลาจัดรูปแบบปุ่มบางปุ่มให้ดูเหมือนลอยอยู่เหนือทุกอย่างแล้ว

FAB เริ่มต้น

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

มาร์กอัป FAB

องค์ประกอบ <button> คือตัวเลือกที่เหมาะสม เริ่มจากจุดนี้ก่อน เนื่องจากมาพร้อมกับประสบการณ์การใช้งาน เมาส์ การสัมผัส และแป้นพิมพ์ที่ยอดเยี่ยม ส่วนสําคัญที่สุดของมาร์กอัปนี้คือการซ่อนไอคอนจากผู้ใช้โปรแกรมอ่านหน้าจอที่มี aria-hidden="true" และเพิ่มข้อความป้ายกํากับที่จําเป็นลงในมาร์กอัป <button> เมื่อเพิ่มป้ายกำกับในกรณีเหล่านี้ ผมชอบเพิ่ม title ด้วย เพื่อให้ผู้ใช้เมาส์ได้รับข้อมูลเกี่ยวกับสิ่งที่ไอคอนจะสื่อสาร

<button data-icon="plus" class="fab" title="Add new action" aria-label="Add new action">
  <svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">...</svg>
</button>

รูปแบบ FAB

เรามาลองเปลี่ยนปุ่มให้เป็นปุ่มทรงกลมที่มีน้ำหนักเบาและมีลักษณะเป็นเงาๆ กันก่อน เพราะนี่คือคุณลักษณะสำคัญอย่างแรกของปุ่ม

.fab {
  --_size: 2rem;

  padding: calc(var(--_size) / 2);
  border-radius: var(--radius-round);
  aspect-ratio: 1;
  box-shadow: var(--shadow-4);
}

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

.fab {
  …

  /* light button and button hover */
  --_light-bg: var(--pink-6);
  --_light-bg-hover: var(--pink-7);

  /* dark button and button hover */
  --_dark-bg: var(--pink-4);
  --_dark-bg-hover: var(--pink-3);

  /* adaptive variables set to light by default */
  --_bg: var(--_light-bg);

  /* static icon colors set to the adaptive foreground variable */
  --_light-fg: white;
  --_dark-fg: black;
  --_fg: var(--_light-fg);

  /* use the adaptive properties on some styles */
  background: var(--_bg);
  color: var(--_fg);

  &:is(:active, :hover, :focus-visible) {
    --_bg: var(--_light-bg-hover);

    @media (prefers-color-scheme: dark) {
      --_bg: var(--_dark-bg-hover);
    }
  }

  /* if users prefers dark, set adaptive props to dark */
  @media (prefers-color-scheme: dark) {
    --_bg: var(--_dark-bg);
    --_fg: var(--_dark-fg);
  }
}

จากนั้นเพิ่มรูปแบบบางอย่างเพื่อช่วยให้ไอคอน SVG พอดีกับพื้นที่

.fab {
  …

  & > svg {
    inline-size: var(--_size);
    block-size: var(--_size);
    stroke-width: 3px;
  }
}

สุดท้าย นำไฮไลต์การแตะออกจากปุ่มเนื่องจากเราได้เพิ่มความคิดเห็นแบบภาพ สำหรับการโต้ตอบของเราเอง ดังนี้

.fab {
  -webkit-tap-highlight-color: transparent;
}

FAB ขนาดเล็ก

เป้าหมายของส่วนนี้คือการสร้างตัวแปรสำหรับปุ่ม FAB การทำให้ FAB บางรายการมีขนาดเล็กกว่าการกระทำเริ่มต้น เราสามารถส่งเสริมการดำเนินการที่ผู้ใช้ทำบ่อยที่สุดได้

มาร์กอัป Mini FAB

HTML นั้นเหมือนกับ FAB แต่เราเพิ่มคลาส ".mini" เพื่อให้ CSS ดึงความสนใจ ในตัวแปรเข้ามา

<button data-icon="heart" class="fab mini" title="Like action" aria-label="Like action">
  <svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">...</svg>
</button>
รูปแบบ FAB ขนาดเล็ก

ด้วยการใช้พร็อพเพอร์ตี้ที่กำหนดเอง การเปลี่ยนแปลงเพียงอย่างเดียวที่จำเป็นคือการปรับตัวแปร --_size

.fab.mini {
  --_size: 1.25rem;
}

ภาพหน้าจอของปุ่ม Fab 2 ปุ่มที่วางซ้อนกันและปุ่มด้านบนมีขนาดเล็กกว่าปุ่มที่อยู่ด้านล่าง

การช่วยเหลือพิเศษ

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

การสาธิตการโต้ตอบด้วยแป้นพิมพ์

เมื่อผู้ใช้โฟกัสที่คอนเทนเนอร์ FAB แล้ว เราได้เพิ่ม role="group" และ aria-label="floating action buttons" ซึ่งจะแจ้งให้ผู้ใช้โปรแกรมอ่านหน้าจอทราบเกี่ยวกับเนื้อหาที่พวกเขาโฟกัส ทางเชิงกลยุทธ์ ฉันวาง FAB เริ่มต้นก่อน เพื่อให้ผู้ใช้พบการทำงานหลักก่อน จากนั้นใช้ flex-direction: column-reverse; เพื่อเรียงลำดับปุ่มหลักที่ด้านล่าง ให้ใกล้กับนิ้วของผู้ใช้เพื่อให้เข้าถึงได้ง่าย นี่เป็นความสำเร็จที่ดี เพราะปุ่มเริ่มต้นนั้นสะดุดตา และเป็นปุ่มแรกสำหรับผู้ใช้แป้นพิมพ์ด้วย ทำให้ได้รับประสบการณ์ที่คล้ายกันมาก

สุดท้าย อย่าลืมซ่อนไอคอนจากผู้ใช้โปรแกรมอ่านหน้าจอและติดป้ายกำกับปุ่มดังกล่าวเพื่อไม่ให้เป็นปริศนา ซึ่งได้ทำใน HTML แล้วกับ aria-hidden="true" ใน <svg> และ aria-label="Some action" ใน <button>

แอนิเมชัน

เพิ่มภาพเคลื่อนไหวประเภทต่างๆ ได้เพื่อยกระดับประสบการณ์ของผู้ใช้ เช่นเดียวกับความท้าทายใน GUI อื่นๆ เราจะกำหนดคุณสมบัติที่กำหนดเอง 2 รายการเพื่อคงประสบการณ์การเคลื่อนไหวที่ลดลงและมอบประสบการณ์การเคลื่อนไหวเต็มรูปแบบ โดยค่าเริ่มต้น สไตล์จะถือว่าผู้ใช้ต้องการลดการเคลื่อนไหว จากนั้นการใช้ คิวรี่สื่อ prefers-reduced-motion จะสับเปลี่ยนค่าการเปลี่ยนไปเป็นแบบเต็มการเคลื่อนไหว

กลยุทธ์การเคลื่อนไหวที่ลดลงพร้อมคุณสมบัติที่กำหนดเอง

ระบบจะสร้างพร็อพเพอร์ตี้ที่กำหนดเอง 3 รายการใน CSS ต่อไปนี้ --_motion-reduced, --_motion-ok และ --_transition การเปลี่ยน 2 รายการแรกเหมาะสมโดยพิจารณาจากค่ากำหนดของผู้ใช้ และตัวแปรสุดท้าย --_transition จะได้รับการตั้งค่าเป็น --_motion-reduced หรือ --_motion-ok ตามลำดับ

.fab {
  /* box-shadow and background-color can safely be transitioned for reduced motion users */
  --_motion-reduced:
    box-shadow .2s var(--ease-3),
    background-color .3s var(--ease-3);

  /* add transform and outline-offset for users ok with motion */
  --_motion-ok:
    var(--_motion-reduced),
    transform .2s var(--ease-3),
    outline-offset 145ms var(--ease-2);

  /* default the transition styles to reduced motion */
  --_transition: var(--_motion-reduced);

  /* set the transition to our adaptive transition custom property*/
  transition: var(--_transition);

  /* if motion is ok, update the adaptive prop to the respective transition prop */
  @media (prefers-reduced-motion: no-preference) {
    --_transition: var(--_motion-ok);
  }
}

เมื่อดำเนินการด้านบนแล้ว จะสามารถเปลี่ยน box-shadow, background-color, transform และ outline-offset ได้ ซึ่งทำให้ UI ได้รับความคิดเห็นที่ดีว่าลูกค้าได้รับการโต้ตอบแล้ว

ต่อไป ให้เติมลูกเล่นให้กับสถานะ :active อีกเล็กน้อยด้วยการปรับ translateYเล็กน้อย ซึ่งจะทำให้ปุ่มดูน่าสนใจ

.fab {
  …

  &:active {
    @media (prefers-reduced-motion: no-preference) {
      transform: translateY(2%);
    }
  }
}

สุดท้าย เปลี่ยนการเปลี่ยนแปลงไอคอน SVG ในปุ่มต่างๆ ดังนี้

.fab {
  …

  &[data-icon="plus"]:hover > svg {
    transform: rotateZ(.25turn);
  }

  & > svg {
    @media (prefers-reduced-motion: no-preference) {
      will-change: transform;
      transition: transform .5s var(--ease-squish-3);
    }
  }
}

บทสรุป

ตอนนี้คุณก็รู้แล้วว่าตัวเองทำยังไง คุณจะทำอะไรบ้าง‽ 🙂

มาลองเปลี่ยนแนวทางของเราและเรียนรู้วิธีทั้งหมดเพื่อสร้างเว็บกันเถอะ

สร้างเดโม ลิงก์ทวีตฉัน แล้วฉันจะเพิ่มลงในส่วนรีมิกซ์ของชุมชนด้านล่าง

รีมิกซ์ของชุมชน

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

แหล่งข้อมูล