Tôi có nên đặt các yếu tố đầu vào bên trong một yếu tố nhãn?


606

Có một thực hành tốt nhất liên quan đến việc làm tổ của labelinput các phần tử HTML?

cách cổ điển:

<label for="myinput">My Text</label>
<input type="text" id="myinput" />

hoặc là

<label for="myinput">My Text
   <input type="text" id="myinput" />
</label>

107
Một trong những ưu điểm lớn của việc đặt <input />bên trong <label>, là bạn có thể bỏ qua forid: <label>My text <input /></label>trong ví dụ của bạn. Đẹp hơn nhiều!
Znarkus

16
Mặc dù tôi đồng ý rằng inputkhông thuộc về ngữ nghĩa bên trong một label, tôi nhận thấy ngày hôm nay rằng các nhà phát triển của Bootstrap không đồng ý với tôi . Một số yếu tố, chẳng hạn như hộp kiểm nội tuyến, được tạo kiểu khác nhau tùy thuộc vào inputbên trong hay bên ngoài.
Blazemonger

6
BTW đây là một ý tưởng thực sự tồi để tạo <label for="id">vì tôi có nhiều biểu mẫu trên trang và tôi không thể sử dụng idthuộc tính cho nhiều tiện ích mà không rơi vào unique id per pagebẫy. Cách duy nhất được chấp nhận để truy cập các widget là form + widget_name.
MaxZoom

5
@MaxZoom nếu bạn có quá nhiều hình thức khác nhau trên trang của mình với tên trường giống hệt nhau mà bạn gặp khó khăn khi tạo ID duy nhất, bạn có thể muốn xem xét lại thiết kế trang của mình một chút, IMHO; rõ ràng tôi không biết tình hình của bạn, nhưng điều đó chỉ có mùi với tôi
Ken Bellows

5
@kenbellows Ý tưởng của nhà thiết kế / doanh nghiệp (không phải của tôi) là đặt hai biểu mẫu Tìm kiếm trên một trang. Các thực tiễn trải nghiệm người dùng tốt nhất có thể thay đổi theo thời gian nhưng HTML phải đủ linh hoạt (IMHO) để bao quát mọi tình huống có thể nhìn thấy.
MaxZoom

Câu trả lời:


529

Từ w3: Nhãn có thể được định vị trước, sau hoặc xung quanh điều khiển liên quan.

<label for="lastname">Last Name</label>
<input type="text" id="lastname" />

hoặc là

<input type="text" id="lastname" />
<label for="lastname">Last Name</label>

hoặc là

<label>
   <input type="text" name="lastname" />
   Last Name
</label>

Lưu ý rằng kỹ thuật thứ ba không thể được sử dụng khi một bảng đang được sử dụng để bố trí, với nhãn trong một ô và trường biểu mẫu liên kết của nó trong một ô khác.

Một trong hai là hợp lệ. Tôi thích sử dụng ví dụ thứ nhất hoặc thứ hai, vì nó cho phép bạn kiểm soát phong cách nhiều hơn.


14
Như đã trả lời, tất cả đều hợp lệ nhưng trong thực tế của riêng tôi, tôi thường giải quyết ví dụ đầu tiên được đưa ra ở đây bởi superUntitle cho các hộp văn bản, textareas và chọn. Nhưng đối với các nút và hộp kiểm radio, tôi thường sử dụng ví dụ thứ ba, nơi tôi muốn đầu vào trước văn bản kèm theo và không muốn cùng loại chiều rộng cố định và / hoặc nổi mà các nhãn và trường còn lại đang sử dụng. Vì vậy, trên bất kỳ biểu mẫu nào, bạn có thể thấy tôi sử dụng cả hai định dạng này cùng nhau.
Funka

6
Tôi tự hỏi nếu <label for="inputbox"><input id="inputbox" type="text" /></label>là một vượt qua theo tiêu chí của họ.
Matt

64
Quá tệ là bạn không thể lồng nhãn trong thẻ đầu vào. Sẽ hợp lý hơn về mặt ngữ nghĩa, vì nhãn thực sự là một thuộc tính của đầu vào, nếu bạn nhìn thấy nó từ một quan điểm trừu tượng.
Alex

