3 điểm bởi GN⁺ 2025-12-30 | 1 bình luận | Chia sẻ qua WhatsApp
  • Trong HTML, ngay cả khi dùng tên thẻ không được nhận diện, trình duyệt vẫn xử lý nó như một phần tử thông thường
  • Nếu chỉ định tên thẻ đó làm selector trong CSS, có thể định kiểu và kiểm soát cách hiển thị
  • Nếu dùng tên có chứa dấu gạch nối (-), có thể tránh xung đột với tiêu chuẩn HTML trong tương lai
  • Thay vì <div> hay <span>, dùng thẻ tùy chỉnh có ý nghĩa sẽ giúp mã dễ đọc hơn
  • Ngay cả trong cấu trúc lồng nhau phức tạp, cũng dễ nắm bắt cấu trúc chỉ qua tên thẻ, giúp việc bảo trì thuận tiện hơn

Cách tận dụng thẻ HTML tùy chỉnh

  • Trình duyệt sẽ render thẻ không biết như một phần tử khối thông thường

    • Đây là hành vi bình thường được nêu trong tiêu chuẩn HTML, và nếu định kiểu bằng CSS thì có thể kiểm soát về mặt hiển thị
    • Ví dụ có thể định nghĩa thẻ như <cool-thing> và trang trí trong CSS theo dạng cool-thing { ... }
  • Nếu tên thẻ có chứa dấu gạch nối (-), sẽ không có nguy cơ xung đột với những phần bổ sung vào tiêu chuẩn HTML sau này

    • Ví dụ: <main-article>, <quote-body>

Cải thiện khả năng đọc và cấu trúc

  • Thay vì <div> hay <span>, nếu dùng thẻ có tên mang ý nghĩa, việc hiểu mã sẽ trở nên dễ hơn
    • Ví dụ, có thể dùng <article-header> thay cho <div class="article-header">
  • Trong cấu trúc <div> lồng nhau, thường khó xác định vị trí thẻ đóng, nhưng nếu dùng tên thẻ tường minh thì cấu trúc sẽ rõ ràng hơn
    • Nếu bên trong <main-article> được tổ chức bằng <article-header>, <article-quote> v.v. thì việc nắm bắt cấu trúc DOM sẽ trực quan hơn

Mã ví dụ

  • Cách cũ
    <div class="cool-thing">
      Hello, World!
    </div>
    
  • Cách dùng thẻ tùy chỉnh
    <cool-thing>
      Hello, World!
    </cool-thing>
    
    • Trong CSS có thể định kiểu theo dạng cool-thing { display: block; font-weight: bold; text-align: center; ... }

Kết luận

  • Nếu tận dụng khả năng định nghĩa thẻ linh hoạt mà tiêu chuẩn HTML cho phép,
    có thể viết markup có cấu trúc và dễ đọc hơn
  • Tuy nhiên, nếu đã có thẻ mang ý nghĩa được định nghĩa sẵn, thì ưu tiên dùng thẻ hiện có

1 bình luận

 
GN⁺ 2025-12-30
Ý kiến trên Hacker News
  • Nhấn mạnh rằng <tag-name> không phải là thẻ không được nhận diện
    Giới thiệu bài viết blog của mình, tác giả giải thích rằng <tagname> sẽ được xử lý như HTMLUnknownElement cho đến khi WHATWG thêm nó thành phần tử mới, còn <tag-name> là một HTMLElement hợp lệ, hữu ích cho layout và styling
    Khi được nâng cấp bằng JavaScript Custom Elements API, nó sẽ trở thành custom element đã được định nghĩa
    Đây là hành vi tiêu chuẩn trên mọi trình duyệt, và W3C HTML Validator cũng công nhận custom element có dấu gạch nối là HTMLElement
    Tuy nhiên, quy tắc [hidden]{display:none} trong stylesheet UA mặc định không được kế thừa, nên cần tự chỉ định
    <DIV> mặc định là display:block cũng là nhờ stylesheet UA, nên với custom element phải tự đặt thuộc tính display
    Có thể phân biệt phần tử đã/ chưa được định nghĩa thông qua các selector :defined:not(:defined) của CSS
    Declarative Shadow DOM (<template shadowrootmode="open">) cũng tương tự, tạo ra custom element chưa được định nghĩa

    • Có người phản biện rằng theo Chromium thì đây không phải vấn đề của stylesheet UA, mà vì hiddenHTML presentation attribute
      Stylesheet UA vẫn được áp dụng giống nhau cho custom element, và không hề có quy tắc [hidden]
      hidden là ví dụ mà chính thuộc tính được diễn giải thành style, giống như align="right"
    • Bày tỏ tiếc nuối rằng nếu có thể dùng dấu hai chấm (:) thay vì dấu gạch nối (-) thì đã có thể tích hợp XML namespace một cách tự nhiên
      Cũng nhắc rằng nginx hay apache có thể chuyển dấu hai chấm thành dấu gạch nối
      Kết lại bằng giọng hoài niệm rằng “không thể quay lại năm 1999”
    • Đặt câu hỏi vì sao cách này lại không trở thành thực tiễn mặc định
  • Chỉ ra rằng cấu trúc lồng <div> trong ví dụ là quá mức
    Đề xuất dùng các thẻ ngữ nghĩa như <article>, <header>, <blockquote> sẽ phù hợp hơn

    • Chỉ ra rằng custom tag, khác với thuộc tính class, chỉ có thể mang một tên duy nhất
      Class có thể có nhiều cái và không có thứ tự, còn custom element lồng nhau thì ép buộc thứ tự nên khó biểu đạt cùng một ý nghĩa
    • Phân tích rằng “div soup” không hẳn là điều xấu, mà là kết quả của quyết định thiết kế khiến HTML gắn chặt cấu trúc với style
      Điều đó có thể hợp lý vào năm 1996 nhưng không còn phù hợp hiện nay
  • Chia sẻ kinh nghiệm đã dùng custom element trong 3~4 năm
    Ý tưởng thì thông minh nhưng triển khai thực tế khá khó chịu
    Dùng quá nhiều custom tag sẽ làm giảm khả năng đọc và khó phân biệt block/inline
    Theo hướng tiếp cận cân bằng, vẫn giữ nguyên các thẻ cơ bản, chỉ dùng custom tag cho các phần tử dạng component như <x-card> hay <x-hero>
    Các thành phần con được phân biệt bằng thuộc tính slot như <div slot="hero-blurb">
    Tác giả thích cách chỉ giới hạn class cho mục đích sửa đổi/tùy biến, còn cấu trúc thì biểu đạt bằng slot

    • Nói rằng mình rất quan tâm đến hướng tiếp cận web component cân bằng, và xin ví dụ hay bộ công cụ
      Giới thiệu Good.HTML do mình tạo ra, nói rằng nó hỗ trợ autohook, interpolation dựa trên template literal, và cấu trúc component được sắp xếp ngăn nắp
      Cũng nói thêm rằng custom element self-closing như < !app-header /> được triển khai bằng mẹo với comment node
    • Hỏi rằng nếu muốn chọn theo thuộc tính slot trong CSS thì có thể viết như div[slot="hero-blurb"] hay không
    • Nhắc rằng pattern này gợi nhớ đến cấu trúc block–element của BEM
  • Về cơ bản, custom tag hoạt động như <span>
    Nếu cần, có thể định nghĩa hành vi thông qua Custom Element API

    • Nói rằng mình đã dùng custom element rất rộng rãi vào năm 2014, và lấy làm tiếc khi React trở thành xu hướng áp đảo
      Theo họ, với phần lớn người dùng thì tổ hợp HTML + custom element sẽ tốt hơn SPA
    • Cho rằng nên ưu tiên phần tử ngữ nghĩa trước, chỉ dùng custom element khi cần
      Chia sẻ ví dụ Hypalink do mình làm và chỉ ra rằng Web Components đang bị đánh giá thấp
  • Giới thiệu việc đã tạo custom tag <yes-script> để làm vai trò ngược lại với <noscript>
    Có thể ẩn một vùng nhất định khi JS bị vô hiệu hóa
    Chia sẻ liên kết dự án

    • Đề xuất rằng có thể dùng tính năng @media (scripting) của CSS để đạt hiệu ứng tương tự chỉ với CSS thuần
      Đính kèm tài liệu MDN
  • Chia sẻ trải nghiệm từng tự tái tạo thẻ <blink> đã bị loại bỏ khỏi trình duyệt
    Được triển khai bằng jQuery và thao tác visibility, và họ nói mình đã ngạc nhiên khi biết trình duyệt cho phép thẻ tùy ý
    Vì đoạn code chỉ khoảng 10 dòng nên không công khai, nhưng đoán là đã có nhiều thử nghiệm tương tự

    • Giải thích rằng thực ra phần lớn trình duyệt chưa từng triển khai <blink>, và chỉ Firefox cùng Opera hỗ trợ đến năm 2013
    • Bày tỏ rằng vẫn còn tiếc khi Flash biến mất
    • Nói rằng cũng có thể tạo hiệu ứng <blink> chỉ với CSS, và chia sẻ mã ví dụ
      Nếu dùng selector blink thay vì .blink thì sẽ áp dụng trực tiếp cho thẻ
    • Cho rằng hành vi như <blink> mang ý nghĩa quá lớn để được cung cấp dưới dạng một phần tử HTML đơn giản, và bày tỏ vui mừng vì nó đã biến mất
  • Chỉ ra rằng các ví dụ như <main-article>, <article-header> có thể được thay bằng thẻ HTML thật
    Dùng <article>, <header>, <blockquote> sẽ phù hợp hơn

    • Nói thêm rằng nếu dùng các thẻ HTML được định nghĩa sẵn thì còn có thể hưởng lợi ích styling mặc định từ trình duyệt
  • Custom tag về cơ bản được render inline như <span>, nhưng chỉ cần đặt thuộc tính display mặc định bằng CSS là được
    Trước đây người ta tránh dùng vì vấn đề namespace, nhưng sau khi tiêu chuẩn cho phép dấu gạch nối (-) thì nguy cơ xung đột đã biến mất
    Chúng cũng hoạt động bình thường trong CSS selector, và có thể truy cập bằng querySelector
    Có cảm giác rằng ngay cả không cần framework như Vue thì HTML hiện đại thôi cũng đã đủ sức biểu đạt

    • Bổ sung rằng phần tử phi tiêu chuẩn có dấu gạch nối được xử lý là HTMLElement chứ không phải HTMLUnknownElement
      Đây là thiết kế để khi được nâng cấp trong tương lai, chuỗi prototype có thể được mở rộng một cách tự nhiên
  • Nếu muốn đặt style mặc định cho mọi custom element thì có thể làm như sau

    :where(:not(:defined)) {
      display: block;
    }
    
    • Nói rằng đúng là mình đang tìm cách này, đồng thời bày tỏ sự thán phục và cảm ơn
  • Nhớ lại rằng IE ngày xưa không nhận ra các thẻ HTML5, nên khoảng năm 2010 họ đã tự giải quyết bằng một script do mình viết
    Chỉ cần tạo thẻ một lần bằng JS là IE sẽ nhận diện, và sau đó xóa đi cũng không sao
    Qua cách này họ nhận ra rằng cả các thẻ tùy ý cũng có thể render được
    Cũng chia sẻ bài blog khi đó

    • Nói thêm rằng html5shim từng rất phổ biến cũng hoạt động theo cách tương tự