Checkout

Shipping, payment, and the order summary.

A checkout is three small forms in sequence, each with one actions row. The field groups lean on autocomplete address and card tokens, which is what lets a browser fill the whole shipping step from one saved profile. City, state, and ZIP share a grid because they submit together; the labels and ids stay one-field units inside it.

Shipping address

The one optional line is marked in its label, per the field unit; the rest are required and get the marker.

Shipping address

<div class="card center" style="--center-max: 40rem">
            <div class="flow">
                <h2>Shipping address</h2>
                <form class="stack">
                    <div class="stack is-tight">
                        <label for="ship-name">Full name</label>
                        <input
                            id="ship-name"
                            type="text"
                            class="input"
                            required
                            autocomplete="name"
                        />
                    </div>
                    <div class="stack is-tight">
                        <label for="ship-street1">Address</label>
                        <input
                            id="ship-street1"
                            type="text"
                            class="input"
                            required
                            autocomplete="address-line1"
                        />
                    </div>
                    <div class="stack is-tight">
                        <label for="ship-street2">Apt, suite, etc. (optional)</label>
                        <input
                            id="ship-street2"
                            type="text"
                            class="input"
                            autocomplete="address-line2"
                        />
                    </div>
                    <div class="grid" style="--grid-min: 10rem">
                        <div class="stack is-tight">
                            <label for="ship-city">City</label>
                            <input
                                id="ship-city"
                                type="text"
                                class="input"
                                required
                                autocomplete="address-level2"
                            />
                        </div>
                        <div class="stack is-tight">
                            <label for="ship-state">State</label>
                            <input
                                id="ship-state"
                                type="text"
                                class="input"
                                required
                                autocomplete="address-level1"
                            />
                        </div>
                        <div class="stack is-tight">
                            <label for="ship-zip">ZIP</label>
                            <input
                                id="ship-zip"
                                type="text"
                                class="input"
                                required
                                inputmode="numeric"
                                autocomplete="postal-code"
                            />
                        </div>
                    </div>
                    <div class="stack is-tight">
                        <label for="ship-country">Country</label>
                        <select id="ship-country" class="input" required autocomplete="country">
                            <option>United States</option>
                            <option>Canada</option>
                            <option>Mexico</option>
                            <option>United Kingdom</option>
                        </select>
                    </div>
                    <div class="cluster is-end">
                        <button class="button is-ghost" type="button">Cancel</button>
                        <button class="button" type="submit">Continue to payment</button>
                    </div>
                </form>
            </div>
        </div>

Payment method

The card number gets its own row; expiry and CVC share a grid, the same pairing as the city row above.

Payment method

<div class="card center" style="--center-max: 40rem">
            <div class="flow">
                <h2>Payment method</h2>
                <form class="stack">
                    <div class="stack is-tight">
                        <label for="pay-card-number">Card number</label>
                        <input
                            id="pay-card-number"
                            type="text"
                            class="input"
                            required
                            placeholder="1234 5678 9012 3456"
                            inputmode="numeric"
                            autocomplete="cc-number"
                        />
                    </div>
                    <div class="grid" style="--grid-min: 8rem">
                        <div class="stack is-tight">
                            <label for="pay-expiry">Expiry</label>
                            <input
                                id="pay-expiry"
                                type="text"
                                class="input"
                                required
                                placeholder="MM / YY"
                                autocomplete="cc-exp"
                            />
                        </div>
                        <div class="stack is-tight">
                            <label for="pay-cvc">CVC</label>
                            <input
                                id="pay-cvc"
                                type="text"
                                class="input"
                                required
                                placeholder="123"
                                inputmode="numeric"
                                autocomplete="cc-csc"
                            />
                        </div>
                    </div>
                    <div class="stack is-tight">
                        <label for="pay-name">Cardholder name</label>
                        <input
                            id="pay-name"
                            type="text"
                            class="input"
                            required
                            autocomplete="cc-name"
                        />
                    </div>
                    <label class="cluster is-tight">
                        <input type="checkbox" name="save-card" class="input" />
                        Save card for future purchases
                    </label>
                    <div class="cluster is-end">
                        <button class="button is-ghost" type="button">Back</button>
                        <button class="button" type="submit">Review order</button>
                    </div>
                </form>
            </div>
        </div>

Order summary

Line items, then totals between dividers, so the amount to pay is the last thing before the button. The place-order button runs the full width; there is no second action.

Order summary

Widget × 2 $24.00
Gadget × 1 $15.00
Book × 3 $39.00

Subtotal $78.00
Shipping $5.00
Tax $6.64

Total $89.64
<div class="card center" style="--center-max: 40rem">
            <div class="flow">
                <h2>Order summary</h2>
                <form class="stack">
                    <div class="stack is-tight">
                        <div class="cluster is-between">
                            <span>Widget <span class="text-muted">&times; 2</span></span>
                            <span>$24.00</span>
                        </div>
                        <div class="cluster is-between">
                            <span>Gadget <span class="text-muted">&times; 1</span></span>
                            <span>$15.00</span>
                        </div>
                        <div class="cluster is-between">
                            <span>Book <span class="text-muted">&times; 3</span></span>
                            <span>$39.00</span>
                        </div>
                    </div>

                    <hr class="divider is-tight" />

                    <div class="stack is-tight">
                        <div class="cluster is-between">
                            <span class="text-muted">Subtotal</span>
                            <span>$78.00</span>
                        </div>
                        <div class="cluster is-between">
                            <span class="text-muted">Shipping</span>
                            <span>$5.00</span>
                        </div>
                        <div class="cluster is-between">
                            <span class="text-muted">Tax</span>
                            <span>$6.64</span>
                        </div>
                    </div>

                    <hr class="divider is-tight" />

                    <div class="cluster is-between">
                        <strong>Total</strong>
                        <strong>$89.64</strong>
                    </div>

                    <button class="button is-block" type="submit">Place order</button>
                </form>
            </div>
        </div>