9
Tài liệu WCAG được liên kết bao gồm tùy chọn sau "Điều khiển được chứa trong một thành phần nhãn có chứa văn bản nhãn." Tôi không biết nếu điều đó đã được thêm vào trong những năm kể từ khi @Sorcy nhận xét, nhưng kịch bản đầu vào trong nhãn được coi là hợp lệ ngay bây giờ.
Alex Weitzer

6
Có một vấn đề với đầu vào bên trong nhãn, ít nhất là bằng chrome, khi bạn đính kèm một trình xử lý sự kiện nhấp vào nhãn, trình xử lý sẽ bị bắn hai lần khi nhãn được nhấp. Bạn có thể nhận được điều này với return false;phần cuối của trình xử lý, nhưng nếu bạn có thể có các trình xử lý khác cần thực thi sau đó và dừng việc truyền bá không phải là một lựa chọn, điều này trở thành một vấn đề.
Wired_in

67

tôi thích

<label>
  Firstname
  <input name="firstname" />
</label>

<label>
  Lastname
  <input name="lastname" />
</label>

kết thúc

<label for="firstname">Firstname</label>
<input name="firstname" id="firstname" />

<label for="lastname">Lastname</label>
<input name="lastname" id="lastname" />

Chủ yếu là vì nó làm cho HTML dễ đọc hơn. Và tôi thực sự nghĩ rằng ví dụ đầu tiên của tôi dễ tạo kiểu hơn với CSS, vì CSS hoạt động rất tốt với các phần tử lồng nhau.

Nhưng đó là vấn đề của hương vị tôi cho rằng.


Nếu bạn cần thêm tùy chọn kiểu dáng, hãy thêm thẻ span.

<label>
  <span>Firstname</span>
  <input name="firstname" />
</label>

<label>
  <span>Lastname</span>
  <input name="lastname" />
</label>

Mã vẫn có vẻ tốt hơn theo ý kiến ​​của tôi.


3
Bao gồm đầu vào bên trong nhãn cũng giống như sử dụng HTML để bố trí.
Emil

8
Tôi cũng thích giải pháp này cho các trường hợp như thế này: <label>Expires after <input name="exp" /> days</label>(nhãn là trước và sau phần tử đầu vào)
Philipp

Tôi nghĩ ví dụ cuối cùng là - bên cạnh các thuộc tính for và id - không thực sự khác biệt so với việc có nhãn bên cạnh đầu vào và cả hai được bọc thành một div, lihoặc không phải là gì!?
retrovertigo

1
@retrovertigo - chức năng? Không. Nó chỉ làm giảm đánh dấu và giảm lạm dụng ngữ nghĩa. Chúng tôi biết đầu vào firstnamephải theo nhãn cho firstname, nhưng trình duyệt cần khai báo. Đó là tất cả vấn đề về hương vị và những gì BẠN nghĩ là tốt nhất (và dễ gỡ lỗi nhất) trong mã của bạn. Tôi thích sử dụng lồng nhau ngay bây giờ, mặc dù phải mất một thời gian để tôi quen với nó.
Xhynk

3
@MPavlak - một cái nhìn nhanh và tôi tìm thấy hướng dẫn này từ w3.org. w3.org/WAI/tutorials/forms/labels . Sau đó tôi đã kiểm tra w3.org/TR/WCAG20-TECHS/H44.html . Ở phía dưới (tối nghĩa) nó nói rằng để yêu cầu sự phù hợp, bạn cần phải vượt qua các tiêu chí kiểm tra, và điều đó nói rõ rằng bạn nên sử dụng thuộc tính for. Trong thực tế khi lần cuối tôi thử nghiệm điều này trong Apple Voiceover (10% thị phần máy đọc màn hình, 60% thị phần máy đọc màn hình di động), các nhãn ngầm không hoạt động, vì vậy đó là một yếu tố chính khác. Mong rằng sẽ giúp!
James Westgate

39

Nếu bạn bao gồm thẻ đầu vào trong thẻ nhãn, bạn không cần sử dụng thuộc tính 'for'.

Điều đó nói rằng, tôi không muốn bao gồm thẻ đầu vào trong nhãn của mình vì tôi nghĩ chúng là các thực thể riêng biệt, không chứa.


8
Việc này đòi hỏi bạn phải sử dụng một id, điều này khiến cho việc cấu trúc bố cục rất khó khăn :-(
lethalman

39

Khác biệt về hành vi: nhấp vào khoảng trắng giữa nhãn và đầu vào

Nếu bạn nhấp vào khoảng trống giữa nhãn và đầu vào, nó chỉ kích hoạt đầu vào nếu nhãn chứa đầu vào.

Điều này có ý nghĩa vì trong trường hợp này, không gian chỉ là một ký tự khác của nhãn.

<p>Inside:</p>

<label>
  <input type="checkbox" />
  |&lt;----- Label. Click between me and the checkbox.
</label>

<p>Outside:</p>

<input type="checkbox" id="check" />
<label for="check">|&lt;----- Label. Click between me and the checkbox.</label>

Có thể nhấp vào giữa nhãn và hộp có nghĩa là:

  • dễ bấm hơn
  • ít rõ ràng hơn nơi mọi thứ bắt đầu và kết thúc

Các ví dụ về hộp kiểm Bootstrap v3.3 sử dụng đầu vào bên trong: http://getbootstrap.com/css/#forms Có thể khôn ngoan khi theo dõi chúng. Nhưng họ đã thay đổi quyết định trong v4.0 https://getbootstrap.com/docs/4.0/components/forms/#checkboxes-and-radios vì vậy tôi không biết điều gì là khôn ngoan nữa:

Các hộp kiểm và sử dụng radio được xây dựng để hỗ trợ xác thực mẫu dựa trên HTML và cung cấp nhãn ngắn gọn, dễ truy cập. Như vậy, <input>s và s của chúng ta <label>là các phần tử anh em trái ngược với một <input>bên trong a <label>. Điều này dài hơn một chút vì bạn phải chỉ định id và cho các thuộc tính để liên quan đến <input><label>.

Câu hỏi UX thảo luận chi tiết về điểm này: /ux/23552/should-the-space-b between-the-checkbox-and-tag-be-clickable


Đây không phải là một sự khác biệt thông số kỹ thuật. Chuyển đổi hoạt động cho cả hai trường hợp trong tất cả các trình duyệt tuân thủ.
hexalys

@hexalys Cảm ơn báo cáo. Tôi đã cập nhật câu trả lời. Bạn có nghĩa là các trình duyệt tuân thủ nên chuyển đổi hoặc không trên cả hai trường hợp? Nếu bạn có thể liên kết đến đoạn tiêu chuẩn có liên quan sẽ rất tuyệt vời.
Ciro Santilli 郝海东 冠状 病 事件

1
Đúng. Mặc dù tôi không nhận thấy rằng ví dụ của bạn là sai lệch vì không gian của bạn không thực sự là không gian văn bản . Đó là một margintrong các hộp kiểm. Hành vi của Firefox trong ví dụ của bạn rất đặc biệt và có vẻ như là một lỗi. A labelsẽ chứa khoảng trắng hoặc phần đệm xung quanh nội dung nội tuyến dưới dạng có thể nhấp. Nhưng do mô hình Nội dung của nhãn là nội dung / Phrasing, nên không thể nhấp vào lề của đầu vào, trừ khi nhãn của bạn được tạo display: blocktrong trường hợp bên trong nhãn blockcó thể nhấp được trong tất cả các trình duyệt.
hexalys

1
Lưu ý rằng liên kết Bootstrap trong câu trả lời sẽ chuyển đến các tài liệu cho v3.3. Các tài liệu cho v4.0 dường như cho thấy họ đã thay đổi quyết định: "Việc sử dụng hộp kiểm và radio được xây dựng để hỗ trợ xác thực mẫu dựa trên HTML và cung cấp nhãn ngắn gọn, có thể truy cập. Như vậy, <input> s và <nhãn> s của chúng tôi là các phần tử anh chị em trái ngược với <input> trong <nhãn>. Đây là một phần dài hơn một chút vì bạn phải chỉ định id và cho các thuộc tính để liên quan đến <input> và <nhãn> ".
Michael Krebs

2
Sự khác biệt hành vi này là một trong những lớn đối với tôi. Khi các phần tử là anh em ruột, bất kỳ lề nào trên một trong hai phần tử đều làm giảm diện tích bề mặt có thể nhấp sẽ kích hoạt phần tử đầu vào. Việc lồng đầu vào bên trong nhãn sẽ duy trì vùng có thể nhấp tối đa, mang lại khả năng truy cập tối đa ngay cả đối với người dùng phải vật lộn với các chuyển động chuột hoặc chạm chính xác. Trong Bootstrap 4, lồng nhau vẫn hoạt động và vẫn hiển thị như cũ mà không cần điều chỉnh hoặc ghi đè bất kỳ CSS Bootstrap nào.
Turgs

17

Cá nhân tôi thích giữ nhãn bên ngoài, như trong ví dụ thứ hai của bạn. Đó là lý do tại sao thuộc tính FOR ở đó. Lý do là tôi thường áp dụng các kiểu cho nhãn, như chiều rộng, để làm cho biểu mẫu trông đẹp hơn (tốc ký bên dưới):

<style>
label {
  width: 120px;
  margin-right: 10px;
}
</style>

<label for="myinput">My Text</label>
<input type="text" id="myinput" /><br />
<label for="myinput2">My Text2</label>
<input type="text" id="myinput2" />

Làm cho nó để tôi có thể tránh các bảng và tất cả những thứ linh tinh trong các hình thức của tôi.


3
Bạn không nên để bản trình bày cho CSS, thay vì sử dụng <br />để tách các đầu vào?
Znarkus

1
@Znarkus - vâng, thông thường tôi gói chúng trong OL / LI để xử lý định dạng như vậy, đây chỉ là một ví dụ tốc ký nhanh.
Vẹt

1
@Parrots: Điều đó không có nhiều ý nghĩa về mặt ngữ nghĩa, imo. Và nếu bạn cần bọc chúng, tại sao không chỉ bọc chúng bằng nhãn?
Znarkus

1
@Parrots Với lý do đó tôi nghĩ mọi thứ trên một trang nên đi vào bên trong ul / li. Và với <label> <span>My text</span> <input /> </label>bạn có tất cả các tùy chọn kiểu dáng bạn cần (bao giờ).
Znarkus

1
Sử dụng "for" bắt buộc bạn sử dụng id, điều này không tốt cho bố cục phân cấp.
lethalman

15

Xem http://www.w3.org/TR/html401/interact/forms.html#h-17.9 để biết các đề xuất W3.

Họ nói rằng nó có thể được thực hiện một trong hai cách. Họ mô tả hai phương thức là rõ ràng (sử dụng "for" với id của phần tử) và ẩn (nhúng phần tử trong nhãn):

Rõ ràng:

Thuộc tính for liên kết nhãn với điều khiển khác một cách rõ ràng: giá trị của thuộc tính for phải giống với giá trị của thuộc tính id của thành phần điều khiển được liên kết.

Ngụ ý:

Để liên kết nhãn với điều khiển khác một cách ngầm định, phần tử điều khiển phải nằm trong nội dung của phần tử LABEL. Trong trường hợp này, LABEL chỉ có thể chứa một yếu tố kiểm soát.


Tôi mới phát hiện ra rằng ẩn không hoạt động trong IE ... nhiều ý tưởng?
carinlynchin

11

Cả hai đều đúng, nhưng đặt đầu vào bên trong nhãn làm cho nó kém linh hoạt hơn nhiều khi tạo kiểu bằng CSS.

Đầu tiên, a <label>bị hạn chế trong đó các phần tử có thể chứa . Ví dụ: bạn chỉ có thể đặt <div>giữa <input>văn bản nhãn và văn bản, nếu <input>không nằm trong <label>.

Thứ hai, trong khi có các cách giải quyết để tạo kiểu dễ dàng hơn như bọc văn bản nhãn bên trong bằng một khoảng, một số kiểu sẽ được kế thừa từ các phần tử cha, có thể làm cho kiểu dáng phức tạp hơn.


kém linh hoạt hơn nhiều? bạn có thể xây dựng? như những người khác đã đề cập, bạn có thể chỉ cần bọc văn bản nhãn bên trong bằng một khoảng, trừ khi đó là những gì làm cho nó kém linh hoạt hơn?
MPavlak

7

Một 'gotcha' đáng chú ý ra lệnh rằng bạn không bao giờ nên bao gồm nhiều hơn một yếu tố đầu vào bên trong một phần tử <nhãn> với thuộc tính "for" rõ ràng, ví dụ:

<label for="child-input-1">
  <input type="radio" id="child-input-1"/>
  <span> Associate the following text with the selected radio button: </span>
  <input type="text" id="child-input-2"/>
</label>

Mặc dù điều này có thể hấp dẫn đối với các tính năng biểu mẫu trong đó giá trị văn bản tùy chỉnh là thứ yếu đối với nút radio hoặc hộp kiểm, chức năng lấy nét nhấp của phần tử nhãn sẽ ngay lập tức tập trung vào phần tử có id được xác định rõ ràng trong thuộc tính 'for' của nó , khiến người dùng gần như không thể nhấp vào trường văn bản chứa để nhập giá trị.

Cá nhân, tôi cố gắng tránh các yếu tố nhãn với trẻ em đầu vào. Có vẻ như không phù hợp về mặt ngữ nghĩa đối với một yếu tố nhãn bao gồm nhiều hơn chính nhãn. Nếu bạn lồng các đầu vào trong nhãn để đạt được tính thẩm mỹ nhất định, bạn nên sử dụng CSS thay thế.


4
Đây không phải là "gotcha". Nó rõ ràng là một phần của thông số kỹ thuật; nhãn có thể chứa tối đa 1 điều khiển trong đó. Bạn cũng đang trộn các kiểu ẩn và rõ ràng ở đây - nếu bạn đặt điều khiển bên trong nhãn, bạn không cần for... và nếu bạn muốn sử dụng for, thì việc điều khiển bên trong nhãn không có ý nghĩa gì nhiều .
cHao

Đúng, nhưng có vẻ như đặc điểm kỹ thuật này không được hiểu rõ. Chúng tôi gặp vấn đề này với API biểu mẫu của Drupal 6, đã tạo ra đánh dấu tạo ra một kịch bản không giống như mô tả ở trên. Nó có đồng nghiệp của tôi và tôi gãi đầu trong một hoặc hai phút, vì vậy tôi nghĩ rằng tôi sẽ giải quyết vấn đề ở đây để tránh sự nhầm lẫn tiềm ẩn trong tương lai.
Aaron

không cần "cho" trong nhãn-> kịch bản đầu vào. một đầu vào cho mỗi nhãn và nó có lợi ích là không phải biết tên hoặc id và bạn có thể tạo kiểu css đẹp để giữ mọi thứ được đóng gói cũng như có tiêu điểm xảy ra khi nhấp vào bất kỳ yếu tố nào khác. xem zipstory.com/signup để biết ví dụ về cách làm sạch này.
Jason Sebring

Cảm ơn bạn; điều này đã trả lời một câu hỏi liên quan khác mà tôi có, cụ thể là liệu nó có khả năng có nhiều hơn một đầu vào bên trong nhãn hay không. (Bối cảnh: Một số tùy chọn nút radio, một tùy chọn trên mỗi dòng, mỗi mục nhập nút radio có 1, 2, 3 hoặc có thể nhiều đầu vào của văn bản loại, với mục đích nhấp vào một dòng có kết quả chọn nút radio của dòng đó, nếu không được chọn và cho phép chỉnh sửa đầu vào / đầu vào trên dòng đó.) Điều này khiến cánh cửa mở ra để có nhiều nhãn cho văn bản không nhập trong biểu mẫu, nhưng nó đã trả lời câu hỏi của tôi về việc những gì tôi nghĩ là ổn. (Không phải vậy.)
Christos Hayward

6

Như hầu hết mọi người đã nói, cả hai cách đều hoạt động thực sự, nhưng tôi nghĩ chỉ có cách đầu tiên nên làm. Nghiêm ngặt về mặt ngữ nghĩa, nhãn không "chứa" đầu vào. Theo tôi, mối quan hệ ngăn chặn (cha mẹ / con cái) trong cấu trúc đánh dấu sẽ phản ánh sự ngăn chặn trong đầu ra trực quan . tức là, một yếu tố xung quanh một yếu tố khác trong đánh dấu nên được vẽ xung quanh yếu tố đó trong trình duyệt . Theo đó, nhãn phải là anh chị em của đầu vào, không phải là cha mẹ. Vì vậy, tùy chọn số hai là tùy ý và khó hiểu. Mọi người đã đọc Zen of Python có thể sẽ đồng ý (Flat tốt hơn lồng nhau, thưa thớt tốt hơn dày đặc, nên có một-- và tốt nhất là chỉ có một cách rõ ràng để làm điều đó ...).

Do các quyết định như vậy từ W3C và các nhà cung cấp trình duyệt lớn (cho phép "bạn thích làm theo cách nào hơn", thay vì "làm đúng cách"), ngày nay web đã bị rối và chúng tôi phải phát triển vấn đề. và mã di sản rất đa dạng.


5

Tôi thường đi với hai lựa chọn đầu tiên. Tôi đã thấy một kịch bản khi tùy chọn thứ ba được sử dụng, khi các lựa chọn radio được nhúng trong nhãn và css có chứa một cái gì đó như

label input {
    vertical-align: bottom;
}

để đảm bảo căn chỉnh dọc phù hợp cho các đài.



2

Tôi rất thích bọc các phần tử bên trong <label>vì tôi không phải tạo id.

Tôi là một nhà phát triển Javascript và React hoặc Angular được sử dụng để tạo các thành phần có thể được tôi hoặc người khác sử dụng lại. Sau đó, thật dễ dàng để sao chép một id trong trang, dẫn đến những hành vi lạ.


1

Một điều bạn cần xem xét là sự tương tác của hộp kiểm và đầu vào radio với javascript.

Sử dụng cấu trúc dưới đây:

<label>
  <input onclick="controlCheckbox()" type="checkbox" checked="checkboxState" />
  <span>Label text</span>
</label>

Khi người dùng nhấp vào chức năng "Nhãn văn bản" controlCheckbox () sẽ được kích hoạt một lần.

Nhưng khi nhấp vào thẻ đầu vào, chức năng controlCheckbox () có thể được kích hoạt hai lần trong một số trình duyệt cũ hơn. Đó là bởi vì cả thẻ đầu vào và thẻ nhãn đều kích hoạt sự kiện onclick kèm theo hộp kiểm.

Sau đó, bạn có thể có một số lỗi trong hộp kiểm của bạn.

Tôi đã gặp vấn đề này gần đây trên IE11. Tôi không chắc chắn nếu các trình duyệt hiện đại có rắc rối với cấu trúc này.


-1

Ưu điểm chính của việc đặt inputbên tronglabel là hiệu quả gõ cho người và lưu trữ byte cho máy tính.

@Znarkus nói trong bình luận của mình với OP,

Một trong những ưu điểm lớn của việc đặt <input />bên trong <label>, là bạn có thể bỏ qua forid: <label>My text <input /></label>trong ví dụ của bạn. Đẹp hơn nhiều!

Lưu ý: Trong mã @Znarknus, một hiệu quả khác được đưa vào không được nêu rõ trong bình luận. type="text"cũng có thể được bỏ qua và inputsẽ hiển thị một hộp văn bản theo mặc định.

So sánh cạnh nhau của tổ hợp phím và byte [1].

31 tổ hợp phím, 31 byte

<label>My Text<input /></label>

58 tổ hợp phím, 58 byte

<label for="myinput">My Text</label><input id="myinput" />

Mặt khác, các đoạn mã bằng nhau về mặt trực quan và chúng cung cấp cùng mức độ truy cập của người dùng. Người dùng có thể nhấp hoặc chạm vào nhãn để đặt con trỏ vào hộp văn bản.

[1] Tệp văn bản (.txt) được tạo trong Notepad trên Windows, byte từ thuộc tính Windows File Explorer

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.