Bước 1: Tạo cấu trúc HTML cho mỗi trường
Mỗi input đặt trong một wrapper .im-float gồm: label, input/textarea và icon tùy chọn. Label đặt sau input để dùng selector anh em kế tiếp.
<div class="im-float uk-form-stacked">
<div class="uk-form-controls uk-position-relative">
<input class="uk-input" type="text" id="name" placeholder=" " autocomplete="name">
<label for="name" class="im-float-label">Họ và tên</label>
<span class="uk-form-icon" aria-hidden="true" uk-icon="user"></span>
</div>
</div>
Bước 2: Viết CSS cho hiệu ứng bay và trạng thái
Hiệu ứng dựa trên hai trạng thái: khi ô trống dùng :placeholder-shown, khi người dùng tương tác dùng :focus-within. Với dark mode, đồng bộ theo .uk-dark hoặc .dark.
/* ===== Floating Label for UIkit ===== */
.im-float { margin-bottom: 16px; }
.im-float .uk-form-controls { /* giữ label vị trí tuyệt đối */
position: relative;
}
/* Label nổi */
.im-float-label {
position: absolute;
left: 44px; /* chừa khoảng cho icon trái (24px + padding) */
top: 50%;
transform: translateY(-50%);
font-size: 14px;
line-height: 1;
color: var(--im-label, #888);
pointer-events: none;
transition: transform 160ms ease, top 160ms ease, font-size 160ms ease, color 160ms ease, left 160ms ease;
}
/* Input/textarea base */
.im-float .uk-input,
.im-float .uk-textarea,
.im-float .uk-select {
padding-left: 44px; /* để icon + label không đè vào text */
padding-right: 12px;
height: 44px;
}
/* Textarea cao hơn và canh label */
.im-float .uk-textarea {
height: auto;
min-height: 120px;
padding-top: 22px;
}
/* Khi focus hoặc có giá trị: label thu nhỏ và bay lên trên */
.im-float:focus-within .im-float-label,
.im-float .uk-input:not(:placeholder-shown) + .im-float-label,
.im-float .uk-textarea:not(:placeholder-shown) + .im-float-label,
.im-float .has-value + .im-float-label {
top: 6px;
transform: none;
font-size: 12px;
color: var(--im-label-active, #666);
}
/* Có icon bên phải */
.im-float.icon-right .im-float-label { left: 12px; }
.im-float.icon-right .uk-input,
.im-float.icon-right .uk-select { padding-left: 12px; padding-right: 44px; }
/* Icon UIkit định vị chuẩn */
.im-float .uk-form-icon { left: 12px; }
.im-float.icon-right .uk-form-icon { left: auto; right: 12px; }
/* Dark mode */
.uk-dark .im-float-label,
.dark .im-float-label { color: var(--im-label, #aaa); }
.uk-dark .im-float:focus-within .im-float-label,
.dark .im-float:focus-within .im-float-label { color: var(--im-label-active, #ddd); }
/* Trạng thái lỗi/hợp lệ (theo class UIkit nếu bạn dùng uk-form-danger/uk-form-success) */
.im-float .uk-input.uk-form-danger ~ .im-float-label { color: #e5484d; }
.im-float .uk-input.uk-form-success ~ .im-float-label { color: #2ecc71; }
/* Giảm chuyển động nếu người dùng yêu cầu */
@media (prefers-reduced-motion: reduce) {
.im-float-label { transition: none; }
}
Bước 3: Xử lý autofill và dữ liệu ban đầu
Một số trình duyệt bỏ qua :placeholder-shown khi autofill. Đoạn JS nhỏ sẽ thêm/lấy bớt class .has-value để label luôn đúng vị trí.
// Floating Label helper: xử lý autofill, giá trị ban đầu và sự kiện nhập
(function () {
function updateState(input) {
const has = !!input.value;
if (has) {
input.classList.add('has-value'); // để chọn bằng selector anh em
if (input.nextElementSibling && input.nextElementSibling.classList.contains('im-float-label')) {
// không cần gì thêm; CSS đã dựa vào .has-value + label
}
} else {
input.classList.remove('has-value');
}
}
function initFloat(root = document) {
const fields = root.querySelectorAll('.im-float .uk-input, .im-float .uk-textarea, .im-float .uk-select');
fields.forEach((el) => {
// Khởi tạo trạng thái ban đầu
updateState(el);
// Lắng nghe nhập liệu
el.addEventListener('input', () => updateState(el));
el.addEventListener('change', () => updateState(el));
// Trì hoãn kiểm tra autofill sau khi trang tải
setTimeout(() => updateState(el), 250);
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => initFloat());
} else {
initFloat();
}
})();
Mẹo triển khai
- Luôn đặt
placeholder=" "để kích hoạt:placeholder-shownmà không hiển thị chữ trùng label. - Dùng
autocompleteđúng chuẩn để tận dụng autofill. - Đặt icon bằng
.uk-form-iconhoặc.uk-form-icon-flipnếu cần.
Bình luận