- 98.css เป็นระบบออกแบบ CSS ที่สร้างเว็บอินเทอร์เฟซให้มีหน้าตาเหมือน Windows 98 โดยอิงกับ HTML เชิงความหมายและการเข้าถึง
- ใช้งานได้ในสภาพแวดล้อมฟรอนต์เอนด์หลากหลายแบบรวมถึง React และ vanilla JavaScript เพราะเป็นเพียงการใส่สไตล์ให้ HTML โดยไม่ต้องใช้ JavaScript
- มี องค์ประกอบ UI แบบ Windows 98 อย่างหลากหลาย ตั้งแต่ปุ่ม ช่องกรอกข้อมูล ตัวควบคุมการเลือก ไปจนถึงหน้าต่าง แท็บ ทรี ตาราง และแถบความคืบหน้า
- รองรับการเชื่อมโยงเลเบล,
aria-label และ ARIA roles และยังสามารถ override สไตล์อย่างระยะห่างหรือสีได้โดยยังคงรูปลักษณ์พื้นฐานไว้
- ติดตั้งได้ผ่าน unpkg, npm และ GitHub Releases และแจกจ่ายภายใต้ MIT License จึงสามารถแก้ไขและมีส่วนร่วมกับโอเพนซอร์สได้
โครงสร้างโปรเจกต์และการติดตั้ง
- 98.css เป็นไลบรารี CSS ที่จำลอง อินเทอร์เฟซ Windows 98 ได้อย่างสมจริง
- ใช้ HTML เชิงความหมายเป็นพื้นฐาน โดยใช้
<button> สำหรับปุ่ม, <label> สำหรับองค์ประกอบ input และ aria-label สำหรับปุ่มไอคอน
- เป้าหมายหลักรวมถึง การเข้าถึง โดยคำนึงถึงการนำทางด้วยคีย์บอร์ดและการใช้งานเทคโนโลยีช่วยเหลือ
- เนื่องจากตกแต่ง HTML ด้วย CSS เพียงอย่างเดียวโดยไม่ใช้ JavaScript จึงไม่ผูกกับฟรอนต์เอนด์เฟรมเวิร์กใดเป็นพิเศษ
- วิธีใช้งานที่เร็วที่สุดคือโหลดสไตล์ชีตจาก unpkg
<link rel="stylesheet" href="https://unpkg.com/98.css">
npm install 98.css
- สามารถ override สไตล์เฉพาะส่วน เช่น ระยะห่างของปุ่มหรือสีของเลเบล input ได้อย่างอิสระ โดยยังคงรูปลักษณ์พื้นฐานไว้
ตัวควบคุมการเลือกพื้นฐาน
-
ปุ่ม
- ปุ่มมาตรฐานมีขนาด 75×23px พร้อมเส้นขอบนูนด้านนอกและด้านใน และมีระยะห่างแนวนอนพื้นฐาน 12px
- รองรับ
<button>, input[type=submit], input[type=reset]
- คลาส
default ใช้ระบุ การทำงานเริ่มต้น ที่จะทำงานเมื่อกด Enter ในหน้าต่างที่กำลังแอ็กทีฟ
- เมื่อคลิก เส้นขอบนูนจะเปลี่ยนเป็นลักษณะกดลง และปุ่มที่ปิดใช้งานจะยังคงเส้นขอบไว้แต่ทำให้เลเบลดูจางลง
- โฟกัสจะแสดงเป็นเส้นขอบประด้านในเนื้อหาปุ่มที่ระยะ 4px
-
ช่องทำเครื่องหมายและปุ่มตัวเลือก
- ช่องทำเครื่องหมายใช้แสดงการเลือกแบบอิสระหรือไม่บังคับร่วมกัน และเมื่อเลือกแล้วจะแสดงไอคอนเครื่องหมายถูกภายในแผงที่กดลง
- หลังช่องทำเครื่องหมาย จำเป็นต้องมี
<label> ที่มีแอตทริบิวต์ for ชี้ไปยัง id ของ input
- การเชื่อมโยงนี้ช่วยให้เทคโนโลยีช่วยเหลือสามารถรับรู้ input ได้
- รองรับการนำทางด้วยปุ่ม Tab และการคลิกทั้งเลเบล
- ใช้แอตทริบิวต์มาตรฐาน
checked, disabled เพื่อกำหนดสถานะเลือกและปิดใช้งาน
- input หลายตัวควรห่อด้วยคอนเทนเนอร์
field-row เพื่อให้มีระยะห่างสม่ำเสมอ
- ปุ่มตัวเลือกเป็นคอนโทรลที่ให้เลือกได้เพียงหนึ่งจากชุดที่จำกัด และสร้างด้วย
input[type=radio]
- กำหนดแอตทริบิวต์
name เดียวกันเพื่อรวมเป็น กลุ่มที่เลือกได้แบบไม่ร่วมกัน และใช้เลเบลกับ field-row เช่นเดียวกับช่องทำเครื่องหมาย
-
กล่องกลุ่ม
fieldset ใช้รวมหลายคอนโทรลไว้ในกรอบสี่เหลี่ยม โดยมีเส้นขอบนอกแบบกดลงและเส้นขอบในแบบนูน ทำให้ดูเหมือนกล่องที่สลักไว้
- หากวาง
legend ไว้ภายใน จะสามารถแสดง เลเบลของกลุ่ม ได้
การป้อนข้อความและการเลือกค่า
-
กล่องข้อความ
- ช่องกรอกแบบบรรทัดเดียวใช้
input[type=text] ส่วนแบบหลายบรรทัดใช้ textarea
- ควรห่อ input กับเลเบลที่เชื่อมโยงอย่างถูกต้องไว้ร่วมกันด้วย
field-row เพื่อจัดวางในแนวนอน
- หากใช้
field-row-stacked จะสามารถวางเลเบลในแนวตั้งไว้เหนือองค์ประกอบ input ได้
- ใช้แอตทริบิวต์ HTML มาตรฐาน
disabled, value เพื่อกำหนดสถานะปิดใช้งานและค่าเริ่มต้น
-
สไลเดอร์
- สไลเดอร์ใช้แสดงช่วงที่ปรับได้และค่าปัจจุบัน โดยเรนเดอร์ด้วย
input[type=range]
- คลาส
has-box-indicator จะแทนที่ตัวบ่งชี้แบบปกติด้วย ตัวบ่งชี้แบบกล่อง
- หากห่อสไลเดอร์ด้วย
div ที่มีคลาส is-vertical ก็สามารถแสดงผลในแนวตั้งได้
- ความยาวของสไลเดอร์แนวตั้งปรับได้ด้วยความกว้างของ
input และความสูงของคอนเทนเนอร์ div
-
ดรอปดาวน์
- ใช้
select และ option เพื่อสร้างดรอปดาวน์สำหรับเลือกหนึ่งรายการจากลิสต์
- รายการแรกจะถูกเลือกเป็นค่าเริ่มต้น และสามารถเปลี่ยนการเลือกเริ่มต้นได้โดยกำหนด แอตทริบิวต์
selected ให้ option อื่น
หน้าต่างสไตล์ Windows 98
-
แถบชื่อเรื่อง
- แถบชื่อเรื่องจะวางเต็มความกว้างด้านบนของหน้าต่างเพื่อบอกเนื้อหา และมีปุ่มคำสั่งหน้าต่างทั่วไปอยู่ภายใน
- ประกอบด้วยสามคลาสคือ
title-bar, title-bar-text, title-bar-controls
aria-label ของปุ่มคำสั่งสามารถใช้ Minimize, Maximize, Restore, Help, Close
aria-label ช่วยสื่อความหมายของปุ่มให้เทคโนโลยีช่วยเหลือรับรู้ พร้อมทั้งใช้สไตล์ไอคอนให้ตรงกับคำสั่ง
- ยังมีคลาสแยกอย่าง
minimize, maximize, restore, help, close ให้ใช้งานด้วย
- การแยกข้อความ
aria-label ออกจากสไตล์ภาพช่วยป้องกันปัญหาด้านการเรนเดอร์หรือการเข้าถึงในกระบวนการ หลายภาษาและโลคัลไลซ์
- หน้าต่างที่ไม่สามารถขยายเต็มจอได้ให้กำหนด
disabled กับปุ่ม Maximize
title-bar inactive ใช้แสดงแถบชื่อเรื่องที่อยู่ในสถานะไม่แอ็กทีฟท่ามกลางหลายหน้าต่าง
-
เนื้อหาหน้าต่างและแถบสถานะ
- คลาส
window ให้เส้นขอบนูนด้านนอกและด้านในพร้อมระยะห่าง และสามารถเปลี่ยนขนาดหน้าต่างได้ด้วยการกำหนดความกว้างของคอนเทนเนอร์
- เนื้อหาจริงใต้แถบชื่อเรื่องควรวางใน
window-body
- แถบสถานะด้านล่างของหน้าต่างใช้แสดงข้อมูลตามบริบท เช่น สถานะปัจจุบันหรือสถานะคีย์บอร์ด
- ใช้
status-bar กับทั้งคอนเทนเนอร์ และใช้ status-bar-field กับแต่ละพื้นที่ข้อความ
- สามารถใช้แถบสถานะสร้างอินเทอร์เฟซอย่าง Task Manager, Notepad, File Explorer ได้
อินเทอร์เฟซแบบลำดับชั้น แท็บ และตาราง
-
ทรีวิว
ul.tree-view ใช้แสดงลำดับชั้นเชิงตรรกะระหว่างออบเจ็กต์ในรูปแบบลิสต์ที่มีการเยื้อง
- เมื่อซ้อน
ul ลูก จะมีเส้นขอบประและการเยื้องโดยอัตโนมัติ และสามารถใส่เนื้อหาใดก็ได้ใน li ภายใน
- โครงสร้างลำดับชั้นที่ขยายและยุบได้สร้างได้โดยวางลิสต์ลูกไว้ภายใน องค์ประกอบ
details
-
แท็บ
- รายการแท็บเขียนด้วย
menu[role=tablist] และแต่ละแท็บใช้ li[role=tab]
- แท็บที่แอ็กทีฟให้กำหนด
aria-selected="true"
- 98.css ไม่มีลอจิกสำหรับสลับแท็บ ดังนั้นการเปลี่ยนสถานะต้องจัดการด้วย JavaScript ของผู้ใช้
- เนื้อหาแท็บควรวางในพื้นที่หน้าต่างที่กำหนด
role="tabpanel"
- หากเพิ่มคลาส
multirows ให้ menu จะสามารถสร้างแท็บหลายแถวได้
-
มุมมองตาราง
- ห่อ HTML
table ด้วย div.sunken-panel เพื่อสร้างเส้นขอบที่เหมาะสมและพื้นที่เลื่อนดูได้
table.interactive จะแสดงเคอร์เซอร์แบบ pointer เมื่อเลื่อนเมาส์ไปเหนือแถวในเนื้อหาตาราง
- แถวที่เลือกให้ใช้ คลาส
highlighted และพฤติกรรมการเลือกแถวจริงต้องเขียนด้วยสคริปต์แยกต่างหาก
สถานะความคืบหน้าและเส้นขอบอเนกประสงค์
-
แถบความคืบหน้า
- สัดส่วนความสำเร็จของงานที่ใช้เวลานานแสดงได้โดยวาง
progress-indicator-bar ไว้ภายใน progress-indicator แล้วกำหนดด้วยความกว้าง
- รูปแบบพื้นฐานเป็นแท่งสีทึบ และถ้าเพิ่มคลาส
segmented จะเปลี่ยนเป็น แถบความคืบหน้าแบบแบ่งส่วน
-
เส้นขอบฟิลด์
- กล่องข้อความ ช่องทำเครื่องหมาย ดรอปดาวน์ spin box และ list box ใช้สไตล์ฟิลด์ที่มีเส้นขอบนอกและในแบบกดลง
- ฟิลด์ทั่วไปใช้สีเน้นของปุ่มด้านใน ส่วนฟิลด์ข้อความแบบอ่านอย่างเดียวหรือปิดใช้งานจะใช้สีพื้นผิวของปุ่ม
- ฟิลด์สถานะจะใช้เฉพาะเส้นขอบนอกแบบกดลง และเหมาะกับแถบสถานะหรือเนื้อหาแบบอ่านอย่างเดียวที่เปลี่ยนแบบไดนามิก
- มีคลาสอเนกประสงค์สามแบบสำหรับใช้กับพื้นที่ทำงานและเนื้อหาไดนามิกนอกเหนือจากฟอร์ม
field-border: พื้นที่ทำงานทั่วไป
field-border-disabled: พื้นที่ทำงานที่ปิดใช้งาน
status-field-border: เนื้อหาสถานะแบบไดนามิก
- คลาสเหล่านี้กำหนดเพียงเส้นขอบ สีพื้นหลัง และระยะห่างขั้นต่ำเท่านั้น ดังนั้นโดยทั่วไปต้องกำหนด
padding เพิ่มเติม เอง
ไลเซนส์และการมีส่วนร่วม
- 98.css แจกจ่ายภายใต้ MIT License
- ตรวจสอบและรายงานบั๊กได้ที่ GitHub Issues
- โปรเจกต์รับ pull request และมีการรีวิวโค้ด โดยเฉพาะยินดีต้อนรับผู้ที่เพิ่งเริ่มมีส่วนร่วมกับโอเพนซอร์ส
1 ความคิดเห็น
ความเห็นจาก Hacker News
โปรเจ็กต์นี้ทำขึ้นระหว่างการฟื้นตัวจากภาวะหมดไฟ และทุกวันนี้ก็ยังรักมันเป็นพิเศษ
https://notes.jordanscales.com/98-css-reflections
สมดุลระหว่างการใช้งานและความคิดถึงทำได้อย่างยอดเยี่ยม จนอยากนำไปใช้กับโปรเจ็กต์อื่นเพิ่มเติม
ระหว่างหาข้อมูลก็ไปเจอพอร์ตโฟลิโอของผู้สร้าง 98.css ด้วย แถมรสนิยมทางดนตรียังตรงกันอย่างมาก เลยเริ่มสงสัยว่าคนที่ทำไลบรารีแนวย้อนยุคทุกคนมีรสนิยมคล้ายกันหรือเปล่า
Flat design ดูน่าขัน แต่กลับทำให้ใครบางคนได้เงินก้อนโต แล้วทุกคนก็แห่ทำตามกันเหมือนฝูงแกะ
เกือบ 20 ปีผ่านไปแล้วยังหลุดจากมันไม่ได้ก็ไม่ได้น่าแปลกใจอีกต่อไป และวิธีที่ UI แบบเก่าเคยทำให้แท็บหลายบรรทัดทำงานได้อย่างเป็นธรรมชาตินั้นยอดเยี่ยมจริง ๆ
ปัญหาคือมันไปชนกับแนวคิดที่ว่าใช้น้อยยิ่งดีกว่า ซึ่งขัดกับ UI แบบดินน้ำมันของเล่นที่อัดแน่นเกินไปของ Apple, Google และผู้ลอกเลียนแบบทั้งหลาย
มันกินพื้นที่แนวตั้งอันมีค่า และทุกครั้งที่คลิกตำแหน่งของบรรทัดก็เปลี่ยนไปจนชวนสับสน ถ้าเป็นปุ่มที่ใช้บอกสถานะ มันไม่ควรขยับหลังถูกคลิก
ทั้งที่มีจอภาพและการ์ดจอที่แสดงสีได้นับล้านสี แต่กลับไม่ใช้มัน ไม่จำเป็นต้องทำให้เหมือนสมุดระบายสี แต่ Windows 10 และ 11 ให้ความรู้สึกหม่นหมอง
สิ่งที่ทำให้ขัดใจอยู่เสมอในสาย 98.css คือ MS Sans Serif ไม่แม่นยำแบบแปลก ๆ สุดท้ายเลยตัดสินใจแก้เอง
https://github.com/jdan/98.css/pull/230
โปรเจ็กต์นี้เคยดังมาหลายรอบก่อนหน้านี้แล้ว: ปี 2024 ได้ 471 คะแนนและ 93 ความเห็น https://news.ycombinator.com/item?id=42056918, ปี 2022 ได้ 606 คะแนนและ 182 ความเห็น https://news.ycombinator.com/item?id=33310554, ปี 2020 ได้ 838 คะแนนและ 211 ความเห็น https://news.ycombinator.com/item?id=22940564
Windows 95: https://alexbsoft.github.io/win95.css/, 1980s website: https://bootstra386.com/, Windows XP: https://botoxparty.github.io/XP.css/, GeoCities: https://code.divshot.com/geo-bootstrap/, Counter-Strike 1.6: https://cs16.samke.me/, Edward Tufte: https://edwardtufte.github.io/tufte-css/, Windows 98: https://jdan.github.io/98.css/, Windows 7: https://khang-nd.github.io/7.css/, PlayStation: https://micah5.github.io/PSone.css/, NES: https://nostalgic-css.github.io/NES.css/, Apple System: https://sakofchit.github.io/system.css/, SNES: https://snes-css.sadlative.com/, The Sims: https://thesimscss.inbn.dev/
อยากทำเว็บไซต์ที่จะใช้สไตล์นี้ แต่ก็นึกไม่ออกว่าจะเหมาะกับอะไร
XFCE-winxp-tc ที่แต่ง Linux ให้เหมือน Windows XP ก็ยอดเยี่ยมเช่นกัน Chicago95 เป็นที่รู้จักกันมาก แต่ถ้าอยากได้บรรยากาศปี 2004 https://github.com/rozniak/xfce-winxp-tc ก็เหมาะมาก
ไม่แน่ใจว่าเป็นเพราะกังวลเรื่องกฎหมายหรือเปล่า
วิธีเอาปุ่มที่ถูกปิดใช้งานออกไปแล้วไม่แสดงเลย เป็นหนึ่งในแนวโน้ม UIที่ชวนสับสนที่สุดในปัจจุบัน และพอเห็นปุ่มสีเทากลับรู้สึกสบายใจกว่า
ควรปิดใช้งานก็ต่อเมื่อผู้ใช้คาดได้ว่าน่าจะใช้ได้และพอจะอนุมานเหตุผลที่ถูกปิดได้ง่าย ถ้าไม่มีทางเปิดใช้ได้ หรือผู้ใช้ไม่ได้คาดว่าจะใช้ได้ ก็ควรเอาออกไปแทน หากเข้าใจเหตุผลได้ไม่ง่ายนัก ก็ควรปล่อยให้ใช้งานได้ แล้วเมื่อใช้ผิดค่อยแสดงข้อความผิดพลาดที่มีประโยชน์
https://learn.microsoft.com/en-us/windows/win32/uxguide/top-...
แต่แนวทางสมัยใหม่ https://learn.microsoft.com/en-us/windows/apps/develop/ui/co... ไม่ได้พูดถึงทั้งความแตกต่างที่ละเอียดแบบนี้ และแม้แต่ปุ่มที่ถูกปิดใช้งานเองก็ไม่กล่าวถึง
แต่ถ้ามีสิทธิ์รัน เพียงแต่ทำไม่ได้เพราะโหมดหรือสถานะปัจจุบัน ก็ควรแสดงปุ่มสีเทาไว้ ในฟอร์มควรให้คลิกปุ่มสีเทาได้ด้วย แล้วบอกว่ามีอะไรผิดพลาด สายการบินใหญ่แห่งหนึ่งไม่มีคำอธิบายแบบนี้จนทำให้เช็กอินไม่สำเร็จ
ทูลทิปตอนเอาเมาส์ไปชี้กับสัญลักษณ์
?เล็ก ๆ หายไปหมดแล้ว และเหมือนซอฟต์แวร์ทุกตัวจะสมมติว่าผู้ใช้รู้วิธีใช้ตั้งแต่วันแรกhttps://ka.ge เป็นเว็บไซต์ส่วนตัวที่ทำด้วย 98.css ซึ่งจำลองสภาพแวดล้อมเดสก์ท็อป Windows 98 ได้อย่างเป๊ะระดับพิกเซลและใช้งานได้จริง โดยมีขนาดต่ำกว่า 1MB
น่าเสียดายที่แท็บในตัวอย่างแท็บหลายบรรทัด ไม่ได้สลับตำแหน่งแบบสุ่มเหมือน Windows ต้นฉบับ ตอนคลิก
ทุกครั้งที่ระบบปฏิบัติการออกเวอร์ชันใหม่ นักออกแบบ UI ก็ต้องทำให้การเปลี่ยนแปลงที่ไม่จำเป็นในเชิงฟังก์ชัน กินทรัพยากรมากขึ้น ช้าลง และไม่เสถียรขึ้น ดูเหมือนเป็นการปรับปรุง
less fasterก็เหมือนนักออกแบบ UI พวกนั้นจะมายุ่งกับคอมเมนต์นี้ด้วยเข้าใจได้ยากว่าทำไมถึงโฟกัสกับการจำลองแบบนี้ ทั้งที่ UI ของ Windows 98 ก็ไม่ใช่จุดสูงสุดของประสบการณ์ผู้ใช้
ความเทอะทะในปัจจุบันเป็นผลจากเทคโนโลยีและชั้นของ abstractionที่ซ้อนทับกันหลายชั้น ดังนั้นประเด็นสำคัญคือการเข้าใจว่าอะไรจำเป็นต่อประสบการณ์ผู้ใช้ที่ดี และหาส่วนประกอบทางเทคโนโลยีให้น้อยที่สุด
มุมโค้งกับช่องว่างลอย ๆ เป็นตัวอย่างเด่น และอิทธิพลจาก macOS กับนักออกแบบเว็บก็ทำร้ายการใช้งาน