Form Bootstrap là gì: Thực hành tạo form từ cơ bản đến nâng cao

Trong thế giới phát triển giao diện web, form là nơi người dùng tương tác nhiều nhất, từ việc điền thông tin của người dùng, tìm kiếm đến gửi phản hồi. Bootstrap có cung cấp sẵn các component lý tưởng giúp bạn xây dựng các form chuyên nghiệp, dễ dùng và phản hồi tốt trên mọi thiết bị. 

Bài viết này sẽ hướng dẫn bạn chi tiết về:

  • Form Bootstrap là gì? Vì sao nên dùng Bootstrap để tạo form?
  • Các thành phần form phổ biến: input, select, checkbox, radio, textarea…
  • Cách tạo layout form hiện đại với responsive grid, form ngang, form inline
  • Gợi ý bài tập thực hành tạo form Bootstrap từ cơ bản đến nâng cao

Tổng quan về Form trong Bootstrap

Sơ lược về form trong thiết kế web

Form (biểu mẫu) là một trong những phần tử quan trọng và xuất hiện thường xuyên nhất trong bất kỳ website hoặc ứng dụng web nào. Chức năng chính của form là giúp người dùng nhập và gửi dữ liệu về phía hệ thống.

Trong HTML, form thường được xây dựng bằng các phần tử:

  • <input>: ô nhập liệu (text, password, email, number, v.v.)
  • <textarea>: vùng nhập nội dung dài
  • <select>: danh sách chọn (dropdown)
  • <button>: nút bấm gửi form hoặc thực hiện hành động

Ví dụ về form HTML thuần:

     <form action="/login" method="post">
       <label for="email">Email:</label><br>
       <input type="email" id="email" name="email"><br><br>
    
       <label for="password">Mật khẩu:</label><br>
       <input type="password" id="password" name="password"><br><br>
    
       <button type="submit">Đăng nhập</button>
     </form>

Kết quả hiển thị:

Tuy nhiên, một trong những vấn đề lớn khi sử dụng form HTML thuần là: giao diện và hành vi mặc định khác nhau giữa các trình duyệt và hệ điều hành. Ví dụ:

  • Kiểu dáng input có thể khác nhau giữa Chrome và Firefox
  • Khoảng cách, font chữ, kích thước input không đồng đều
  • Không tự động responsive trên thiết bị di động

Do đó, trong thực tế, form rất cần được chuẩn hóa và thiết kế lại giao diện để đảm bảo tính đồng nhất, thân thiện và dễ sử dụng.

Form Bootstrap là gì?

Form Bootstrap là tập hợp các class CSS được Bootstrap cung cấp sẵn để giúp bạn xây dựng form một cách nhanh chóng. Thay vì phải viết lại từng dòng CSS cho input, label, select…, bạn chỉ cần thêm các class như .form-control, .form-label, .form-select, .form-check,… là đã có một giao diện chuyên nghiệp, dễ sử dụng và thân thiện với người dùng.

Việc sử dụng Form Bootstrap sẽ giúp:

  • Xây dựng giao diện nhanh chóng
  • Đồng nhất phong cách giữa các trình duyệt
  • Có sẵn responsive, dễ dàng với các thiết bị khác nhau
  • Tùy biến linh hoạt theo nhu cầu dự án

Ví dụ về form đăng nhập xây dựng bằng Bootstrap:

     <form>
       <div class="mb-3">
         <label for="exampleInputEmail1" class="form-label">Email address</label>
         <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
         <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
       </div>
       <div class="mb-3">
         <label for="exampleInputPassword1" class="form-label">Password</label>
         <input type="password" class="form-control" id="exampleInputPassword1">
       </div>
       <div class="mb-3 form-check">
         <input type="checkbox" class="form-check-input" id="exampleCheck1">
         <label class="form-check-label" for="exampleCheck1">Check me out</label>
       </div>
       <button type="submit" class="btn btn-primary">Submit</button>
     </form>

Kết quả hiển thị:

Các nhóm thành phần chính trong Form Bootstrap

Form control – Các ô nhập cơ bản (<input>, <textarea>)

Trong Bootstrap, các ô nhập liệu dạng văn bản như <input> và <textarea> được cải tiến với class .form-control. Chỉ với class này, bạn có thể dễ dàng tạo ra các trường nhập dữ liệu rõ ràng, đẹp mắt, đồng nhất về giao diện và phản hồi người dùng.

Ví dụ cơ bản:

     <form>
       <div class="mb-3">
         <label for="exampleEmail" class="form-label">Email</label>
         <input type="email" class="form-control" id="exampleEmail" placeholder="name@example.com">
       </div>
      
       <div class="mb-3">
         <label for="exampleTextarea" class="form-label">Nội dung</label>
         <textarea class="form-control" id="exampleTextarea" rows="3"></textarea>
       </div>
     </form>

Hiển thị:

  • Tùy chỉnh kích thước input

Bootstrap hỗ trợ 3 kích thước input bao gồm .form-control-lg (ô nhập lớn), .form-control-sm (ô nhập nhỏ) và kích thước mặc định nếu không thêm class:

        <input class="form-control form-control-lg mb-3" type="text" placeholder="Lớn">
       <input class="form-control mb-3" type="text" placeholder="Mặc định">
       <input class="form-control form-control-sm" type="text" placeholder="Nhỏ">

  

  • Ghi chú hướng dẫn dưới input (Form text)

Bạn có thể thêm nội dung hướng dẫn cho người dùng bằng .form-text kết hợp với aria-describedby:

<label for="inputPassword" class="form-label">Mật khẩu</label>
       <input type="password" id="inputPassword" class="form-control" aria-describedby="passwordHelp">
       <div id="passwordHelp" class="form-text">
         Mật khẩu phải từ 8–20 ký tự, bao gồm chữ và số.
       </div>

Lưu ý, việc sử dụng aria-describedby là để cải thiện khả năng tiếp cận cho người dùng sử dụng trình đọc màn hình.

  • Input chọn file (File input)

Đối với input chọn file, Bootstrap cũng có định dạng lại, ngoài ra bạn có thể tùy chọn kích cỡ với .form-control-sm hoặc .form-control-lg:

       <input class="form-control" type="file" id="formFile">
  • Input chọn màu (Color input)

Trong Bootstrap, bạn có thể sử dụng type=“color” kết hợp với .form-control-color để hiển thị hộp chọn màu với kích thước hợp lý:

       <input type="color" class="form-control form-control-color" value="#563d7c" title="Chọn màu">

Select – Danh sách chọn (dropdown)

Trong HTML thuần, phần tử <select> được dùng để tạo các menu lựa chọn. Tuy nhiên, giao diện mặc định của <select> thường không đồng nhất giữa các trình duyệt và khá khó để tùy biến. Bootstrap cung cấp class .form-select để style lại phần tử <select> một cách đẹp mắt, hiện đại và dễ dùng hơn, trong khi vẫn giữ nguyên chức năng mặc định của HTML.

Đọc chi tiết: Dropdown Bootstrap là gì: Hướng dẫn cách dùng chi tiết cho người mới

Ví dụ:

       <select class="form-select" aria-label="Chọn quốc gia">
         <option selected>Chọn quốc gia</option>
         <option value="vn">Việt Nam</option>
         <option value="us">Hoa Kỳ</option>
         <option value="jp">Nhật Bản</option>
       </select>

      

  • Tùy chỉnh kích thước select

Giống như .form-control, Bootstrap cũng hỗ trợ 3 kích thước cho select bao gồm: .form-control-lg (ô nhập lớn), .form-control-sm (ô nhập nhỏ) và kích thước mặc định nếu không thêm class:

       <select class="form-select form-select-lg mb-3">
         <option selected>Lựa chọn lớn</option>
       </select>
      
       <select class="form-select mb-3">
         <option selected>Lựa chọn mặc định</option>
       </select>
      
       <select class="form-select form-select-sm">
         <option selected>Lựa chọn nhỏ</option>
       </select>

Checkbox và Radio button

Checkbox và Radio là những thành phần cơ bản nhưng rất quan trọng trong form, giúp người dùng thực hiện lựa chọn. Bootstrap cung cấp class .form-check để tạo giao diện checkbox và radio đồng nhất, dễ dùng và đẹp mắt hơn.

Đọc chi tiết: Button Bootstrap là gì? Cách sử dụng Button và Button Group

  • Checkbox cơ bản

Để tạo một checkbox có nhãn đi kèm, sử dụng cấu trúc sau:

       <div class="form-check">
         <input class="form-check-input" type="checkbox" value="" id="flexCheckDefault">
         <label class="form-check-label" for="flexCheckDefault">
           Tôi đồng ý với điều khoản
         </label>
       </div>

Trong đó:

  • .form-check: bao bọc toàn bộ checkbox và label
  • .form-check-input: áp dụng định dạng cho input checkbox
  • .form-check-label: định dạng cho nhãn

Kết quả:

  • Radio button cơ bản

Tương tự như checkbox, radio cũng dùng cấu trúc .form-check:

       <div class="form-check">
         <input class="form-check-input" type="radio" name="gender" id="radioMale" value="male" checked>
         <label class="form-check-label" for="radioMale">
           Nam
         </label>
       </div>
       <div class="form-check">
         <input class="form-check-input" type="radio" name="gender" id="radioFemale" value="female">
         <label class="form-check-label" for="radioFemale">
           Nữ
         </label>
       </div>

Kết quả:

Lưu ý, Các radio cùng name sẽ thuộc cùng một nhóm lựa chọn.

  • Hiển thị ngang (inline)

Trường hợp bạn muốn hiển thị checkbox hoặc radio trên cùng một dòng, hãy thêm class .form-check-inline:

       <div class="form-check form-check-inline">
         <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option1">
         <label class="form-check-label" for="inlineCheckbox1">A</label>
       </div>
       <div class="form-check form-check-inline">
         <input class="form-check-input" type="checkbox" id="inlineCheckbox2" value="option2">
         <label class="form-check-label" for="inlineCheckbox2">B</label>
       </div>

Range – Thanh trượt chọn giá trị

Ngoài các trường nhập liệu quen thuộc như text hay select, đôi khi bạn cần một cách trực quan hơn để người dùng lựa chọn giá trị số, ví dụ như điều chỉnh âm lượng, đánh giá mức độ, hoặc chọn khoảng giá.

Bootstrap hỗ trợ phần tử <input type=”range”> với class .form-range để giúp bạn tạo ra thanh trượt (slider) có giao diện đồng nhất giữa các trình duyệt, dễ tùy chỉnh và dễ sử dụng.

Ví dụ:

<label for="customRange1" class="form-label">Chọn mức độ</label>

<input type="range" class="form-range" id="customRange1">

Mặc định, range sẽ có giá trị từ 0 đến 100, với bước nhảy là 1 đơn vị.

  • Tùy chỉnh giới hạn min, max

Bạn có thể điều chỉnh phạm vi của thanh trượt bằng thuộc tính min và max:

       <label for="customRange2" class="form-label">Chọn từ 0 đến 5</label>
       <input type="range" class="form-range" min="0" max="5" id="customRange2">
  • Tùy chỉnh bước nhảy (step)

Nếu bạn cần cho phép chọn giá trị không phải số nguyên (ví dụ bước nhảy là 0.5), hãy dùng step:

       <label for="customRange3" class="form-label">Chọn từng 0.5</label>
       <input type="range" class="form-range" min="0" max="5" step="0.5" id="customRange3">

Input Group – Kết hợp label và input

Trong nhiều trường hợp, bạn cần hiển thị biểu tượng, tiền tố, hậu tố hoặc nút bấm đi kèm với trường nhập, ví dụ như:

  • Tiền tệ (₫, $)
  • Username với tiền tố @
  • Email với hậu tố @example.com
  • Nút gửi bên trong ô tìm kiếm

Thay vì viết HTML phức tạp, Bootstrap cung cấp class .input-group giúp bạn tạo các input group đẹp, nhất quán và dễ tùy chỉnh chỉ với vài dòng code.

Cú pháp cơ bản:

       <div class="input-group mb-3">
         <span class="input-group-text">@</span>
         <input type="text" class="form-control" placeholder="Tên người dùng">
       </div>

Trong đó:

  • .input-group: bao toàn bộ nhóm input
  • .input-group-text: chứa nội dung hiển thị kèm (text, ký hiệu)
  • .form-control: là input chính

Hiển thị:

  • Gán tiền tố và hậu tố cho input group
<!-- Tiền tố -->
<div class="input-group mb-3">
 <span class="input-group-text">₫</span>
 <input type="text" class="form-control" placeholder="Giá sản phẩm">
</div>


<!-- Hậu tố -->
<div class="input-group mb-3">
 <input type="text" class="form-control" placeholder="Email">
 <span class="input-group-text">@example.com</span>
</div>
  • Input group với button

Bạn có thể kết hợp input + button vào cùng một dòng gọn gàng mà không cần tự xử lý CSS, ví dụ:

       <div class="input-group mb-3">
         <input type="text" class="form-control" placeholder="Từ khóa tìm kiếm">
         <button class="btn btn-outline-secondary" type="button">Tìm</button>
       </div>

Floating Labels – Nhãn nổi bên trong input

Floating label (nhãn nổi) là một xu hướng thiết kế hiện đại, nơi nhãn của trường nhập liệu ban đầu hiển thị bên trong input như placeholder, và sau đó nổi lên trên khi người dùng bắt đầu nhập. Kiểu thiết kế này giúp giao diện gọn gàng, chuyên nghiệp hơn , và thường thấy trong các ứng dụng di động hoặc hệ thống hiện đại. Bootstrap hỗ trợ tính năng này thông qua class .form-floating.

Ví dụ:

       <div class="form-floating mb-3">
         <input type="email" class="form-control" id="floatingEmail" placeholder="name@example.com">
         <label for="floatingEmail">Địa chỉ email</label>
       </div>

Hiển thị:

Lưu ý:

  • placeholder vẫn cần khai báo để label hiển thị đúng vị trí ban đầu (dù sẽ bị ẩn khi label nổi lên).
  • Phần tử <label> phải nằm sau input trong HTML.

Một số trường hợp thường dùng

  • Form đăng nhập (email, mật khẩu)
  • Form đăng ký thông tin
  • Giao diện hiện đại cần tiết kiệm không gian hiển thị

Các cách tùy chỉnh layout form với Bootstrap

Việc tổ chức layout cho form đóng vai trò quan trọng trong việc tạo trải nghiệm người dùng tốt hơn. Bootstrap hỗ trợ nhiều cách dàn form phù hợp với từng tình huống cụ thể dưới đây.

Responsive Grid Form – Tạo form đa cột trên desktop, đơn cột trên mobile

Trong các biểu mẫu có nhiều trường thông tin, việc bố trí form theo dạng lưới (grid) giúp giao diện gọn gàng hơn trên desktop, đồng thời vẫn tự động hiển thị một cột trên thiết bị di động. Đây là cách bố trí phổ biến và hiện đại trong các hệ thống quản trị, form đăng ký, đặt hàng…

Để tạo layout form có nhiều cột responsive, bạn có thể sử dụng hệ thống Grid bao gồm:

  • Dùng .row để tạo dòng mới
  • Sử dụng .col-* hoặc .col-md-*, .col-lg-* để chia các trường thành nhiều cột
  • Thêm .g-* (gutter) để tạo khoảng cách giữa các cột và hàng
     <div class="row g-3">
       <div class="col-md-6">
         <label for="firstName" class="form-label">Họ</label>
         <input type="text" class="form-control" id="firstName" placeholder="Nguyễn">
       </div>
       <div class="col-md-6">
         <label for="lastName" class="form-label">Tên</label>
         <input type="text" class="form-control" id="lastName" placeholder="Văn A">
       </div>
     </div>

Ví dụ cụ thể về form có responsive:

     <form class="row g-3">
       <div class="col-md-6">
         <label for="inputEmail4" class="form-label">Email</label>
         <input type="email" class="form-control" id="inputEmail4">
       </div>
       <div class="col-md-6">
         <label for="inputPassword4" class="form-label">Mật khẩu</label>
         <input type="password" class="form-control" id="inputPassword4">
       </div>
       <div class="col-12">
         <label for="inputAddress" class="form-label">Địa chỉ</label>
         <input type="text" class="form-control" id="inputAddress" placeholder="123 Đường chính">
       </div>
       <div class="col-12">
         <label for="inputAddress2" class="form-label">Địa chỉ bổ sung</label>
         <input type="text" class="form-control" id="inputAddress2" placeholder="Căn hộ, số tầng, toà nhà...">
       </div>
       <div class="col-md-6">
         <label for="inputCity" class="form-label">Thành phố</label>
         <input type="text" class="form-control" id="inputCity">
       </div>
       <div class="col-md-4">
         <label for="inputState" class="form-label">Tỉnh/Thành</label>
         <select id="inputState" class="form-select">
           <option selected>Chọn...</option>
           <option>Hà Nội</option>
           <option>TP. HCM</option>
         </select>
       </div>
       <div class="col-md-2">
         <label for="inputZip" class="form-label">Mã bưu điện</label>
         <input type="text" class="form-control" id="inputZip">
       </div>
       <div class="col-12">
         <div class="form-check">
           <input class="form-check-input" type="checkbox" id="gridCheck">
           <label class="form-check-label" for="gridCheck">
             Ghi nhớ thông tin
           </label>
         </div>
       </div>
       <div class="col-12">
         <button type="submit" class="btn btn-primary">Gửi</button>
       </div>
     </form>

Kết quả:

Một số lưu ý khi dùng form grid:

  • Luôn đặt các nhóm input trong .row để Bootstrap nhận biết dòng mới
  • Dùng .mb-3 hoặc .g-* để tạo khoảng cách giữa các trường giúp giao diện thoáng hơn
  • Dùng .col-12 nếu muốn input chiếm toàn bộ chiều ngang dòng
  • Ưu tiên .col-md-*, .col-lg-* để tạo layout responsive hiệu quả trên từng loại thiết bị

Đọc thêm về cách sử dụng Responsive trong bootstrap

Inline Form – Form trong một dòng

Inline form phù hợp với các tình huống cần tiết kiệm không gian như thanh tìm kiếm, login nhanh ở header, hoặc các form đơn giản. Để tạo inline form, bạn sử dụng class .row kết hợp với .row-cols-*, và các tiện tích của Grid System để tạo bố cục ngang linh hoạt theo kích thước màn hình.

Ví dụ:

     <form class="row row-cols-lg-auto g-3 align-items-center">
       <div class="col-12">
         <label class="visually-hidden" for="inlineFormInputGroupUsername">Username</label>
         <div class="input-group">
           <div class="input-group-text">@</div>
           <input type="text" class="form-control" id="inlineFormInputGroupUsername" placeholder="Username">
         </div>
       </div>
    
       <div class="col-12">
         <label class="visually-hidden" for="inlineFormSelectPref">Preference</label>
         <select class="form-select" id="inlineFormSelectPref">
           <option selected>Choose...</option>
           <option value="1">One</option>
           <option value="2">Two</option>
           <option value="3">Three</option>
         </select>
       </div>
    
       <div class="col-12">
         <div class="form-check">
           <input class="form-check-input" type="checkbox" id="inlineFormCheck">
           <label class="form-check-label" for="inlineFormCheck">
             Remember me
           </label>
         </div>
       </div>
    
       <div class="col-12">
         <button type="submit" class="btn btn-primary">Submit</button>
       </div>
     </form>

Trong đó:

  • .row: Kích hoạt hệ thống lưới của Bootstrap.
  • .row-cols-lg-auto: Chia các cột theo nội dung (auto width) trên màn hình lớn trở lên (lg), giúp form trông gọn gàng theo chiều ngang.
  • .g-3: Tạo khoảng cách đều giữa các cột và dòng (cả ngang và dọc).
  • .align-items-center: Căn giữa các phần tử theo chiều dọc, giúp checkbox và nút submit cùng nằm trên một hàng với input.
  • .col-12: Cột chiếm toàn bộ chiều ngang khi ở màn hình nhỏ.

Kết quả:

Horizontal Form – Label và input nằm ngang

Form ngang (horizontal form) là kiểu bố cục trong đó label và input được hiển thị trên cùng một dòng, thay vì xếp chồng lên nhau như layout dọc. Đây là lựa chọn phù hợp khi bạn muốn tối ưu không gian chiều dọc và giúp người dùng đọc thông tin nhanh hơn. Cấu trúc cơ bản để tạo form ngang:

  • Bọc mỗi nhóm label + input trong một class .row
  • Gán chiều rộng cụ thể cho label và input bằng .col-sm-*
  • Thêm .col-form-label vào label để căn giữa theo chiều dọc

Ví dụ:

     <form>
       <div class="row mb-3">
         <label for="inputEmail3" class="col-sm-3 col-form-label">Email</label>
         <div class="col-sm-9">
           <input type="email" class="form-control" id="inputEmail3">
         </div>
       </div>
       <div class="row mb-3">
         <label for="inputPassword3" class="col-sm-3 col-form-label">Mật khẩu</label>
         <div class="col-sm-9">
           <input type="password" class="form-control" id="inputPassword3">
         </div>
       </div>
     </form>

Trong đó:

  • Phần Label chiếm diện tích 3 cột, input chiếm 9 cột

Kết quả:

  • Tuỳ chỉnh kích thước label trong form ngang

Khi bạn sử dụng .form-control-sm hoặc .form-control-lg để tăng kích thước form, nên áp dụng tương ứng class .col-form-label-sm hoặc .col-form-label-lg cho <label> để căn chỉnh đúng:

     <form>
       <div class="row mb-3">
         <label for="emailSm" class="col-sm-2 col-form-label col-form-label-sm">Email</label>
         <div class="col-sm-10">
           <input type="email" class="form-control form-control-sm" id="emailSm" placeholder="Nhập email nhỏ">
         </div>
       </div>
      
       <div class="row mb-3">
         <label for="emailLg" class="col-sm-2 col-form-label col-form-label-lg">Email</label>
         <div class="col-sm-10">
           <input type="email" class="form-control form-control-lg" id="emailLg" placeholder="Email lớn">
         </div>
       </div>
     </form>

Kết quả:

Trạng thái đặc biệt của Form

Trong thực tế không chỉ đơn giản là nhập dữ liệu, mà nó còn cần phản hồi lại người dùng bằng cách hiển thị trạng thái như vô hiệu hoá (disabled) hoặc kiểm tra hợp lệ (validation). Bootstrap hỗ trợ sẵn các class để giúp bạn xử lý hai trạng thái phổ biến này một cách nhanh chóng.

Disabled Form – Vô hiệu hóa toàn bộ hoặc từng phần

Khi cần ngăn người dùng tương tác với form (ví dụ: đang tải dữ liệu, chưa đủ điều kiện, chỉ hiển thị để xem…), bạn có thể dùng thuộc tính disabled để vô hiệu hóa:

  • Vô hiệu hoá toàn bộ form bằng fieldset: Đây là cách nhanh nhất để vô hiệu hóa tất cả các trường trong form cùng lúc. Khi thêm thuộc tính .disabled vào thẻ <fieldset>, toàn bộ các trường bên trong sẽ không thể tương tác.
     <form>
       <fieldset disabled>
         <div class="mb-3">
           <label for="disabledTextInput" class="form-label">Email</label>
           <input type="text" id="disabledTextInput" class="form-control" placeholder="email@example.com">
         </div>
         <div class="mb-3">
           <label for="disabledSelect" class="form-label">Lựa chọn</label>
           <select id="disabledSelect" class="form-select">
             <option>Không thể chọn</option>
           </select>
         </div>
         <button type="submit" class="btn btn-primary">Gửi</button>
       </fieldset>
     </form>

Kết quả:

  • Vô hiệu hoá từng input cụ thể: Sử dụng khi bạn chỉ muốn ngăn người dùng nhập vào một vài trường nhất định, ví dụ: các trường chỉ hiển thị để đọc hoặc bị khóa theo điều kiện nào đó.
     <form>
       <div class="mb-3">
         <label for="readonlyInput" class="form-label">Tên người dùng</label>
         <input type="text" id="readonlyInput" class="form-control" value="nguyen van A" disabled>
       </div>
    
       <div class="mb-3">
         <label for="selectRole" class="form-label">Vai trò</label>
         <select id="selectRole" class="form-select" disabled>
           <option selected>Admin</option>
           <option>Editor</option>
           <option>Viewer</option>
         </select>
       </div>
    
       <button type="submit" class="btn btn-primary">Gửi</button>
     </form>

Kết quả:

Validation – Kiểm tra dữ liệu đầu vào

Bootstrap hỗ trợ hiển thị trạng thái hợp lệ (is-valid) và không hợp lệ (is-invalid) bằng CSS. Bạn có thể thêm class này thủ công hoặc kết hợp với JavaScript để kiểm tra trước khi submit.

Cách hoạt động:

  • Bootstrap dựa trên CSS pseudo-class :valid và :invalid để tạo hiệu ứng
  • Bạn cần thêm class .was-validated vào thẻ <form> sau khi kiểm tra
  • Sử dụng thuộc tính required để bắt buộc nhập dữ liệu

Ví dụ form có validation:

     <form class="needs-validation" novalidate>
       <div class="mb-3">
         <label for="username" class="form-label">Tên người dùng</label>
         <input type="text" class="form-control" id="username" required>
         <div class="valid-feedback">Hợp lệ!</div>
         <div class="invalid-feedback">Vui lòng nhập tên người dùng.</div>
       </div>
       <div class="mb-3">
         <label for="email" class="form-label">Email</label>
         <input type="email" class="form-control" id="email" required>
         <div class="invalid-feedback">Vui lòng nhập địa chỉ email hợp lệ.</div>
       </div>
       <div class="form-check mb-3">
         <input type="checkbox" class="form-check-input" id="termsCheck" required>
         <label class="form-check-label" for="termsCheck">Tôi đồng ý điều khoản</label>
         <div class="invalid-feedback">Bạn phải đồng ý trước khi gửi.</div>
       </div>
       <button class="btn btn-primary" type="submit">Gửi</button>
     </form>
     <script>
       (() => {
         const forms = document.querySelectorAll('.needs-validation');
      
         forms.forEach((form) => {
           form.addEventListener('submit', (event) => {
             if (!form.checkValidity()) {
               event.preventDefault();
               event.stopPropagation();
             }
      
             form.classList.add('was-validated');
           });
         });
       })();
     </script>

Trong đó:

  • Form bao gồm class needs-validation để kích hoạt validate và sử dụng .invalid-feedback, .valid-feedback để hiển thị thông báo
  • Khi form bị submit, JavaScript kiểm tra tính hợp lệ của từng trường. Nếu có trường không hợp lệ, form sẽ không được gửi và Bootstrap sẽ hiển thị feedback tương ứng

Hiển thị kết quả:

  • Trước khi submit form
  • Sau khi submit và vi phạm validate
  • Validate theo trình duyệt mặc định (không cần javascript)

Bạn có thể sử dụng thuộc tính required để yêu cầu không được bỏ trống input. Nếu để trống thì trình duyệt sẽ hiển thị lỗi theo giao diện mặc định:

     <form>
       <input type="text" class="form-control" required>
       <button class="btn btn-primary mt-3" type="submit">Gửi</button>
     </form>
  • Validation phía server

Khi thực hiện submit một form, và nhận được phản hồi lỗi từ phía server, bạn có thể gắn các class .is-valid hoặc .is-invalid theo kết quả trả về tương ứng. Ví dụ:

     <form>
       <input type="text" class="form-control is-invalid" required>
       <div class="invalid-feedback">Trường này không hợp lệ.</div>
       <input type="text" class="form-control is-valid">
       <div class="valid-feedback">Trường này hợp lệ.</div>
       <button class="btn btn-primary mt-3" type="submit">Gửi</button>
     </form>

Kết quả:

  • Tooltip feedback

Để hiển thị thông báo dạng tooltip cho input, bạn có thể dùng class .valid-tooltip (thông báo hợp lệ) và .invalid-tooltip (thông báo không hợp lệ).

Ví dụ:

     <form class="row g-3 needs-validation" novalidate>
       <div class="col-md-4 position-relative">
         <label for="validationTooltip01" class="form-label">Họ</label>
         <input type="text" class="form-control" id="validationTooltip01" value="Mark" required>
         <div class="valid-tooltip">Hợp lệ</div>
       </div>
       <div class="col-md-4 position-relative">
         <label for="validationTooltip02" class="form-label">Tên</label>
         <input type="text" class="form-control" id="validationTooltip02" value="Otto" required>
         <div class="valid-tooltip">Hợp lệ</div>
       </div>
       <div class="col-md-6 position-relative">
         <label for="validationTooltip03" class="form-label">Thành phố</label>
         <input type="text" class="form-control" id="validationTooltip03" required>
         <div class="invalid-tooltip">Vui lòng chọn thành phố</div>
       </div>
       <div class="col-12">
         <button class="btn btn-primary" type="submit">Submit</button>
       </div>
     </form>

Lưu ý, sau khi thực hiện kiểm tra, cần thay đổi .needs-validation thành .was-validated để có thể hiển thị thông báo lỗi.

Kết quả:

Lưu ý, Tooltip chỉ hiển thị chính xác nếu phần tử cha có position: relative

Bài tập luyện tập sử dụng Form Bootstrap (dễ – trung bình – khó)

Bài tập 1: (Dễ) – Tạo Form Đăng nhập đơn giản

Tạo một form đăng nhập gồm 2 trường: Email và Mật khẩu, căn giữa form trên màn hình. Hình ảnh minh họa:

Lời giải Bài tập 1

Sử dụng .form-control cho input, đặt trong thẻ có class .card để dễ nhìn. Sau đó đặt form trong thẻ div có class .min-vh-100 để chiếm chiều cao toàn trang và .d-flex, .justify-content-center, .align-items-center căn giữa theo chiều dọc.

     <div class="container min-vh-100 d-flex justify-content-center align-items-center">
<div class="card p-4 shadow" style="width: 100%; max-width: 400px;">
<h4 class="mb-3">Đăng nhập</h4>
<form>
<div class="mb-3">
<label for="loginEmail" class="form-label">Email</label>
<input type="email" class="form-control" id="loginEmail" placeholder="name@example.com">
</div>
<div class="mb-3">
<label for="loginPassword" class="form-label">Mật khẩu</label>
<input type="password" class="form-control" id="loginPassword" placeholder="••••••••">
</div>
<button type="submit" class="btn btn-primary w-100">Đăng nhập</button>
</form>
</div>

Bài tập 2: (Trung bình) – Form liên hệ có kiểm tra hợp lệ

Tạo một form liên hệ gồm: Họ tên, Email, Nội dung và Checkbox “Tôi đồng ý”. Thêm validate yêu cầu nhập đủ thông tin trước khi gửi. Hình ảnh minh họa:

Trước khi submit:

Sau khi submit:

Lời giải Bài tập 2
  • Sử dụng các lớp như .form-label, .form-control để định dạng label và input.
  • Thêm thuộc tính required cho các input để ràng buộc
  • Thêm .needs-validation để cho biết form có xử lý kiểm tra và novalidate vào <form>  tắt trình duyệt kiểm tra mặc định
  • Dùng <div class=”invalid-feedback”>…</div> ngay sau input để hiển thị khi dữ liệu không hợp lệ
  • Viết đoạn JavaScript xử lý validation
     <form class="needs-validation" novalidate>
       <div class="mb-3">
         <label for="fullname" class="form-label">Họ tên</label>
         <input type="text" class="form-control" id="fullname" required>
         <div class="invalid-feedback">Vui lòng nhập họ tên.</div>
       </div>
       <div class="mb-3">
         <label for="email" class="form-label">Email</label>
         <input type="email" class="form-control" id="email" required>
         <div class="invalid-feedback">Vui lòng nhập email hợp lệ.</div>
       </div>
       <div class="mb-3">
         <label for="message" class="form-label">Nội dung</label>
         <textarea class="form-control" id="message" rows="3" required></textarea>
         <div class="invalid-feedback">Vui lòng nhập nội dung.</div>
       </div>
       <div class="form-check mb-3">
         <input class="form-check-input" type="checkbox" id="agree" required>
         <label class="form-check-label" for="agree">Tôi đồng ý với điều khoản</label>
         <div class="invalid-feedback">Bạn cần đồng ý trước khi gửi.</div>
       </div>
       <button class="btn btn-success" type="submit">Gửi liên hệ</button>
     </form>
    
     <script>
     (() => {
       const forms = document.querySelectorAll('.needs-validation');
       forms.forEach((form) => {
         form.addEventListener('submit', (event) => {
           if (!form.checkValidity()) {
             event.preventDefault();
             event.stopPropagation();
           }
           form.classList.add('was-validated');
         });
       });
     })();
     </script>

Bài tập 3: (Khó) – Tạo form đăng ký có nhiều cột, có responsive, validate

Tạo một form đăng ký với các trường: Họ (first name), Tên (last name), Email, Mật khẩu, Quốc gia (select).

Yêu cầu về giao diện:

  • Responsive: hiển thị 2 cột trên desktop, 1 cột trên mobile
  • Có kiểm tra hợp lệ với required, invalid-feedback
  • Lỗi chỉ hiển thị sau khi người dùng bấm nút Gửi

Hình ảnh minh hoạ:

  • Trên màn hình PC
  • Trên màn hình SP
    Lời giải Bài tập 3
    • Sử dụng Bootstrap Grid (row, col-md-6) để chia các trường thành 2 cột trên desktop, 1 cột trên mobile (tự động responsive)
    • Thêm thuộc tính required vào mỗi trường để yêu cầu người dùng phải nhập hoặc chọn giá trị
    • Hiển thị lỗi bằng .invalid-feedback
    • Thêm class .needs-validation và thuộc tính novalidate vào form
    • Dùng JavaScript để kiểm tra tính hợp lệ khi người dùng bấm submit. Nếu có lỗi, form không gửi và hiển thị lỗi.
         <form class="needs-validation" novalidate>
           <div class="row g-3">
             <div class="col-md-6">
               <label for="firstName" class="form-label">Họ</label>
               <input type="text" class="form-control" id="firstName" required>
               <div class="invalid-feedback">Vui lòng nhập họ.</div>
             </div>
        
             <div class="col-md-6">
               <label for="lastName" class="form-label">Tên</label>
               <input type="text" class="form-control" id="lastName" required>
               <div class="invalid-feedback">Vui lòng nhập tên.</div>
             </div>
        
             <div class="col-md-6">
               <label for="registerEmail" class="form-label">Email</label>
               <input type="email" class="form-control" id="registerEmail" required>
               <div class="invalid-feedback">Vui lòng nhập email hợp lệ.</div>
             </div>
        
             <div class="col-md-6">
               <label for="registerPassword" class="form-label">Mật khẩu</label>
               <input type="password" class="form-control" id="registerPassword" required minlength="6">
               <div class="invalid-feedback">Mật khẩu phải có ít nhất 6 ký tự.</div>
             </div>
        
             <div class="col-12">
               <label for="country" class="form-label">Quốc gia</label>
               <select class="form-select" id="country" required>
                 <option selected disabled value="">Chọn quốc gia</option>
                 <option>Việt Nam</option>
                 <option>Nhật Bản</option>
                 <option>Hoa Kỳ</option>
               </select>
               <div class="invalid-feedback">Vui lòng chọn quốc gia.</div>
             </div>
        
             <div class="col-12">
               <button class="btn btn-primary" type="submit">Đăng ký</button>
             </div>
           </div>
         </form>
        
         <script>
         (() => {
           const forms = document.querySelectorAll('.needs-validation');
        
           forms.forEach((form) => {
             form.addEventListener('submit', (event) => {
               if (!form.checkValidity()) {
                 event.preventDefault();
                 event.stopPropagation();
               }
               form.classList.add('was-validated');
             });
           });
         })();
         </script>

    Một số lưu ý khi dùng Form trong dự án thực tế

    Mặc dù Bootstrap đã cung cấp sẵn rất nhiều công cụ mạnh mẽ để xây dựng form nhanh chóng, nhưng trong thực tế dự án, việc sử dụng form đòi hỏi nhiều hơn thế. Từ cách xử lý validation, trải nghiệm người dùng, đến bảo mật và khả năng truy cập, tất cả đều ảnh hưởng trực tiếp đến hiệu quả sử dụng của form.

    Dưới đây là những lưu ý quan trọng giúp bạn xây dựng form vừa chuyên nghiệp, vừa thân thiện với người dùng trong các dự án thực tế:

    • Luôn kiểm tra dữ liệu phía client và server: Validation phía client (HTML5 + Bootstrap) giúp cải thiện trải nghiệm người dùng bằng cách hiển thị lỗi sớm. Tuy nhiên, validation phía server vẫn bắt buộc, vì người dùng có thể vô hiệu hóa JavaScript hoặc gửi request thủ công.
    • Sử dụng thuộc tính name cho tất cả các input: Dù bạn dùng id để hiển thị/validate, nhưng thuộc tính name là bắt buộc để dữ liệu được gửi đi trong form. Ví dụ:
     <input type="text" id="email" name="email" required>
    • Tránh disabled nếu cần gửi dữ liệu: Các trường disabled sẽ không được gửi khi submit, kể cả có name. Nếu bạn cần chỉ đọc mà vẫn gửi dữ liệu, dùng readonly thay vì disabled.
    <input type="text" class="form-control" value="Không thể chỉnh sửa" disabled>
    <input type="text" class="form-control" value="Chỉ đọc được thôi" readonly>
    • Tối ưu UX cho thiết bị di động: Sử dụng grid responsive (col-md-6, col-12, v.v.) để tự động điều chỉnh layout. Đảm bảo form hiển thị đẹp, dễ bấm, dễ nhập trên màn hình nhỏ.
    • Tối ưu accessibility (khả năng tiếp cận): Luôn gắn label với input bằng for và id, hạn chế dùng placeholder làm label duy nhất (nên có label rõ ràng).

    Câu hỏi thường gặp về form Bootstrap

    Làm sao hiển thị icon trong input của form?

    Bạn có thể dùng .input-group kết hợp với .input-group-text để chèn icon (dùng Font Awesome, Bootstrap Icons hoặc SVG). Ví dụ sử dụng kết hợp Bootstrap icons và input:

           <div class="input-group mb-3">
             <span class="input-group-text"><i class="bi bi-person"></i></span>
             <input type="text" class="form-control" placeholder="Tên đăng nhập">
           </div>

    Form validation Bootstrap có cần dùng JavaScript không?

    Nếu anh muốn kiểm soát việc hiển thị thông báo lỗi, ngăn gửi form khi dữ liệu không hợp lệ, và dùng class .was-validated thì bạn cần dùng JavaScript để thực hiện kiểm tra dữ liệu và hiển thị lỗi. Nếu không sử dụng JavaScript, validation sẽ được kích hoạt theo chế độ mặc định của browser.

    Ví dụ code JavaScript để kích hoạt validate của Form Bootstrap:

         <script>
           (() => {
             const forms = document.querySelectorAll('.needs-validation');
             forms.forEach((form) => {
               form.addEventListener('submit', (event) => {
                 if (!form.checkValidity()) {
                   event.preventDefault();
                   event.stopPropagation();
                 }
                 form.classList.add('was-validated');
               });
             });
           })();
         </script>

    Floating label có dùng được với textarea không?

    Từ Bootstrap 5.2 trở đi, floating-label hoạt động tốt với <textarea> nếu bạn đảm bảo textarea có thuộc tính placeholder (ngay cả khi nó trống).

         <div class="form-floating">
           <textarea class="form-control" placeholder=" " id="floatingTextarea"></textarea>
           <label for="floatingTextarea">Nội dung</label>
         </div>

    Tổng Kết

    Form trong Bootstrap, và các thành phần cấu tạo nên nó là công cụ không thể thiếu giúp lập trình viên xây dựng giao diện nhập liệu chuyên nghiệp, dễ sử dụng và đồng bộ với toàn bộ thiết kế website. Nhờ sử dụng hệ thống lưới linh hoạt, class tiện lợi cùng khả năng tuỳ biến cao, form Bootstrap phù hợp với hầu hết các nhu cầu từ đơn giản đến phức tạp.

    Qua bài viết này, ITviec hi vọng bạn đã nắm được cách tạo, bố cục, xử lý trạng thái và kiểm tra dữ liệu đầu vào với Form trong Bootstrap để áp dụng hiệu quả vào dự án thực tế của mình.

    TÁC GIẢ
    Phạm Hữu Ngọc
    Phạm Hữu Ngọc

    Software Engineer

    Ngọc Phạm – một kỹ sư phần mềm với hơn 5 năm kinh nghiệm, từng tham gia phát triển các dự án đa dạng cho khách hàng tại Mỹ, Nhật Bản và Việt Nam. Với niềm đam mê sáng tạo và tinh thần không ngừng học hỏi, Ngọc luôn tìm kiếm những giải pháp tối ưu, nâng cao chất lượng sản phẩm và sẵn sàng chinh phục những thách thức công nghệ mới. Hiện tại, Ngọc là Software Engineer tại Voyager Inc., chuyên làm việc với Ruby on Rails, Python, ReactJS và NuxtJS. Với nền tảng vững chắc về phát triển web, API backend và frontend hiện đại, Ngọc không chỉ tập trung vào việc xây dựng các ứng dụng mạnh mẽ, linh hoạt mà còn chú trọng đến trải nghiệm người dùng, bảo mật và khả năng mở rộng hệ thống.