Computer >> Hướng Dẫn Máy Tính >  >> Phần Mềm >> Các Trình Duyệt

Tại sao việc hỗ trợ các trình duyệt cũ lại quan trọng:Hướng dẫn hiện đại

Hỗ trợ các trình duyệt cũ hơn

Bạn không phải lo lắng nhiều về việc hỗ trợ các trình duyệt cũ hơn hiện nay. Họ vẫn hoạt động tốt kể từ khi Internet Explorer 8 bị khai tử.

Nhưng câu hỏi vẫn là:Bạn nên hỗ trợ Internet Explorer 9 và các trình duyệt khác như thế nào? Ngay từ đầu, bạn có nên nghĩ đến việc hỗ trợ Internet Explorer 9 không?

Chúng tôi sẽ xem xét một số điều mà bạn muốn cân nhắc.

Hãy nghĩ đến các tính năng chứ không phải trình duyệt

Giả sử thế giới chỉ có hai tính năng và hai trình duyệt.

  1. Trình duyệt A hỗ trợ tính năng A nhưng không hỗ trợ tính năng B.
  2. Trình duyệt B hỗ trợ tính năng B nhưng không hỗ trợ tính năng A.

Có thể phát hiện trình duyệt nào hỗ trợ tính năng nào và hành động từ đó.

// This is JavaScript
if (Browser A) { // Code for A}
if (Browser B) { // code for B}

Nhưng nếu có nhiều trình duyệt hơn thì sao? Điều gì sẽ xảy ra nếu thế giới chứa các trình duyệt C, D và E? Thật khó để hỗ trợ các tính năng bạn cần nếu bạn đang nghĩ về trình duyệt.

Có một cách tốt hơn:Bạn có thể kiểm tra xem một tính năng có tồn tại hay không. Nếu nó tồn tại, hãy sử dụng nó. Nếu không, hãy cung cấp mã dự phòng.

Khối mã sau hoạt động từ trình duyệt A đến trình duyệt Z.

// This is JavaScript
if (feature A) { // Code if browser contains feature A} else { // Code if browser doesn't contain feature A}

Và bây giờ bạn không phải lo lắng về trình duyệt.

Quyết định có nên sử dụng một tính năng hay không

Nhiều người quyết định có nên sử dụng một tính năng hay không tùy thuộc vào số lượng trình duyệt hỗ trợ tính năng đó. Tuy nhiên, như tôi đã lập luận ở trên, trình duyệt không quan trọng.

Điều quan trọng là:Bạn có thể viết mã dự phòng cho tính năng này một cách dễ dàng không? Nếu bạn có thể mã hóa dự phòng một cách dễ dàng, hãy tiếp tục và sử dụng tính năng này. Nếu bạn không thể viết mã dự phòng một cách dễ dàng thì đừng sử dụng tính năng này.

Quyết định hỗ trợ trình duyệt nào

Bạn vẫn cần một điểm dừng.

Bạn định hỗ trợ những trình duyệt nào?

Bạn KHÔNG hỗ trợ trình duyệt nào? Nếu bạn không muốn hỗ trợ trình duyệt thì việc bạn viết mã dự phòng cho nó là vô nghĩa.

Câu trả lời hay nhất của tôi là:Xem ai đang sử dụng trang web của bạn. Họ sử dụng trình duyệt nào? Hãy làm theo.

Có, có thể có những người ngoại lệ cố gắng truy cập trang web của bạn trên Internet Explorer 6. Nhưng bạn có thời gian và sức lực để viết thêm mã cho một trình duyệt mà hầu như không ai sử dụng không?

Liệu năng lượng của bạn có được sử dụng tốt hơn ở nơi khác không?

Mức hỗ trợ

Tôi cho rằng có bốn cấp độ hỗ trợ:

  1. mọi thứ phải trông giống nhau và hoạt động giống nhau trên tất cả các trình duyệt
  2. trang web phải trông giống nhau nhưng chức năng có thể khác nhau giữa các trình duyệt
  3. chức năng phải giống nhau nhưng giao diện có thể khác nhau giữa các trình duyệt
  4. giao diện và chức năng có thể khác nhau giữa các trình duyệt

Bạn đang cung cấp loại hỗ trợ nào cho các trình duyệt cũ hơn? Tại sao?

Kết thúc

Hãy suy nghĩ về điều đó:

  1. tại sao bạn lại cố gắng hỗ trợ trình duyệt cũ mà bạn đang cố gắng hỗ trợ?
  2. Bạn đang hỗ trợ ở mức độ nào?
  3. nó có xứng đáng với nguồn lực bạn đã phân bổ không?

Hỗ trợ các trình duyệt cũ hơn — CSS

Có hai cách để cung cấp dự phòng cho các tính năng CSS:

  1. dự phòng thuộc tính
  2. truy vấn tính năng

Dự phòng thuộc tính

Nếu trình duyệt không nhận ra thuộc tính hoặc giá trị tương ứng của thuộc tính đó thì trình duyệt sẽ bỏ qua thuộc tính đó hoàn toàn.

Khi điều này xảy ra, trình duyệt sẽ sử dụng — hoặc quay lại — về giá trị trước đó mà nó tìm thấy.

Đây là cách dễ nhất để cung cấp phương án dự phòng.

Đây là một ví dụ:

.layout { display: block; display: grid; }

Trong ví dụ này, các trình duyệt hỗ trợ CSS Grid sẽ sử dụng display: grid . Trình duyệt không hỗ trợ CSS Grid sẽ quay về display: block .

Bỏ qua các giá trị mặc định

Nếu phần tử bạn đang sử dụng có giá trị mặc định là display: block , bạn có thể bỏ qua display: block tuyên bố. Điều này có nghĩa là bạn có thể hỗ trợ CSS Grid bằng một dòng mã:

.layout { display: grid; }

Các trình duyệt hỗ trợ CSS Grid sẽ có thể đọc các thuộc tính CSS khác như grid-template-columns . Các trình duyệt không hỗ trợ CSS Grid thì không thể.

Điều này có nghĩa là bạn có thể viết các thuộc tính Lưới CSS bổ sung mà không phải lo lắng về các giá trị dự phòng.

.layout { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-gap: 1em; }

Truy vấn tính năng hoặc @supports , cho bạn biết liệu thuộc tính CSS hoặc giá trị tương ứng của nó có được trình duyệt hỗ trợ hay không.

Bạn có thể nghĩ đến các truy vấn tính năng CSS như if/else các câu lệnh bằng JavaScript. Chúng trông như thế này:

@supports (property: value) { /* Code when property or value is supported*/}
@supports not (property: value) { /* Code when property or value is not supported */}

@supports rất hữu ích nếu bạn muốn trình duyệt chỉ đọc CSS nếu họ hỗ trợ một tài sản cụ thể.

Đối với ví dụ về Lưới CSS mà chúng tôi có ở trên, bạn có thể thực hiện việc này:

@supports (display: grid) { .layout { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-gap: 1em; padding-left: 1em; padding-right: 1em; }}

Trong ví dụ này, padding-leftpadding-right sẽ chỉ được đọc bởi các trình duyệt hỗ trợ cả @supports Lưới CSS.

Jen Simmons có ví dụ tốt hơn về @supports tại nơi làm việc. Cô sử dụng các truy vấn tính năng để phát hiện xem trình duyệt có hỗ trợ thuộc tính như -webkit-initial-letter hay không .

@supports (initial-letter: 4) or (-webkit-initial-letter: 4) { p::first-letter { -webkit-initial-letter: 4; initial-letter: 4; color: #FE742F; font-weight: bold; margin-right: 0.5em; }}

Tại sao việc hỗ trợ các trình duyệt cũ lại quan trọng:Hướng dẫn hiện đại

Ví dụ của Jen đưa chúng ta đến một câu hỏi:Các trang web có nên trông giống nhau trên các trình duyệt không? Chúng ta sẽ xem xét điều này sau. Nhưng trước tiên, hãy tìm hiểu thêm về truy vấn tính năng.

Hỗ trợ truy vấn tính năng

Các truy vấn tính năng đã nhận được sự hỗ trợ tuyệt vời. Tất cả các trình duyệt chính hiện nay đều hỗ trợ truy vấn tính năng.

Tại sao việc hỗ trợ các trình duyệt cũ lại quan trọng:Hướng dẫn hiện đại

Điều gì sẽ xảy ra nếu một tính năng được hỗ trợ nhưng truy vấn tính năng thì không?

Đây từng là phần khó khăn. Jen Simmons và các chuyên gia khác đã cảnh báo chúng ta về khả năng này. Bạn có thể đọc cách xử lý trong bài viết này.

Đây là quan điểm của tôi:Tôi không hỗ trợ IE 11 nữa nên tôi sử dụng các truy vấn tính năng theo cách tôi đã đề cập ở trên.

Sử dụng đồng thời các thuộc tính dự phòng và truy vấn tính năng

Hãy nhìn vào đoạn mã sau. Trình duyệt sẽ áp dụng những giá trị đệm nào?

@supports (display: grid) { .layout { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-gap: 1em; padding-left: 1em; padding-right: 1em; }}
.layout { padding-left: 2em; padding-right: 2em; }

Câu trả lời là:Tất cả các trình duyệt sẽ áp dụng 2em của phần đệm trái và phải.

Tại sao?

Điều này xảy ra vì padding-left: 2empadding-right: 2em được khai báo sau trong tệp CSS. Thuộc tính được khai báo sau sẽ ghi đè thuộc tính được khai báo trước đó.

Nếu bạn muốn padding-left: 2empadding-right: 2em để chỉ áp dụng tới các trình duyệt không hỗ trợ CSS Grid, bạn có thể hoán đổi thứ tự thuộc tính.

.layout { padding-left: 2em; padding-right: 2em; }
@supports (display: grid) { .layout { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-gap: 1em; padding-left: 1em; padding-right: 1em; }}

Lưu ý :Khai báo mã dự phòng trước tiên trong CSS luôn là một cách hay vì tính chất xếp tầng của nó.

Điều này cũng có nghĩa là nếu bạn đang sử dụng cả @supports @supports not , bạn nên khai báo @supports not đầu tiên. Nó làm cho mã của bạn nhất quán.

/* Always write "@supports not" first if you use it */@supports not (display: grid) { .layout { padding-left: 2em; padding-right: 2em; }}
@supports (display: grid) { .layout { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-gap: 1em; padding-left: 1em; padding-right: 1em; }}

Bây giờ hãy nói về việc liệu các trang web có trông giống nhau trên các trình duyệt hay không.

Các trang web có trông giống nhau trên các trình duyệt không?

Một số người tin rằng các trang web sẽ trông giống nhau trên các trình duyệt. Họ cho rằng việc xây dựng thương hiệu là quan trọng và nhấn mạnh rằng các trang web phải trông nhất quán để bảo vệ thương hiệu.

Những người khác nói không. Họ tin rằng họ nên nắm lấy tinh thần nâng cao tiến bộ. Họ có thể mang đến cho người dùng những trình duyệt tốt hơn nhiều sự yêu thích hơn.

Cả hai quan điểm đều đúng nhưng xuất phát từ những góc độ khác nhau.

Quan điểm quan trọng nhất đến từ người dùng. Trang web của bạn có thể cung cấp cho người dùng những gì họ cần không?

Nếu có, bạn không cần phải quá khắt khe về tính nhất quán. Hãy tiếp tục và mang đến cho người dùng những trải nghiệm thậm chí còn tốt hơn nữa với trình duyệt tốt hơn!

Kết thúc

Để cung cấp hỗ trợ cho các tính năng CSS, bạn có thể sử dụng:

  1. Dự phòng thuộc tính
  2. Truy vấn tính năng

Khi viết CSS, hãy đảm bảo bạn khai báo mã dự phòng trước bộ mã khác dành cho các trình duyệt có hỗ trợ tốt hơn.

Hỗ trợ các trình duyệt cũ hơn — JavaScript

Thật dễ dàng để cung cấp hỗ trợ JavaScript cho các trình duyệt cũ hơn. Hầu hết bạn chỉ cần sử dụng polyfill.

Nhưng còn nhiều điều bạn có thể làm hơn.

Polyfill là gì?

Polyfill là một đoạn mã cho trình duyệt biết cách triển khai tính năng JavaScript. Sau khi thêm polyfill, bạn không cần phải lo lắng về việc hỗ trợ nữa. Nó sẽ hoạt động.

Đây là cách Polyfill hoạt động:

  1. nó kiểm tra xem tính năng này có được hỗ trợ hay không
  2. nếu không, nó sẽ thêm mã để hỗ trợ tính năng này

Đây là một ví dụ về polyfill đang hoạt động. Nó kiểm tra xem trình duyệt có hỗ trợ Array.prototype.find không . Nếu trình duyệt không hỗ trợ Array.prototype.find , nó sẽ cho trình duyệt biết cách hỗ trợ nó.

Bạn có thể tìm thấy mã này trên MDN.

if (!Array.prototype.find) { Object.defineProperty(Array.prototype, 'find', { value: function(predicate) { // 1. Let O be ? ToObject(this value). if (this == null) { throw new TypeError('"this" is null or not defined'); }
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")). var len = o.length >>> 0;
// 3. If IsCallable(predicate) is false, throw a TypeError exception. if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); }
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined. var thisArg = arguments[1];
// 5. Let k be 0. var k = 0;
// 6. Repeat, while k < len while (k < len) { // a. Let Pk be ! ToString(k). // b. Let kValue be ? Get(O, Pk). // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). // d. If testResult is true, return kValue. var kValue = o[k]; if (predicate.call(thisArg, kValue, k, o)) { return kValue; } // e. Increase k by 1. k++; }
// 7. Return undefined. return undefined; }, configurable: true, writable: true });}

Lưu ý :Một polyfill là một tập hợp con của miếng chêm. Shim là một thư viện mang API mới đến môi trường cũ hơn.

Sử dụng polyfill

Có hai cách để sử dụng polyfill:

  1. polyfill thủ công, như trong ví dụ trên
  2. thêm nhiều polyfill cùng một lúc thông qua thư viện

Đổ đầy thủ công

Trước tiên, bạn cần tìm kiếm polyfill bạn cần. Bạn sẽ có thể tìm thấy một nếu bạn google xung quanh. Các nhà phát triển thông minh đã tạo ra các polyfill cho hầu hết mọi thứ bạn cần.

Sau khi bạn tìm thấy polyfill, hãy sử dụng quy trình trên để tạo cung cấp hỗ trợ cho các trình duyệt cũ hơn.

Thêm nhiều polyfill cùng một lúc

Một số thư viện chứa nhiều polyfill. ES6-shim là một ví dụ về thư viện như vậy. Nó cung cấp hỗ trợ cho tất cả các tính năng ES6 trên các trình duyệt cũ hơn.

Sử dụng các tính năng JavaScript tiên tiến

Nếu bạn muốn sử dụng các tính năng JavaScript tiên tiến, hãy cân nhắc thêm Babel vào quá trình xây dựng của mình.

Babel là một công cụ biên dịch JavaScript. Trong quá trình biên dịch này, nó có thể:

  1. thêm bất kỳ miếng chêm/polyfill nào bạn cần
  2. biên dịch bộ tiền xử lý thành JavaScript

Thông tin thêm về điểm thứ hai:

Babel hoạt động ngoại tuyến trong quá trình xây dựng của bạn. Nó có thể đọc các tệp bạn truyền vào, sau đó chuyển đổi các tệp này thành JavaScript mà trình duyệt có thể đọc.

Điều này có nghĩa là bạn có thể sử dụng các tính năng tiên tiến như Flow, TypeScript và các công nghệ thú vị khác mà bạn đã nghe nói đến. Tất cả chúng sẽ hoạt động trên trình duyệt, miễn là bạn chuyển chúng qua Babel trước!

Điều gì sẽ xảy ra nếu polyfill không đủ?

Nếu polyfill không đủ để hỗ trợ tính năng này, bạn có thể muốn xem xét lại mức độ hỗ trợ mà bạn cung cấp cho trình duyệt được đề cập.

Bạn có cần cung cấp chức năng giống nhau trên các trình duyệt khác nhau không? Có lẽ bạn nên cân nhắc việc nâng cao dần dần.

Có lẽ bạn có thể viết mã theo cách không sử dụng tính năng này?

Có thể có rất nhiều khả năng, nhưng bạn sẽ có được sự trôi dạt.

Làm cách nào để biết trình duyệt có hỗ trợ tính năng này hay không?

Đầu tiên, tôi kiểm tra caniuse.com. Viết tên tính năng JavaScript mà bạn muốn và bạn sẽ có thể thấy các mức hỗ trợ của trình duyệt.

Đây là một ví dụ với Abort Controller

Tại sao việc hỗ trợ các trình duyệt cũ lại quan trọng:Hướng dẫn hiện đại

Nếu caniuse.com không cung cấp cho tôi bất kỳ thông tin nào, tôi sẽ kiểm tra MDN. Bạn sẽ tìm thấy hỗ trợ về trình duyệt ở cuối hầu hết các bài viết.

Đây lại là ví dụ với Abort Controller:

Tại sao việc hỗ trợ các trình duyệt cũ lại quan trọng:Hướng dẫn hiện đại

Coi chừng chi phí của JavaScript

Khi sử dụng polyfill, bạn sẽ thêm nhiều mã JavaScript hơn.

Vấn đề với việc thêm nhiều JavaScript là có nhiều JavaScript hơn. Và càng có nhiều JavaScript thì càng có nhiều vấn đề hơn:

  1. các trình duyệt cũ hơn thường tồn tại trong các máy tính cũ hơn. Họ có thể không có đủ sức mạnh xử lý.
  2. Các gói JavaScript có thể làm chậm quá trình tải trang web. Thông tin thêm về điều này trong “Chi phí của JavaScript“ của Addy Osmani

Kết thúc

Thật dễ dàng để thêm hỗ trợ cho các tính năng JavaScript. Hầu hết thời gian, bạn thêm một polyfill và kết thúc một ngày. Nhưng hãy lưu ý đến chi phí của JavaScript khi bạn làm như vậy!

Đôi khi, việc loại bỏ hoàn toàn tính năng này có thể là điều tốt.

Tại sao hỗ trợ các trình duyệt cũ hơn?

Tại sao bạn phải quan tâm đến trình duyệt cũ?

Ai sử dụng trình duyệt cũ? Có lẽ là người dùng có máy tính cũ?

Nếu họ dùng máy tính cũ thì có lẽ họ không có tiền mua máy mới.

Nếu họ không có tiền để mua máy tính mới, có thể họ cũng sẽ không mua bất cứ thứ gì từ bạn.

Nếu họ không mua bất cứ thứ gì từ bạn thì tại sao bạn phải quan tâm đến việc hỗ trợ trình duyệt của họ?

Đối với một doanh nhân, đó là một cách suy nghĩ hoàn toàn hợp lý. Nhưng tại sao các nhà phát triển chúng tôi vẫn nhất quyết hỗ trợ các trình duyệt cũ hơn?

Hãy chia nhỏ nó

Có rất nhiều lớp giả định trong quá trình suy nghĩ ban đầu.

"Ai sử dụng trình duyệt cũ? Có lẽ là người dùng có máy tính cũ? Nếu họ sử dụng máy tính cũ, có lẽ họ không có tiền để mua máy mới".

Mặc dù đúng là mọi người sử dụng trình duyệt cũ vì họ sử dụng máy tính cũ, nhưng chúng tôi không thể cho rằng mọi người không đủ khả năng mua trình duyệt mới.

  • Có thể công ty của họ không muốn mua cho họ một chiếc.
  • Có thể họ hài lòng với máy tính của mình và không muốn nâng cấp.
  • Có thể họ không có đủ kiến thức để nâng cấp máy tính của mình.
  • Có thể họ không có quyền truy cập vào máy tính mới.
  • Có thể họ bị ràng buộc với điện thoại di động không có trình duyệt tốt.

Đừng cho rằng.

Nếu họ không có tiền để mua một chiếc máy tính mới, có thể họ cũng sẽ không mua bất cứ thứ gì từ bạn. Nếu họ không mua bất cứ thứ gì từ bạn thì tại sao bạn phải quan tâm đến việc hỗ trợ trình duyệt của họ?

Chúng ta phải phóng to sang các lĩnh vực khác để nói về điểm này.

Khả năng tiếp cận cho xe lăn

Nếu bạn đã đến Singapore, bạn sẽ nhận thấy gần như mọi cầu thang đều có đoạn đường dốc hoặc thang máy.

Nhưng tại sao? Tại sao chính phủ và các tập đoàn tư nhân lại chi tiền cho thang máy và đường dốc? Tại sao lại xây chúng khi cầu thang đã đủ để đưa con người từ nơi thấp lên nơi cao hơn?

Hóa ra một số người không thể sử dụng cầu thang. Họ không thể đi lại bằng đôi chân của mình. Họ phải ngồi trên xe lăn và không thể tự mình di chuyển lên cầu thang. Thang máy và đường dốc phục vụ những người này.

Và hóa ra là có nhiều người được hưởng lợi hơn từ thang máy và đường dốc.

  1. Những người có đầu gối yếu hơn.
  2. Những người mang theo xe đạp hoặc xe máy.
  3. Cha mẹ đang đẩy xe đẩy em bé.

Nếu bạn thấy mình đang đẩy bất cứ thứ gì bằng bánh xe, bạn sẽ sử dụng đoạn đường dốc hoặc thang máy mà không cần suy nghĩ kỹ. Bạn cũng được hưởng lợi.

Nhưng vấn đề là:Không ai kiếm được một xu từ việc vận hành đường dốc hay thang máy? Vậy tại sao lại xây dựng chúng?

Bởi vì nó xứng đáng.

Và giá trị không phải lúc nào cũng có nghĩa là tiền.

Hãy xem xét hiện tượng nóng lên toàn cầu

Bạn sống trên Trái đất. Bạn cảm thấy thế nào về sự nóng lên toàn cầu?

Một số người không quan tâm. Sẽ không sao nếu rừng bị đốt cháy. Sẽ không sao nếu các công ty gây ô nhiễm sông ngòi và thải hàng tấn carbon dioxide vào không khí. Nó không ảnh hưởng đến họ.

Nhưng có một nhóm người quan tâm. Họ yêu thích hành tinh chúng ta đang sống. Họ muốn cho con cái mình một nơi ở tốt hơn. Có rất nhiều lý do khiến họ quan tâm. Và có lẽ họ muốn tiết kiệm càng nhiều tài nguyên càng tốt.

Bạn đứng ở đâu?

Bạn có đưa tiền cho một công ty phá hủy trái đất khi nó hoạt động không?

Có lẽ bạn sẽ làm được. Có lẽ bạn sẽ không. Có thể bạn không quan tâm. Cả ba tùy chọn đều hợp lệ.

Và một lần nữa, bạn thấy đấy, không phải lúc nào vấn đề cũng là về tiền.

Web dành cho tất cả mọi người

Giấc mơ đằng sau Web là một không gian thông tin chung nơi chúng ta giao tiếp bằng cách chia sẻ thông tin.

— Tim Berners-Lee

Các nhà phát triển giao diện người dùng của chúng tôi là người giám sát trang web. Trang web xuất hiện như thế nào là tùy thuộc vào chúng ta. Chúng tôi không thể buộc mọi người xây dựng đường dốc và thang máy, nhưng chúng tôi có thể đảm bảo rằng chúng tôi tự xây dựng chúng.

Thực sự, sự lựa chọn là tùy thuộc vào bạn.

Bạn không cần phải quan tâm nếu bạn không muốn.

Hầu hết các nhà phát triển giao diện người dùng giỏi mà tôi biết? Họ quan tâm. Họ chọn hòa nhập. Đó là điều khiến chúng tôi trở thành nhà phát triển giao diện người dùng.

Chúng tôi quan tâm.

Nhưng đôi khi chúng ta cũng có những ràng buộc và giới hạn. Và chúng tôi làm việc với những giới hạn đó.

Bài viết này ban đầu được đăng trên blog của tôi.
Đăng ký nhận bản tin của tôi nếu bạn muốn có nhiều bài viết hơn để giúp bạn trở thành nhà phát triển front-end giỏi hơn.

Học cách viết mã miễn phí. Chương trình giảng dạy mã nguồn mở của freeCodeCamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu