0

[Series 100 Bài Học HTML/CSS Thực Chiến - Bài 23]: Khởi Động Chương 8 — Xây Dựng Giao Diện Trang Giỏ Hàng (Shopping Cart), Đồng Bộ Bảng Lưới Đa Gian Hàng & Bí Thuật Làm Thanh Thanh Toán Bám Đáy (position: sticky; bottom: 0)

Chào mừng anh em chính thức bước sang Chương 8 với Bài 23 trong chuỗi 100 Bài Học Làm Chủ HTML/CSS Qua Dự Án Clone Shopee!

Ở Chương 7 (từ Bài 20 đến Bài 22), chúng ta đã hoàn thiện trọn vẹn Trang Chi Tiết Sản Phẩm (PDP). Sau khi khách hàng chọn xong màu sắc bàn phím, đọc bình luận 5 sao và bấm nút "Thêm Vào Giỏ Hàng", điểm dừng chân tiếp theo trước khi rút hầu bao chính là Trang Giỏ Hàng (Shopping Cart Page)!

Nếu bạn mở trang Giỏ hàng của Shopee trên máy tính, bạn sẽ nhận ra đây không phải là một bảng <table> đơn thuần như các trang web truyền thống, mà là một hệ thống các khối thẻ trắng tách rời theo từng Gian hàng (Multi-Vendor Cart Blocks) với 3 bài toán kỹ thuật CSS cực kỳ thú vị:

  1. Đồng bộ hóa 6 cột xuyên suốt nhiều khối (Synchronized Grid Columns): Thanh tiêu đề cột (Sản Phẩm | Đơn Giá | Số Lượng | Số Tiền | Thao Tác) nằm ở một khối trắng riêng trên cùng, trong khi các sản phẩm bên dưới lại nằm trong từng khối Shop tách rời nhau. Làm sao để cột Đơn Giá, Số Lượng, Số Tiền của mọi sản phẩm luôn thẳng hàng dọc tuyệt đối với thanh tiêu đề phía trên?

  2. Hộp chọn Phân loại hàng ngay trong Giỏ (Inline Variation Selector): Cho phép khách hàng bấm đổi màu sắc/kích cỡ ngay trong giỏ hàng mà không cần quay lại trang sản phẩm.

  3. Thanh Tổng Tiền & Mua Hàng Bám Dính Đáy Màn Hình (Sticky Bottom Checkout Bar): Khi giỏ hàng có tới 10–20 món đồ, thanh tổng tiền (Chọn Tất Cả, Shopee Voucher, Dùng Shopee Xu, Tổng thanh toán ₫4.740.000, Nút MUA HÀNG) sẽ tự động bám chặt ở mép dưới cùng của màn hình (bottom: 0) cho đến khi người dùng cuộn chạm đáy giỏ hàng!

Hãy cùng giải phẫu và tự tay code toàn bộ khu vực "chốt sổ doanh thu" này ngay bây giờ!

1. Giải phẫu Cấu trúc Giỏ hàng E-Commerce & Bí quyết Đồng bộ 6 Cột bằng CSS Grid

Trong thiết kế luồng mua sắm Thương mại điện tử, màn hình Giỏ hàng (Cart) và Thanh toán (Checkout) luôn tách biệt rõ ràng giữa Danh sách mặt hàng có thể cuộn và Khung tổng kết đơn hàng (Order Summary / Checkout Bar) luôn nằm trong tầm mắt người dùng:

image.png

Trên giao diện Desktop (1200px) của Shopee, để giữ cho Thanh Tiêu Đề Cột (.cart-table-header) và Từng Dòng Sản Phẩm (.cart-item-row) luôn khớp khít từng milimet dù chúng nằm ở các thẻ <div> hoàn toàn độc lập, chúng ta áp dụng chung 1 công thức chia 6 cột bằng CSS Grid:

Plaintext

|<-------------------------------- KHUNG 1200PX (PADDING TRÁI/PHẢI 20PX) -------------------------------->|
+------+------------------------------------------+-------------+---------------+-------------+-----------+
| [✓]  | Sản Phẩm (Ảnh 80px + Tên + Phân loại)    |   Đơn Giá   |   Số Lượng    |   Số Tiền   | Thao Tác  |
| 50px |              flex / 1fr                  |    150px    |     150px     |    140px    |   120px   |
+------+------------------------------------------+-------------+---------------+-------------+-----------+
Thứ tự cột Kích thước khai báo trong grid-template-columns Nội dung hiển thị & Cách căn lề
Cột 1 (5rem) 50px cố định Chứa ô Custom Checkbox màu cam để tích chọn mua sản phẩm.
Cột 2 (1fr) Tự động co giãn chiếm toàn bộ phần còn lại (≈550px\approx 550\text{px}) Chứa Ảnh sản phẩm (80x80px), Tên sản phẩm (2 dòng) và Nút đổi Phân loại hàng.
Cột 3 (15rem) 150px cố định (text-align: center) Hiển thị Giá gốc gạch ngang và Đơn giá khuyến mãi hiện tại.
Cột 4 (15rem) 150px cố định (text-align: center) Chứa bộ tăng giảm số lượng [-] [ 1 ] [+] (Tái sử dụng từ Bài 20!).
Cột 5 (14rem) 140px cố định (text-align: center) Hiển thị Thành tiền màu cam (Đơn giá ×\times Số lượng).
Cột 6 (12rem) 120px cố định (text-align: center) Chứa nút Xóa và link Tìm sản phẩm tương tự.

Công thức vàng dùng chung:

Chỉ cần gán grid-template-columns: 5rem 1fr 15rem 15rem 14rem 12rem; cho cả .cart-table-header lẫn .cart-item-row, cả 6 cột từ trên xuống dưới sẽ thẳng tắp như một bảng Excel mà vẫn giữ được các khoảng hở xám #f5f5f5 tách biệt giữa từng Gian hàng!

2. Nguyên lý position: sticky; bottom: 0 — Ghim Thanh Thanh Toán ở Đáy Màn Hình!

Ở Bài 08 (Sticky Header) và Bài 14 (Sticky Gợi Ý Hôm Nay), chúng ta đã dùng position: sticky kết hợp với top: 0 để ghim phần tử lên đỉnh màn hình khi cuộn xuống.

Nhưng với Thanh Tổng Tiền Giỏ Hàng (.cart-checkout-bar), quy luật hoạt động lại ngược lại hoàn toàn:

  • Nó được đặt ở cuối cùng của khu vực Giỏ hàng trong file HTML.

  • Khi danh sách giỏ hàng quá dài (còn khuất ở phía dưới đáy màn hình), chúng ta muốn thanh Tổng tiền này nổi đè lên và bám chặt ở mép dưới cùng của cửa sổ trình duyệt (bottom: 0)!

  • Ngay khi người dùng cuộn chuột xuống tới sản phẩm cuối cùng của giỏ hàng, thanh Tổng tiền sẽ tự động "hạ cánh" nằm yên vị ngay dưới đáy giỏ hàng và nhường chỗ cho phần Footer bên dưới đi lên!

Đó chính là sức mạnh độc nhất vô nhị của position: sticky; bottom: 0;:

  1. Lúc chưa cuộn tới đáy .cart-section: Nó hoạt động như position: fixed; bottom: 0 (luôn bám sát cạnh dưới màn hình kèm bóng đổ hắt ngược lên trên box-shadow: 0 -2px 10px rgba(0,0,0,0.06)).

  2. Lúc đã cuộn hết .cart-section: Nó trả lại vị trí tự nhiên ở cuối khối giỏ hàng, không bao giờ đè che mất phần Mega Footer!

3. Thực hành: Code Trang Giỏ Hàng Đa Gian Hàng & Sticky Checkout Bar

Bước 1: Bổ sung HTML Khu Vực Giỏ Hàng (.cart-section) vào index.html

Hãy mở file index.html, tìm đến bên trong <div class="shopee-container grid-container"> (bạn có thể đặt ngay bên dưới </section> của Chương 7 - Trang Chi Tiết Sản Phẩm) và chèn toàn bộ cấu trúc Chương 8: Trang Giỏ Hàng Shopee dưới đây:

HTML

        <!-- ================================================================= -->
        <!-- CHƯƠNG 8 (BÀI 23): GIAO DIỆN TRANG GIỎ HÀNG & STICKY CHECKOUT BAR -->
        <!-- ================================================================= -->
        <section class="cart-section">
            
            <!-- 1. Dải thông báo Freeship màu vàng kem trên đỉnh Giỏ hàng -->
            <div class="cart-freeship-banner">
                <i class="fa-solid fa-truck-fast cart-freeship-icon"></i>
                <span>Nhấn vào mục Mã giảm giá ở cuối trang để hưởng miễn phí vận chuyển bạn nhé!</span>
            </div>

            <!-- 2. Thanh Tiêu Đề 6 Cột (Cart Table Header) -->
            <div class="cart-table-header">
                <div class="cart-col-checkbox">
                    <label class="filter-checkbox">
                        <input type="checkbox" class="filter-checkbox__input" checked>
                        <span class="filter-checkbox__box"><i class="fa-solid fa-check"></i></span>
                    </label>
                </div>
                <div class="cart-col-product">Sản Phẩm</div>
                <div class="cart-col-center">Đơn Giá</div>
                <div class="cart-col-center">Số Lượng</div>
                <div class="cart-col-center">Số Tiền</div>
                <div class="cart-col-center">Thao Tác</div>
            </div>

            <!-- 3. KHỐI GIAN HÀNG SỐ 1: AULA OFFICIAL STORE VN -->
            <div class="cart-shop-group">
                
                <!-- Header của Gian hàng trong Giỏ -->
                <div class="cart-shop-header">
                    <div class="cart-col-checkbox">
                        <label class="filter-checkbox">
                            <input type="checkbox" class="filter-checkbox__input" checked>
                            <span class="filter-checkbox__box"><i class="fa-solid fa-check"></i></span>
                        </label>
                    </div>
                    <span class="cart-shop-badge">Yêu thích+</span>
                    <a href="#" class="cart-shop-name">AULA Official Store VN</a>
                    <button type="button" class="cart-shop-chat-btn" title="Chat với Shop">
                        <i class="fa-solid fa-comments"></i>
                    </button>
                </div>

                <!-- Dải khuyến mãi Mua Kèm Deal Sốc bên trong Shop -->
                <div class="cart-bundle-banner">
                    <span class="bundle-tag">Mua Kèm Deal Sốc</span>
                    <span class="bundle-text">Mua thêm 1 sản phẩm để được giảm thêm ₫20.000</span>
                    <a href="#" class="bundle-link">Thêm &gt;</a>
                </div>

                <!-- Dòng Sản Phẩm 1 của Shop 1 -->
                <div class="cart-item-row">
                    <!-- Cột 1: Checkbox -->
                    <div class="cart-col-checkbox">
                        <label class="filter-checkbox">
                            <input type="checkbox" class="filter-checkbox__input" checked>
                            <span class="filter-checkbox__box"><i class="fa-solid fa-check"></i></span>
                        </label>
                    </div>

                    <!-- Cột 2: Ảnh + Tên sản phẩm + Hộp đổi Phân loại hàng -->
                    <div class="cart-item-overview">
                        <a href="#" class="cart-item-img-wrap">
                            <img src="https://placehold.co/160x160/ee4d2d/ffffff?text=AULA+F75+Pro" alt="Bàn phím AULA F75 Pro" class="cart-item-img">
                        </a>
                        <div class="cart-item-details">
                            <a href="#" class="cart-item-name">Bàn phím cơ không dây AULA F75 Pro 3 Mode Mạch Xuôi Hotswap LED RGB</a>
                            <div class="cart-item-return-tag">
                                <i class="fa-solid fa-rotate-left"></i> Đổi ý miễn phí 15 ngày
                            </div>
                        </div>
                        <!-- Nút chọn lại Phân loại hàng ngay trong Giỏ -->
                        <div class="cart-item-variation">
                            <div class="cart-variation-label">
                                Phân loại hàng: <i class="fa-solid fa-caret-down"></i>
                            </div>
                            <div class="cart-variation-value">Trắng Xanh (Ice Vein), Reaper Switch</div>
                        </div>
                    </div>

                    <!-- Cột 3: Đơn Giá -->
                    <div class="cart-col-center cart-item-price">
                        <span class="cart-price-old">₫1.390.000</span>
                        <span class="cart-price-current">₫850.000</span>
                    </div>

                    <!-- Cột 4: Bộ tăng giảm Số Lượng (Tái sử dụng class từ Bài 20) -->
                    <div class="cart-col-center">
                        <div class="quantity-stepper">
                            <button type="button" class="quantity-btn"><i class="fa-solid fa-minus"></i></button>
                            <input type="text" class="quantity-input" value="1" aria-label="Số lượng">
                            <button type="button" class="quantity-btn"><i class="fa-solid fa-plus"></i></button>
                        </div>
                    </div>

                    <!-- Cột 5: Số Tiền (Thành tiền màu cam) -->
                    <div class="cart-col-center">
                        <span class="cart-item-total">₫850.000</span>
                    </div>

                    <!-- Cột 6: Thao Tác (Xóa / Tìm tương tự) -->
                    <div class="cart-col-center cart-item-actions">
                        <button type="button" class="cart-action-delete">Xóa</button>
                        <a href="#" class="cart-action-similar">
                            Tìm sản phẩm tương tự <i class="fa-solid fa-caret-down"></i>
                        </a>
                    </div>
                </div>

                <!-- Chân Gian hàng: Voucher của Shop & Freeship -->
                <div class="cart-shop-footer">
                    <div class="cart-shop-footer-row">
                        <i class="fa-solid fa-ticket cart-voucher-icon"></i>
                        <span>Đã giảm ₫50.000 từ Voucher của Shop</span>
                        <a href="#" class="cart-footer-action-link">Thêm mã giảm giá của Shop</a>
                    </div>
                    <div class="cart-shop-footer-row">
                        <i class="fa-solid fa-truck-fast cart-shipping-icon"></i>
                        <span>Giảm ₫30.000 phí vận chuyển đơn tối thiểu ₫0</span>
                        <a href="#" class="cart-footer-action-link">Tìm hiểu thêm</a>
                    </div>
                </div>

            </div>

            <!-- 4. KHỐI GIAN HÀNG SỐ 2: LG OFFICIAL FLAGSHIP STORE -->
            <div class="cart-shop-group">
                
                <div class="cart-shop-header">
                    <div class="cart-col-checkbox">
                        <label class="filter-checkbox">
                            <input type="checkbox" class="filter-checkbox__input" checked>
                            <span class="filter-checkbox__box"><i class="fa-solid fa-check"></i></span>
                        </label>
                    </div>
                    <span class="cart-shop-badge cart-shop-badge--mall">Mall</span>
                    <a href="#" class="cart-shop-name">LG Official Flagship Store</a>
                    <button type="button" class="cart-shop-chat-btn" title="Chat với Shop">
                        <i class="fa-solid fa-comments"></i>
                    </button>
                </div>

                <!-- Dòng Sản Phẩm 1 của Shop 2 -->
                <div class="cart-item-row">
                    <div class="cart-col-checkbox">
                        <label class="filter-checkbox">
                            <input type="checkbox" class="filter-checkbox__input" checked>
                            <span class="filter-checkbox__box"><i class="fa-solid fa-check"></i></span>
                        </label>
                    </div>

                    <div class="cart-item-overview">
                        <a href="#" class="cart-item-img-wrap">
                            <img src="https://placehold.co/160x160/d0011b/ffffff?text=LG+UltraGear+27" alt="Màn hình LG UltraGear" class="cart-item-img">
                        </a>
                        <div class="cart-item-details">
                            <a href="#" class="cart-item-name">Màn hình Gaming LG UltraGear 27GS60F-B 27 inch FHD IPS 180Hz 1ms HDR10</a>
                            <div class="cart-item-return-tag">
                                <i class="fa-solid fa-shield-heart"></i> Bảo hành chính hãng 24 tháng
                            </div>
                        </div>
                        <div class="cart-item-variation">
                            <div class="cart-variation-label">
                                Phân loại hàng: <i class="fa-solid fa-caret-down"></i>
                            </div>
                            <div class="cart-variation-value">27 Inch / IPS / 180Hz</div>
                        </div>
                    </div>

                    <div class="cart-col-center cart-item-price">
                        <span class="cart-price-old">₫4.890.000</span>
                        <span class="cart-price-current">₫3.890.000</span>
                    </div>

                    <div class="cart-col-center">
                        <div class="quantity-stepper">
                            <button type="button" class="quantity-btn"><i class="fa-solid fa-minus"></i></button>
                            <input type="text" class="quantity-input" value="1" aria-label="Số lượng">
                            <button type="button" class="quantity-btn"><i class="fa-solid fa-plus"></i></button>
                        </div>
                    </div>

                    <div class="cart-col-center">
                        <span class="cart-item-total">₫3.890.000</span>
                    </div>

                    <div class="cart-col-center cart-item-actions">
                        <button type="button" class="cart-action-delete">Xóa</button>
                        <a href="#" class="cart-action-similar">
                            Tìm sản phẩm tương tự <i class="fa-solid fa-caret-down"></i>
                        </a>
                    </div>
                </div>

            </div>

            <!-- ================================================================= -->
            <!-- 5. THANH THANH TOÁN BÁM DÍNH ĐÁY MÀN HÌNH (STICKY CHECKOUT BAR)   -->
            <!-- ================================================================= -->
            <div class="cart-checkout-bar">
                
                <!-- Tầng 1 của Checkout Bar: Chọn Shopee Voucher -->
                <div class="checkout-bar__voucher-row">
                    <div class="checkout-voucher-left">
                        <i class="fa-solid fa-ticket checkout-voucher-icon"></i>
                        <span>Shopee Voucher</span>
                    </div>
                    <a href="#" class="checkout-voucher-link">Chọn hoặc nhập mã</a>
                </div>

                <!-- Tầng 2 của Checkout Bar: Dùng Shopee Xu -->
                <div class="checkout-bar__coin-row">
                    <label class="filter-checkbox checkout-coin-label">
                        <input type="checkbox" class="filter-checkbox__input" checked>
                        <span class="filter-checkbox__box"><i class="fa-solid fa-check"></i></span>
                        <i class="fa-solid fa-coins checkout-coin-icon"></i>
                        <span class="checkout-coin-title">Shopee Xu</span>
                        <span class="checkout-coin-sub">Đã dùng 20.000 Shopee Xu</span>
                    </label>
                    <span class="checkout-coin-discount">-₫20.000</span>
                </div>

                <!-- Tầng 3 (Tầng chính): Chọn tất cả + Tổng thanh toán + Nút MUA HÀNG -->
                <div class="checkout-bar__main-row">
                    
                    <!-- Nhánh trái: Chọn tất cả / Xóa / Lưu vào mục Đã thích -->
                    <div class="checkout-main__left">
                        <label class="filter-checkbox checkout-select-all">
                            <input type="checkbox" class="filter-checkbox__input" checked>
                            <span class="filter-checkbox__box"><i class="fa-solid fa-check"></i></span>
                            <span class="checkout-action-btn">Chọn Tất Cả (2)</span>
                        </label>
                        <button type="button" class="checkout-action-btn">Xóa</button>
                        <button type="button" class="checkout-action-btn checkout-action-btn--primary">Lưu vào mục Đã thích</button>
                    </div>

                    <!-- Nhánh phải: Tổng thanh toán & Nút MUA HÀNG cỡ lớn -->
                    <div class="checkout-main__right">
                        <div class="checkout-total-info">
                            <div class="checkout-total-top">
                                <span class="checkout-total-label">Tổng thanh toán (2 Sản phẩm):</span>
                                <span class="checkout-total-price">₫4.670.000</span>
                            </div>
                            <div class="checkout-total-bottom">
                                <span>Tiết kiệm</span>
                                <span class="checkout-saved-amount">₫1.560.000</span>
                            </div>
                        </div>

                        <button type="button" class="btn btn--primary checkout-submit-btn">
                            Mua Hàng
                        </button>
                    </div>

                </div>

            </div>

        </section>

Bước 2: Viết CSS cho Giỏ Hàng 6 Cột & Sticky Bottom Bar trong ./assets/css/main.css

Hãy mở file main.css, cuộn xuống dưới cùng và bổ sung đoạn code CSS của Chương 8 dưới đây:

CSS

/* Bổ sung vào cuối file ./assets/css/main.css */

/* --- CHƯƠNG 8 (BÀI 23): GIAO DIỆN TRANG GIỎ HÀNG & STICKY CHECKOUT BAR --- */

.cart-section {
    margin-top: 2rem;
    margin-bottom: 4rem;
}

/* 1. Dải thông báo Freeship màu vàng kem */
.cart-freeship-banner {
    background-color: #fffefb;
    border: 1px solid rgba(224, 168, 0, 0.4);
    padding: 1.2rem 1.6rem;
    border-radius: 2px;
    margin-bottom: 1.2rem;
    display: flex;
    align-items: center;
    gap: 1rem;
    font-size: 1.4rem;
    color: var(--text-primary);
}

.cart-freeship-icon {
    color: #00bfa5;
    font-size: 1.8rem;
}

/* --- CÔNG THỨC CHIA 6 CỘT ĐỒNG BỘ CHO CẢ HEADER LẪN TỪNG DÒNG SẢN PHẨM --- */
.cart-table-header,
.cart-item-row {
    display: grid;
    /* Cột 1 (Checkbox: 50px) | Cột 2 (Sản phẩm: 1fr) | Cột 3,4,5,6 cố định chiều rộng */
    grid-template-columns: 5rem 1fr 15rem 15rem 14rem 12rem;
    align-items: center;
    padding: 0 2rem;
}

/* 2. Thanh Tiêu Đề 6 Cột (.cart-table-header) */
.cart-table-header {
    height: 5.5rem;
    background-color: var(--white-color);
    border-radius: 2px;
    box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.05);
    margin-bottom: 1.2rem;
    font-size: 1.4rem;
    color: #888888;
}

.cart-col-product {
    color: var(--text-primary);
}

.cart-col-center {
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

/* 3. Khối Gian Hàng trong Giỏ (.cart-shop-group) */
.cart-shop-group {
    background-color: var(--white-color);
    border-radius: 2px;
    box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.05);
    margin-bottom: 1.5rem;
}

.cart-shop-header {
    height: 6rem;
    padding: 0 2rem;
    border-bottom: 1px solid rgba(0, 0, 0, 0.09);
    display: flex;
    align-items: center;
}

.cart-shop-header .cart-col-checkbox {
    width: 5rem;                    /* Khớp đúng 50px với cột 1 của Grid bên dưới! */
    flex-shrink: 0;
}

.cart-shop-badge {
    background-color: var(--shopee-primary);
    color: var(--white-color);
    font-size: 1.1rem;
    font-weight: 500;
    padding: 0.2rem 0.5rem;
    border-radius: 2px;
    margin-right: 0.8rem;
}

.cart-shop-badge--mall {
    background-color: var(--shopee-mall-red);
}

.cart-shop-name {
    font-size: 1.4rem;
    font-weight: 500;
    color: var(--text-primary);
    margin-right: 0.8rem;
}

.cart-shop-chat-btn {
    color: var(--shopee-primary);
    font-size: 1.6rem;
}

/* Dải Mua Kèm Deal Sốc bên trong Shop */
.cart-bundle-banner {
    background-color: #fff3f0;
    padding: 1rem 2rem 1rem 7rem;   /* Thụt lề trái 70px (20px padding + 50px cột checkbox) để thẳng hàng với ảnh! */
    display: flex;
    align-items: center;
    gap: 1.2rem;
    font-size: 1.3rem;
}

.bundle-tag {
    color: var(--shopee-primary);
    border: 1px solid var(--shopee-primary);
    padding: 0.1rem 0.5rem;
    border-radius: 2px;
    font-size: 1.1rem;
    background-color: var(--white-color);
}

.bundle-link {
    color: var(--shopee-primary);
    font-weight: 500;
}

/* 4. Dòng Sản Phẩm trong Giỏ (.cart-item-row) */
.cart-item-row {
    padding-top: 2rem;
    padding-bottom: 2rem;
    border-bottom: 1px solid rgba(0, 0, 0, 0.09);
}

/* Cột 2: Chia thành Ảnh (80px) + Tên sản phẩm (flex: 1) + Phân loại hàng (180px) */
.cart-item-overview {
    display: flex;
    align-items: flex-start;
    gap: 1.4rem;
    padding-right: 2rem;
}

.cart-item-img-wrap {
    width: 8rem;
    height: 8rem;
    flex-shrink: 0;
    border: 1px solid rgba(0, 0, 0, 0.09);
    border-radius: 2px;
    overflow: hidden;
}

.cart-item-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.cart-item-details {
    flex: 1;
}

.cart-item-name {
    font-size: 1.4rem;
    line-height: 1.8rem;
    color: var(--text-primary);
    margin-bottom: 0.8rem;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.cart-item-return-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 1.2rem;
    color: var(--shopee-primary);
    border: 1px solid var(--shopee-primary);
    padding: 0.1rem 0.5rem;
    border-radius: 2px;
}

/* Hộp chọn lại Phân loại hàng ngay trong dòng sản phẩm */
.cart-item-variation {
    width: 18rem;
    flex-shrink: 0;
    color: var(--text-secondary);
    font-size: 1.3rem;
    line-height: 1.7rem;
    cursor: pointer;
    padding: 0.4rem 0.8rem;
    border-radius: 2px;
    transition: background-color 0.15s ease;
}

.cart-item-variation:hover {
    background-color: rgba(0, 0, 0, 0.03);
}

.cart-variation-label {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 0.2rem;
}

/* Cột 3, 5, 6: Đơn giá, Thành tiền & Thao tác */
.cart-item-price {
    flex-direction: row;
    gap: 0.8rem;
    font-size: 1.4rem;
}

.cart-price-old {
    color: var(--text-secondary);
    text-decoration: line-through;
}

.cart-price-current {
    color: var(--text-primary);
}

.cart-item-total {
    font-size: 1.5rem;
    color: var(--shopee-primary);
    font-weight: 500;
}

.cart-item-actions {
    gap: 0.6rem;
}

.cart-action-delete {
    font-size: 1.4rem;
    color: var(--text-primary);
}

.cart-action-delete:hover {
    color: var(--shopee-primary);
}

.cart-action-similar {
    font-size: 1.25rem;
    color: var(--shopee-primary);
    line-height: 1.5rem;
}

/* Chân Gian hàng: Voucher & Freeship */
.cart-shop-footer {
    padding: 1.4rem 2rem 1.4rem 7rem;
    display: flex;
    flex-direction: column;
    gap: 1.2rem;
    font-size: 1.35rem;
}

.cart-shop-footer-row {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.cart-voucher-icon { color: var(--shopee-primary); font-size: 1.6rem; }
.cart-shipping-icon { color: #00bfa5; font-size: 1.6rem; }

.cart-footer-action-link {
    color: #0055aa;
    margin-left: 1.2rem;
}

/* ================================================================= */
/* 5. BÍ THUẬT: THANH THANH TOÁN BÁM DÍNH ĐÁY MÀN HÌNH (BOTTOM: 0)   */
/* ================================================================= */
.cart-checkout-bar {
    background-color: var(--white-color);
    border-radius: 2px;
    /* Bóng đổ hắt ngược lên phía trên (0 -4px 12px) tạo cảm giác nổi đè lên danh sách giỏ hàng! */
    box-shadow: 0 -0.3rem 1rem 0 rgba(0, 0, 0, 0.06);
    border: 1px solid rgba(0, 0, 0, 0.05);
    
    /* KÍCH HOẠT STICKY BOTTOM BAR */
    position: sticky;
    bottom: 0;
    z-index: calc(var(--z-sticky) - 2); /* Tầng 98: Nổi trên danh sách sản phẩm khi cuộn */
}

/* Tầng 1: Chọn Shopee Voucher (Căn về nửa bên phải từ cột 550px) */
.checkout-bar__voucher-row {
    padding: 1.2rem 2.4rem 1.2rem 55rem;
    border-bottom: 1px dashed rgba(0, 0, 0, 0.09);
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 1.4rem;
}

.checkout-voucher-left {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    color: var(--text-primary);
}

.checkout-voucher-icon {
    color: var(--shopee-primary);
    font-size: 1.8rem;
}

.checkout-voucher-link {
    color: #0055aa;
}

/* Tầng 2: Dùng Shopee Xu */
.checkout-bar__coin-row {
    padding: 1.2rem 2.4rem 1.2rem 55rem;
    border-bottom: 1px dashed rgba(0, 0, 0, 0.09);
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 1.4rem;
}

.checkout-coin-label {
    align-items: center;
}

.checkout-coin-icon {
    color: #f6a700;                 /* Màu vàng đồng xu Shopee */
    font-size: 1.6rem;
}

.checkout-coin-title {
    color: var(--text-primary);
    font-weight: 500;
}

.checkout-coin-sub {
    color: var(--text-secondary);
    font-size: 1.3rem;
    margin-left: 0.6rem;
}

.checkout-coin-discount {
    color: var(--shopee-primary);
    font-weight: 500;
}

/* Tầng 3: Chọn tất cả + Tổng thanh toán + Nút MUA HÀNG */
.checkout-bar__main-row {
    padding: 1.6rem 2.4rem 1.6rem 2rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.checkout-main__left {
    display: flex;
    align-items: center;
    gap: 2.4rem;
}

.checkout-select-all {
    align-items: center;
    gap: 1.6rem;
}

.checkout-action-btn {
    font-size: 1.5rem;
    color: var(--text-primary);
    cursor: pointer;
}

.checkout-action-btn:hover {
    color: var(--shopee-primary);
}

.checkout-action-btn--primary {
    color: var(--shopee-primary);
}

.checkout-main__right {
    display: flex;
    align-items: center;
    gap: 2rem;
}

.checkout-total-info {
    text-align: right;
}

.checkout-total-top {
    display: flex;
    align-items: baseline;
    justify-content: flex-end;
    gap: 0.8rem;
}

.checkout-total-label {
    font-size: 1.5rem;
    color: var(--text-primary);
}

.checkout-total-price {
    font-size: 2.4rem;              /* Tổng tiền to 24px màu cam cực kỳ nổi bật */
    color: var(--shopee-primary);
    font-weight: 500;
}

.checkout-total-bottom {
    font-size: 1.3rem;
    color: var(--text-primary);
    margin-top: 0.2rem;
}

.checkout-saved-amount {
    color: var(--shopee-primary);
    margin-left: 1.2rem;
}

.checkout-submit-btn {
    min-width: 21rem;               /* Nút Mua Hàng rộng 210px, cao 40px chuẩn Shopee */
    height: 4rem;
    font-size: 1.5rem;
    font-weight: 500;
}

image.png

4. Giải mã dòng code: 3 Bí quyết thực chiến đắt giá trong Bài 23

  1. Bóng đổ hắt ngược lên trên (box-shadow: 0 -0.3rem 1rem ...) của .cart-checkout-bar:

    • Ở Bài 08, thanh Sticky Header nằm ở đỉnh màn hình (top: 0), nên chúng ta đặt giá trị trục Y của bóng đổ là số dương (0 1px 4px) để bóng đổ hắt xuống dưới.

    • Ngược lại, thanh .cart-checkout-bar bám ở đáy màn hình (bottom: 0) và các dòng sản phẩm trôi ở phía trên nó. Vì vậy, chúng ta phải đặt giá trị trục Y là số âm (-0.3rem tức -3px) để bóng đổ hắt ngược lên phía trên, tạo ranh giới tách biệt rõ ràng giữa thanh thanh toán và danh sách sản phẩm bên dưới!

  2. Thụt lề toán học padding-left: 7rem (70px) ở .cart-bundle-banner và .cart-shop-footer:

    • Bạn có nhận thấy dòng "Mua Kèm Deal Sốc" và dòng "Đã giảm ₫50.000 từ Voucher của Shop" luôn bắt đầu thẳng hàng dọc tuyệt đối với mép trái của tấm ảnh sản phẩm (chứ không tràn ra tận dưới ô Checkbox) không?

    • Lý do là mỗi dòng sản phẩm có padding-left: 2rem (20px) cộng với Cột 1 Checkbox rộng 5rem (50px) =7rem= 7\text{rem} (70px). Chỉ cần đặt padding-left: 7rem cho dải khuyến mãi và chân Shop, mọi thành phần đều nằm trên một đường thẳng kiến trúc hoàn hảo!

  3. Đường kẻ nét đứt border-bottom: 1px dashed rgba(0,0,0,0.09) giữa các tầng của Checkout Bar:

    • Trên Shopee, khu vực Shopee Voucher và Shopee Xu trên thanh thanh toán không dùng đường kẻ liền (solid) mà dùng đường kẻ nét đứt (dashed) giống như đường răng cưa xé vé của một chiếc cuống vé giảm giá thực tế!

5. Bài tập trải nghiệm thực tế & Hẹn gặp ở Bài 24!

Hãy lưu lại file index.html và main.css, sau đó nhấn F5 trên trình duyệt và cuộn tới khu vực Giỏ Hàng (Chương 8):

  1. Khi bạn bắt đầu cuộn chuột bước vào khu vực Giỏ hàng (khi sản phẩm số 2 vẫn còn nằm thấp phía dưới màn hình), bạn sẽ thấy Thanh Tổng Thanh Toán ₫4.670.000 tự động nổi lên và bám chặt ở mép dưới cùng màn hình!

  2. Khi bạn cuộn tiếp qua hết sản phẩm cuối cùng của Shop LG, thanh Tổng thanh toán sẽ nhẹ nhàng "đậu" lại đúng vị trí kết thúc giỏ hàng để nhường chỗ cho phần tiếp theo đi lên!

  3. Bạn có thể click chuột tích/bỏ tích vào các ô Checkbox của từng sản phẩm, từng Gian hàng hoặc ô Shopee Xu mượt mà nhờ tái sử dụng bộ .filter-checkbox từ Bài 18!

Thử thách khám phá dành cho bạn trước khi sang Bài 24:

  1. Hãy thử nhân bản (copy-paste) thêm 2 khối <div class="cart-shop-group"> nữa vào trong .cart-section (để giỏ hàng có khoảng 4–5 gian hàng dài hơn chiều cao màn hình), sau đó lăn chuột lên xuống để cảm nhận sự phối hợp đỉnh cao giữa Sticky Header ở đỉnh (top: 0) và Sticky Checkout Bar ở đáy (bottom: 0) cùng lúc!

  2. Hãy thử thiết kế thêm một hộp Popover nhỏ xổ ra khi người dùng bấm vào mục "Phân loại hàng: ▾" (.cart-item-variation) để cho phép chọn lại màu sắc bàn phím ngay trong giỏ hàng!

Ở Bài 24, chúng ta sẽ hoàn thiện bước tiếp theo ngay sau khi bấm nút "Mua Hàng": Xây dựng Giao Diện Trang Thanh Toán (Checkout / Order Confirmation Page) với Đường viền Phong bì thư kẻ sọc Đỏ - Xanh (repeating-linear-gradient) cực kỳ nổi tiếng ở khung Địa Chỉ Nhận Hàng và bộ chọn Phương Thức Thanh Toán!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí