Passer au contenu principal

Captive Portal personnalisé : Guide HTML et CSS

Ce guide de référence technique présente les normes de développement, l'architecture CSS et les contraintes réseau requises pour concevoir et coder une page de destination de Captive Portal personnalisée. Il fournit aux développeurs frontend et aux architectes réseau des stratégies concrètes pour naviguer dans les environnements Apple CNA et Android webview, garantissant ainsi des expériences WiFi invités parfaites au pixel près, conformes et hautement performantes.

📖 11 min de lecture📝 3,190 mots🔧 2 exemples concrets3 questions d'entraînement📚 8 définitions clés

Écouter ce guide

Voir la transcription du podcast
Portail Captif Personnalisé : Guide HTML et CSS — Une Fiche Technique Purple [INTRODUCTION] Bienvenue dans la série des Fiches Techniques Purple. Aujourd'hui, nous entrons dans le vif du sujet sur un élément qui concerne chaque déploiement de WiFi invité : le Captive Portal. Plus précisément, nous allons voir comment rédiger un code HTML et CSS propre et fiable pour une page d'accueil de Captive Portal personnalisée. Si vous vous êtes déjà connecté au WiFi d'un hôtel et avez été accueilli par une page de connexion cassée — images manquantes, texte sans style, bouton de connexion qui ne réagit pas au toucher — vous avez fait l'expérience de ce qui se produit lorsqu'un développeur conçoit un portail sans comprendre les contraintes de l'environnement dans lequel il s'exécute. Aujourd'hui, nous allons faire en sorte que cela ne vous arrive pas. Cette fiche technique s'adresse aux développeurs frontend, aux designers créatifs et aux développeurs web qui conçoivent un Captive Portal de zéro ou qui personnalisent un modèle existant. Nous aborderons la structure HTML, les règles CSS essentielles, les contraintes du mini-navigateur Apple CNA qui piègent même les développeurs chevronnés, et comment les plateformes comme le concepteur de portail de Purple peuvent éliminer presque entièrement cette complexité. Entrons dans le vif du sujet. [ANALYSE TECHNIQUE APPROFONDIE] Tout d'abord, définissons ce qu'est réellement un Captive Portal au niveau du réseau. Lorsqu'un appareil se connecte à un réseau WiFi qui nécessite une authentification, le réseau intercepte le trafic HTTP et redirige l'utilisateur vers une page d'accueil. C'est le Captive Portal. L'utilisateur voit une page de connexion, effectue une action — saisir un e-mail, accepter les conditions, se connecter via les réseaux sociaux — puis le réseau lui accorde un accès complet à Internet. Le point critique à comprendre est l'endroit où cette page est affichée. Sur les appareils iOS, elle s'ouvre dans le Captive Network Assistant d'Apple — le CNA — qui est une version allégée de WebKit webview. Ce n'est pas Safari. Il n'a pas de cookies persistants. Il ne peut pas charger de ressources externes. Son support JavaScript est limité. Et il se ferme dès que l'utilisateur bascule vers une autre application. Sur macOS, le CNA s'affiche dans une fenêtre fixe de 900 par 572 pixels. Sur Android, les appareils modernes utilisent les Chrome Custom Tabs, qui sont nettement plus performants. Windows 10 ouvre le navigateur par défaut de l'utilisateur. Les appareils Samsung utilisent Samsung Internet. Cette fragmentation des plateformes est la principale source de dysfonctionnement des portails captifs en production. Les développeurs testent sur leur téléphone Android, tout semble parfait, puis les clients de l'hôtel équipés d'un iPhone se retrouvent face à un écran blanc avec du texte sans style. Voyons donc comment coder de manière défensive. La règle d'or pour le HTML et le CSS d'un Captive Portal est la suivante : traitez la page comme si elle n'avait pas de connexion Internet. Car pendant la phase d'authentification, c'est le cas. Le réseau est captif. Toute ressource que votre page tente de charger depuis une URL externe — une police Google Font, une feuille de style hébergée sur un CDN, une bibliothèque JavaScript, un logo — échouera silencieusement ou provoquera un indicateur de chargement infini.Commençons par la structure HTML. Votre document doit être une page HTML5 propre. Dans l'en-tête (head), vous devez inclure une balise méta viewport avec le contenu défini sur width=device-width et initial-scale=1. C'est non négociable pour le rendu mobile. Sans cela, iOS affichera la page avec une largeur de 980 pixels et la réduira, rendant le tout microscopique. Votre CSS doit être intégré — soit dans un bloc style au sein de l'élément head, soit sous forme d'attributs de style en ligne sur chaque élément. N'utilisez pas de feuille de style externe liée via une balise link. Cette feuille de style réside sur votre serveur, que le réseau captif ne peut pas atteindre pendant l'authentification. La page s'affichera alors sans aucun style. Pour les polices, utilisez une pile de polices système. Quelque chose comme : font-family — apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif. Cela indique au navigateur d'utiliser la police système disponible. N'utilisez pas Google Fonts. L'appel d'importation échouera et votre police de secours sera Times New Roman, ce qui ne correspond pas à l'image de marque pour laquelle votre client paie. Pour les images — votre logo, les graphismes d'arrière-plan, les éléments décoratifs — vous avez deux options. Soit vous les hébergez sur le même serveur de Captive Portal, ce qui signifie qu'elles se trouvent sur le même réseau local et sont accessibles avant la fin de l'authentification. Soit, et c'est encore mieux, vous les encodez sous forme d'URI de données Base64 directement dans votre HTML ou CSS. Cela élimine complètement toute dépendance externe. Parlons maintenant de la mise en page. Étant donné que plus de quatre-vingt-dix pour cent des connexions aux portails captifs se font sur des appareils mobiles, votre conception doit être pensée en priorité pour le mobile (mobile-first). Cela signifie une mise en page sur une seule colonne, avec une largeur maximale d'environ 480 pixels, centrée sur la page. Utilisez flexbox sur l'élément body — display flex, flex-direction column, align-items center, justify-content center, min-height 100vh. Cela centre votre carte de contenu verticalement et horizontalement sur n'importe quelle taille d'écran. Votre bouton d'appel à l'action principal doit être adapté au tactile. Les directives d'interface humaine d'Apple spécifient une zone de contact minimale de 44 par 44 pixels. En pratique, pour un CTA principal, privilégiez une hauteur d'environ 48 pixels, sur toute la largeur du conteneur, avec un border-radius d'environ 8 à 12 pixels. Pour les champs de formulaire — saisie d'e-mail, saisie de nom — définissez la taille de la police (font-size) à au moins 16 pixels. C'est essentiel. iOS Safari et le CNA zoomeront automatiquement sur tout champ de saisie dont la taille de police est inférieure à 16 pixels, ce qui brisera votre mise en page soigneusement élaborée. Définir font-size à 16 pixels ou plus empêche ce comportement de zoom. La section sur le consentement légal mérite une attention particulière. Conformément au GDPR, si vous collectez des données personnelles — même une simple adresse e-mail —, vous devez obtenir un consentement explicite et éclairé. Cela implique une case à cocher qui est décochée par défaut, avec un libellé visible indiquant clairement ce à quoi l'utilisateur consent. Ne pré-cochez pas la case. La case de consentement elle-même doit être clairement visible sans avoir à faire défiler la page. Voici maintenant un détail d'implémentation crucial, spécifiquement pour le CNA d'iOS. Lorsque l'utilisateur termine l'authentification, le CNA vérifie si le domaine captif est devenu accessible. Cette vérification est déclenchée par une navigation complète sur la page, et non par des appels AJAX JavaScript. Cela signifie que si vous concevez une application monopage qui soumet le formulaire via fetch ou XMLHttpRequest et met à jour le DOM sans redirection complète de la page, le CNA ne détectera jamais que l'authentification est terminée. Vous devez rediriger vers une nouvelle URL après l'authentification — une redirection HTTP complète, et non une manipulation du DOM par JavaScript. C'est l'une des erreurs les plus courantes dans le développement de Captive Portal. Pour le JavaScript, restez minimaliste. Le CNA a un support JS limité et n'a pas accès à localStorage ou sessionStorage. Les cookies sont détruits à la fermeture du CNA. Toute gestion d'état qui repose sur ces API de navigateur échouera. Les écouteurs d'événements en JavaScript natif (Vanilla) fonctionnent très bien. jQuery est une dépendance externe de 30 kilo-octets qui ne parviendra pas à se charger. [RECOMMANDATIONS D'IMPLÉMENTATION ET PIÈGES À ÉVITER] Voici la liste de contrôle pratique pour votre implémentation. Premièrement : la balise meta viewport, toujours. Deuxièmement : tout le CSS en ligne, pas de feuilles de style externes. Troisièmement : toutes les images servies depuis le serveur du Captive Portal ou encodées en Base64. Quatrièmement : une pile de polices système, pas de polices web. Cinquièmement : une taille de police minimale de 16 pixels sur tous les champs de saisie. Sixièmement : des zones de clic adaptées au tactile, d'au moins 44 par 44 pixels. Septièmement : une mise en page sur une seule colonne, d'une largeur maximale de 480 pixels. Huitièmement : une redirection complète de la page lors de l'authentification, et non une mise à jour d'état en JavaScript. Neuvièmement : une case à cocher de consentement conforme au GDPR, décochée par défaut. Dixièmement : testez sur un appareil iOS réel en utilisant un véritable réseau captif, et non un aperçu de navigateur. Les pièges que je vois le plus souvent en production. Numéro un : Google Fonts — supprimez l'importation, elle échouera. Numéro deux : les bibliothèques JavaScript externes — Bootstrap, jQuery, tout script hébergé sur un CDN échouera. Numéro trois : les variables CSS déclarées dans une feuille de style externe — elles doivent figurer dans votre bloc de style en ligne. Numéro quatre : les images d'arrière-plan référencées par URL — encodez-les en Base64. Numéro cinq : la soumission de formulaire AJAX sans redirection post-authentification — le CNA ne détectera pas la fin de l'authentification. Parlons maintenant franchement de l'alternative entre développer ou acheter. Développer un Captive Portal personnalisé à partir de zéro signifie que vous êtes également responsable de l'infrastructure backend — le serveur RADIUS, la base de données, le certificat SSL, la configuration DNS, l'intégration réseau avec vos points d'accès et les correctifs de sécurité continus. C'est un engagement d'ingénierie considérable. Le créateur de portail de Purple vous offre une interface glisser-déposer avec un éditeur HTML et CSS personnalisé pour les développeurs qui ont besoin d'un contrôle au pixel près, tout en gérant l'ensemble de l'infrastructure backend — l'authentification, la capture de données, les analyses, les outils de conformité GDPR et les intégrations réseau avec plus de 200 fournisseurs de points d'accès. Vous bénéficiez du contrôle créatif sans la charge de l'infrastructure. [QUESTIONS-RÉPONSES RAPIDES] Puis-je utiliser CSS Grid dans un Captive Portal ? Oui, mais testez spécifiquement sur iOS CNA. Flexbox bénéficie d'un support plus large dans les anciennes versions de WebKit. Puis-je utiliser des logos SVG ? Oui, les SVG intégrés sont entièrement pris en charge et préférables aux PNG encodés en Base64 pour les logos, car ils s'adaptent parfaitement aux écrans retina. Le CNA macOS prend-il en charge les mêmes contraintes que le CNA iOS ? Dans l'ensemble oui, avec une différence : le CNA macOS s'affiche dans une fenêtre fixe de 900 par 572 pixels. Puis-je utiliser un framework CSS comme Tailwind ? Uniquement si vous générez un fichier CSS purgé et autonome, et que vous l'intégrez directement dans votre bloc de style. Qu'en est-il de l'HTTPS ? Votre Captive Portal doit être servi via HTTP pour que la redirection initiale fonctionne — les connexions HTTPS ne peuvent pas être interceptées par le réseau captif. [RÉSUMÉ ET PROCHAINES ÉTAPES] Pour résumer le briefing d'aujourd'hui. Un Captive Portal personnalisé est un environnement web contraint, et non un contexte de navigateur standard. L'Apple CNA et les webviews Android imposent des limites strictes aux ressources externes, aux cookies, au JavaScript et à l'état de la session. La solution consiste à créer des pages HTML autonomes avec du CSS intégré, des polices système, des images encodées en Base64 et des redirections de page entière lors de l'authentification. Pour les exploitants de sites et les équipes informatiques qui évaluent leurs options : si votre besoin est un portail entièrement personnalisé à l'image de votre marque avec du HTML et du CSS sur mesure, le choix se résume à créer et maintenir vous-même l'intégralité de la pile technique — ce qui représente un engagement d'ingénierie conséquent — ou à utiliser une plateforme comme Purple qui fournit la capacité d'édition HTML et CSS personnalisée en plus d'une infrastructure backend de niveau production. Les prochaines étapes à partir d'ici : consultez la documentation de l'éditeur de portail de Purple, auditez votre portail existant par rapport à la checklist mobile-first que nous avons abordée aujourd'hui, et si vous partez de zéro, utilisez la structure de modèle HTML que nous avons présentée comme base de référence. Merci pour votre écoute, et à bientôt pour le prochain briefing.

📚 Fait partie de notre série principale : Le guide ultime des Captive Portals

header_image.png

Executive Summary

For enterprise venues—ranging from luxury hotels Hospitality and retail chains Retail to transit hubs Transport and modern medical campuses Healthcare —the guest WiFi splash page is the digital front door. However, over 90% of guest WiFi logins occur on mobile devices, where rendering is governed not by standard browsers like Safari or Chrome, but by highly restricted Captive Network Assistant (CNA) webviews [1]. These "mini-browsers" enforce severe sandbox limitations: they block external CDNs, disable persistent cookies, ignore external web fonts, and severely restrict JavaScript execution to mitigate security risks and prevent session hijacking [2].

When a developer designs a splash page using traditional web standards, these constraints result in broken layouts, missing brand assets, and non-functional login buttons, directly impacting customer satisfaction and digital engagement. This guide provides solutions to these challenges, presenting defensive coding practices—such as inline CSS, Base64 asset encoding, system font stacks, and explicit navigation-driven authentication handshakes—to ensure seamless cross-platform rendering. Furthermore, we examine how utilising a managed solution like Purple's portal builder allows developers to maintain complete HTML/CSS creative control while offloading RADIUS authentication, database scaling, GDPR/PCI compliance, and multi-vendor AP integrations [3].

Technical Deep-Dive

To build a resilient custom captive portal, developers must understand the network-level interception and browser virtualisation that occurs when a guest associates with an open Service Set Identifier (SSID).

The Captive Portal Lifecycle

When a client device associates with a captive SSID, the following sequence is triggered:

  1. IP Association: The device completes a 3-way handshake and requests an IP address via DHCP.
  2. Active Connectivity Probe: The operating system's background network manager immediately sends an HTTP GET request to a dedicated vendor-neutral canary URL (e.g., Apple's http://captive.apple.com/hotspot-detect.html or Google's http://connectivitycheck.gstatic.com/generate_204) [1].
  3. DNS/HTTP Interception: The local Wireless LAN Controller (WLC) or Access Point (AP) intercepts this port 80 HTTP request. Instead of returning the expected HTTP 200 or 204 status, the gateway redirects the client's traffic to the captive portal's landing page URL via an HTTP 302 redirect [2].
  4. Webview Spawning: Detecting the redirect, the OS spawns its native Captive Network Assistant (CNA) mini-browser to display the redirected splash page, bypassing the need for the user to manually open a full browser.
  5. Authentication and State Transition: The user completes the login form, submitting credentials back to the portal server, which instructs the gateway (often via a RADIUS Access-Accept or external API call) to authorise the MAC address.
  6. CNA Exit Handshake: The CNA mini-browser performs another HTTP GET to its canary URL. If it receives the expected 200/204 response, it changes its top-right button from "Cancel" to "Done" and establishes the WiFi connection as the primary network interface.

Platform-Specific Mini-Browser Constraints

Each operating system handles this lifecycle within different webview environments, resulting in highly fragmented behaviour. The table below details these critical constraints:

Platform / Webview Display Method Persistent Cookies External Web Fonts JavaScript Execution Window Dimensions Exit Handshake Trigger
Apple iOS CNA (Websheet) Mini-Browser Popup Blocked (Destroyed on close) Blocked (Offline) Limited (No localStorage/sessionStorage) Responsive (Device-width) Full-page HTTP Redirect Only [1]
Apple macOS CNA (Captive Network Assistant) Mini-Browser Popup Blocked Blocked Limited (No alert/confirm dialogs) Fixed (900px x 572px) Full-page HTTP Redirect Only
Android (Google) (CaptivePortalLogin) Push Notification -> Chrome Custom Tab Allowed (Shared with Chrome) Allowed (If whitelisted in walled garden) Full Responsive Automatic (Captive Portal API / 204 Check) [2]
Samsung Android (Samsung Internet) Push Notification -> Mini-Browser Allowed Allowed Full Responsive Automatic
Windows 10/11 (Default Browser) Auto-Launch Default Browser Allowed (Full browser context) Allowed Full Responsive Manual / Automatic

cna_constraints_comparison.png

Coding Around the Apple CNA "Done" Button Trap

One of the most frequent failure modes in custom portal development is the "Done" Button Trap on iOS devices. When a user authenticates, the iOS Websheet webview must detect that the network is no longer captive. It does this by monitoring the success of its background canary requests.

Crucially, the iOS CNA will only trigger this check upon a full-page HTTP navigation (location redirect). If a developer builds a modern Single Page Application (SPA) that submits form data via an asynchronous AJAX call (e.g., fetch() or Axios) and updates the DOM dynamically without changing the URL, the CNA will never re-run its connectivity check. The user will be authenticated at the gateway level, but the CNA button in the top-right corner will remain as "Cancel". If the frustrated user clicks "Cancel", the iOS device will immediately disassociate from the SSID, terminating the WiFi session [1].

To prevent this, the authentication success handler must perform a full-page redirect to a physical landing page (e.g., window.location.href = '/success') or submit the login form natively via a standard HTTP POST action.

Implementation Guide

To ensure consistent rendering across all platforms, developers must transition from modern, asset-heavy web design to a highly self-contained, defensive coding style.

The Golden Rule: Design for Zero Internet Connectivity

During the captive state, the client device has no access to the wider internet. It can only resolve and access IP addresses and domains explicitly whitelisted in the wireless controller's Walled Garden (such as the IP of the captive portal server itself). Therefore, any external asset referenced in your HTML will fail to load, resulting in a broken layout.

To design defensively, implement the following Mobile-First Captive Portal Design Checklist:

mobile_first_checklist.png

1. Viewport Configuration

To prevent mobile devices from scaling down the viewport to a desktop width (typically 980px), the HTML <head> must include a responsive viewport meta tag. Without this, text and input fields will appear microscopic on mobile devices:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

2. Inlining CSS and Removing External Dependencies

Never link to external CSS files or CDNs (e.g., Bootstrap, Tailwind, or Google Fonts). All CSS must be embedded within a <style> block in the HTML <head>.

For typography, utilise a system font stack that references pre-installed local operating system fonts. This avoids HTTP requests entirely and ensures the page loads instantly using the device's native, high-quality sans-serif typeface:

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    background-color: #F5F1ED; /* Pearl White Brand Colour */
    color: #011638; /* Dark Blue Brand Colour */
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
}

3. Base64 Asset Encoding

Images, logos, and icons should not be referenced via external HTTP URLs unless the hosting domain is whitelisted in the gateway's walled garden. The most reliable method is to encode small visual assets (such as PNG or SVG logos) directly into the HTML or CSS as Base64 Data URIs:

<!-- Inline Base64 Logo Example -->
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI0MCIgZmlsbD0iIzc0NThGRCIvPjwvc3ZnPg==" alt="Purple Logo" class="brand-logo">

4. Input Field and Tap Target Optimisation

To comply with mobile usability standards (such as Apple's Human Interface Guidelines), all interactive elements must be optimised for touch input:

  • Input Font Size: Input text font sizes must be at least 16px. If the font size is lower (e.g., 14px), iOS Safari and the CNA will automatically zoom in on the input field when focused, distorting the page layout [1].
  • Tap Targets: Buttons, checkboxes, and links must have a minimum touch target area of 44px x 44px to prevent accidental clicks or user frustration.

When capturing guest data (e.g., email, phone number, or social profiles), the HTML structure must support explicit legal consent. Under GDPR, pre-ticked checkboxes or implicit consent statements (e.g., "By logging in, you agree to our terms") are non-compliant [3].

  • Provide an unchecked-by-default checkbox for Terms & Conditions and Privacy Policies.
  • Wrap detailed legal text in a scrollable, constrained-height container (max-height: 120px; overflow-y: auto;) to keep the primary login form above the fold.
<div class="consent-container">
    <input type="checkbox" id="terms_consent" name="terms_consent" required>
    <label for="terms_consent">
        I explicitly agree to the <a href="#" onclick="showTerms()">Terms of Service</a> and consent to the processing of my data in accordance with the <a href="#" onclick="showPrivacy()">Privacy Policy</a>.
    </label>
</div>

Custom Captive Portal HTML/CSS Template

Below is a complete, production-ready, single-file HTML/CSS template that incorporates all mobile-first, CNA-compliant best practices. It features a responsive layout, a system font stack, Base64-ready asset placeholders, touch-friendly inputs, and explicit GDPR-compliant consent structures:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>Guest WiFi Login</title>
    <style>
        /* CSS Reset & Variable Declarations */
        :root {
            --color-primary: #7458FD; /* Purple Brand Colour */
            --color-dark: #011638; /* Dark Blue */
            --color-light: #F5F1ED; /* Pearl White */
            --color-white: #FFFFFF;
            --color-border: #D1D5DB;
            --radius-container: 12px;
            --radius-element: 6px;
        }
        
        * {
            box-sizing: border-box;
            -webkit-tap-highlight-color: transparent;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            background-color: var(--color-light);
            color: var(--color-dark);
            margin: 0;
            padding: 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
        }
        
        /* Responsive Card Layout */
        .portal-card {
            background-color: var(--color-white);
            width: 100%;
            max-width: 420px;
            padding: 32px 24px;
            border-radius: var(--radius-container);
            box-shadow: 0 4px 20px rgba(1, 22, 56, 0.05);
            text-align: center;
        }
        
        .logo-container {
            margin-bottom: 24px;
        }
        
        /* Embedded Base64 Logo Placeholder */
        .logo {
            width: 120px;
            height: auto;
        }
        
        h1 {
            font-size: 24px;
            font-weight: 700;
            margin: 0 0 8px 0;
            color: var(--color-dark);
        }
        
        p {
            font-size: 14px;
            color: #4B5563;
            margin: 0 0 24px 0;
            line-height: 1.5;
        }
        
        /* Form Styles */
        .form-group {
            text-align: left;
            margin-bottom: 16px;
        }
        
        label {
            display: block;
            font-size: 14px;
            font-weight: 600;
            margin-bottom: 6px;
            color: var(--color-dark);
        }
        
        /* Critical: font-size must be at least 16px to prevent iOS auto-zoom */
        input[type="email"],
        input[type="text"] {
            width: 100%;
            height: 48px;
            padding: 12px 16px;
            font-size: 16px;
            border: 1px solid var(--color-border);
            border-radius: var(--radius-element);
            background-color: var(--color-white);
            color: var(--color-dark);
            outline: none;
            transition: border-color 0.2s;
        }
        
        input[type="email"]:focus,
        input[type="text"]:focus {
            border-color: var(--color-primary);
            box-shadow: 0 0 0 3px rgba(116, 88, 253, 0.15);
        }
        
        /* Consent Styles */
        .consent-group {
            display: flex;
            align-items: flex-start;
            text-align: left;
            margin: 20px 0;
        }
        
        /* Touch-friendly target sizing */
        input[type="checkbox"] {
            width: 20px;
            height: 20px;
            margin: 2px 12px 0 0;
            flex-shrink: 0;
            cursor: pointer;
            accent-color: var(--color-primary);
        }
        
        .consent-label {
            font-size: 13px;
            line-height: 1.4;
            color: #4B5563;
            user-select: none;
        }
        
        .consent-label a {
            color: var(--color-primary);
            text-decoration: none;
            font-weight: 600;
        }
        
        .consent-label a:hover {
            text-decoration: underline;
        }
        
        /* Touch-Friendly CTA Button (Minimum 44px height) */
        .btn-submit {
            width: 100%;
            height: 48px;
            background-color: var(--color-primary);
            color: var(--color-white);
            border: none;
            border-radius: var(--radius-element);
            font-size: 16px;
            font-weight: 600;
            cursor: pointer;
            transition: background-color 0.2s;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        .btn-submit:hover {
            background-color: #5B3EE3;
        }
        
        .btn-submit:active {
            background-color: #4A2FD4;
        }
        
        /* Legal Terms Scrollbox */
        .terms-scrollbox {
            display: none; /* Toggled via JS */
            text-align: left;
            font-size: 11px;
            color: #6B7280;
            background-color: var(--color-light);
            padding: 12px;
            border-radius: var(--radius-element);
            max-height: 100px;
            overflow-y: auto;
            margin-bottom: 16px;
            border: 1px solid var(--color-border);
        }
        
        .footer {
            margin-top: 24px;
            font-size: 11px;
            color: #9CA3AF;
        }
    </style>
</head>
<body>

    <div class="portal-card">
        <div class="logo-container">
            <!-- Replace src with your actual Base64-encoded SVG or PNG -->
            <svg class="logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 30">
                <rect width="100" height="30" rx="6" fill="#7458FD"/>
                <text x="50" y="20" font-family="sans-serif" font-size="12" fill="#FFFFFF" font-weight="bold" text-anchor="middle">YOUR BRAND</text>
            </svg>
        </div>
        
        <h1>Welcome to Guest WiFi</h1>
        <p>Please enter your details below to gain secure, high-speed internet access.</p>
        
        <!-- Form must submit natively (full page navigation) to clear Apple CNA -->
        <form action="/login/submit" method="POST" onsubmit="return validateForm()">
            <div class="form-group">
                <label for="guest_name">Full Name</label>
                <input type="text" id="guest_name" name="name" placeholder="John Doe" required autocomplete="name">
            </div>
            
            <div class="form-group">
                <label for="guest_email">Email Address</label>
                <input type="email" id="guest_email" name="email" placeholder="john@example.com" required autocomplete="email">
            </div>
            
            <div class="consent-group">
                <input type="checkbox" id="terms_consent" name="terms_accepted" required>
                <label for="terms_consent" class="consent-label">
                    I accept the <a href="#" onclick="toggleTerms(event)">Terms of Service</a> and consent to data processing in compliance with GDPR regulations.
                </label>
            </div>
            
            <div id="terms_box" class="terms-scrollbox">
                <strong>WiFi Terms of Service:</strong><br>
                1. This service is provided as-is without warranties.<br>
                2. Users must not engage in illegal bandwidth-intensive activities.<br>
                3. Personal data is collected solely for authentication and marketing opt-ins in compliance with our Privacy Policy.
            </div>
            
            <button type="submit" class="btn-submit">Connect to WiFi</button>
        </form>
        
        <div class="footer">
            Powered by Purple | Secure Guest WiFi
        </div>
    </div>

    <script>
        function toggleTerms(e) {
            e.preventDefault();
            var box = document.getElementById('terms_box');
            box.style.display = (box.style.display === 'block') ? 'none' : 'block';
        }
        
        function validateForm() {
            var consent = document.getElementById('terms_consent');
            if (!consent.checked) {
                alert('You must accept the Terms of Service to connect.');
                return false;
            }
            return true;
        }
    </script>
</body>
</html>

Troubleshooting & Risk Mitigation

When deploying custom-coded HTML/CSS captive portals, IT operations teams frequently encounter several severe operational risks:

1. The SSL/TLS Certificate Warning Loop

Because captive portals function by intercepting traffic, they present a fundamental conflict with modern HTTPS web security. When a user attempts to visit an HTTPS site (e.g., https://www.google.com), and the gateway attempts to redirect that traffic to an HTTP captive portal, the browser detects a mismatch in the SSL certificate and displays a critical "Your connection is not private" security warning.

  • Mitigation: Never attempt to intercept HTTPS traffic directly. Rely entirely on the operating system's native CNA helper (which makes an unencrypted HTTP request to trigger the redirect). Ensure your captive portal's domain has a valid, publicly trusted SSL certificate (e.g., Let's Encrypt or DigiCert) and is served over HTTPS only after the initial HTTP redirect has successfully routed the user to your portal domain [2].

2. DNS Resolution Failures (The Walled Garden Trap)

If your custom HTML page references external resources—such as a social login OAuth endpoint (e.g., Facebook, Google) or a payment gateway—the DNS requests for these domains will fail unless they are explicitly whitelisted in the wireless controller's Walled Garden. If a domain is missing from the whitelist, the login flow will stall, presenting a blank screen.

  • Mitigation: Maintain a strict, minimal Walled Garden list. If utilising social logins, whitelist the specific wildcard domains recommended by the identity providers (e.g., *.google.com, *.gstatic.com).

3. Session Timeout and MAC Spoofing Vulnerabilities

Standard captive portals authenticate devices based on their MAC addresses. However, modern mobile operating systems (iOS 14+ and Android 10+) utilise randomised MAC addresses (private WiFi addresses) by default, rotating them periodically. This can lead to guests being repeatedly prompted to re-authenticate, destroying the user experience [1].

  • Mitigation: Implement reasonable session timeouts (e.g., 24 hours) on the RADIUS server to prevent stale sessions, and utilise modern authentication standards like Passpoint (Hotspot 2.0) or WPA3-Enterprise for seamless, secure onboarding that bypasses MAC-based captive portals entirely.

Purple Product Relevance: Build vs. Buy

While coding a single HTML page is straightforward, hosting, securing, and scaling a custom captive portal infrastructure presents massive technical and compliance hurdles. The table below compares the engineering and operational realities of self-hosting a custom portal versus utilising Purple's managed enterprise platform:

Feature / Operational Requirement Self-Hosted Custom Portal Purple Enterprise WiFi Platform
HTML/CSS Customisation Fully manual coding, uploading files to individual APs or local web servers. Pixel-perfect developer editor allowing custom HTML/CSS injects, combined with a drag-and-drop visual builder.
RADIUS Infrastructure Must deploy, configure, and maintain highly available FreeRADIUS or Cloud RADIUS servers [4]. Built-in, globally distributed, cloud-native RADIUS with active-active redundancy and 99.99% uptime SLAs.
Multi-Vendor AP Support Custom integration scripts required for each hardware vendor (Cisco, Aruba, Meraki, Ruckus) [5]. Native, out-of-the-box integration with over 200 hardware models; unified portal deployment across mixed-hardware estates.
Data Privacy & Compliance Venue assumes 100% legal liability for GDPR, CCPA, and PCI DSS compliance, including secure database encryption and data deletion workflows. Fully compliant by design. Built-in consent management, automated data-subject deletion requests, and secure ISO 27001-certified hosting.
Analytics & Marketing Requires building custom data ingestion pipelines and integrating third-party marketing tools. Enterprise-grade analytics dashboard with real-time footfall tracking, return-rate metrics, and automated marketing campaign triggers [6].
Identity Provider Integrations Manual OAuth2 integrations with Google, Facebook, Apple, and local SMS gateways. One-click integrations with major social platforms, SMS gateways, and Azure AD / Okta for corporate guests.

Purple's platform resolves the "Build vs. Buy" dilemma. It provides developers with the complete creative freedom of a custom HTML/CSS workspace while eliminating the complex, high-risk backend infrastructure engineering required to support secure RADIUS authentication at scale.

ROI & Business Impact

Investing in a professionally engineered, responsive custom captive portal delivers quantifiable returns across IT operations, marketing, and legal compliance.

1. Operational Cost Reduction (IT Helpdesk Tickets)

In large-scale deployments, such as a stadium or multi-site retail chain, a broken captive portal is a leading driver of IT helpdesk escalations. When guests encounter a "white screen" or a non-responsive login button, they overwhelm on-site staff or submit support tickets.

$$\text{Annual Support Savings} = (\text{Total Annual Guest Visits} \times \text{Portal Failure Rate} \times \text{Helpdesk Contact Rate}) \times \text{Cost Per Support Ticket}$$

  • Scenario: A convention centre with 1,000,000 annual visitors. A poorly coded portal has a 5% failure rate on older iOS devices, leading to a 10% helpdesk contact rate. At an industry-standard $15 per support ticket, the operational cost is: $$(1,000,000 \times 0.05 \times 0.10) \times $15 = $75,000 \text{ annually in avoidable support overhead}$$
  • Outcome: Transitioning to a CNA-optimised, mobile-first template reduces the portal failure rate to <0.1%, virtually eliminating this operational drain.

2. Marketing Data Capture and Opt-in Optimisation

For retail and hospitality venues, the guest WiFi portal is the primary mechanism for capturing clean, first-party customer data. A poorly designed user interface with microscopic text or a clunky form layout causes high bounce rates—users abandon the login process entirely, resulting in lost marketing opportunities.

  • Case Study (Retail): A national retail chain implemented a mobile-first optimised captive portal utilising Purple's platform. By replacing a multi-step login form with a single-field email input (font-size: 16px) and an optimised 48px tap-target button, they saw a 42% increase in completed registrations and a 28% increase in marketing newsletter opt-ins within the first quarter [6].

Under GDPR and CCPA, non-compliant data collection carries severe financial penalties (up to 4% of global annual turnover under GDPR). Relying on pre-ticked checkboxes or failing to provide a clear, easily accessible Privacy Policy on your splash page exposes the enterprise to immense legal liability.

  • Mitigation ROI: Implementing an explicit, un-ticked consent checkbox and hosting terms within an optimised scrollbox ensures 100% regulatory compliance, mitigating the risk of multi-million dollar regulatory fines and protecting brand reputation.

Summary of Key Takeaways

  • The CNA Sandbox is Restrictive: Apple's iOS Websheet and macOS CNA are highly sandboxed environments that block external assets, cookies, and web fonts. All styling and assets must be self-contained (inline CSS, Base64 images, system fonts) [1].
  • AJAX Breaks the iOS Exit Handshake: To successfully transition the iOS device from "captive" to "connected" (changing the top-right button from "Cancel" to "Done"), you must trigger a full-page HTTP redirect. Asynchronous DOM updates will leave the device in a captive loop.
  • Mobile-First is Mandatory: Over 90% of logins occur on mobile. Design a single-column layout (max-width: 480px), utilise touch-friendly tap targets (minimum 44px x 44px), and enforce a minimum 16px font size on all text inputs to prevent automatic iOS browser zooming.
  • Walled Gardens Control DNS: Any external domain referenced during login (e.g., social login APIs) must be explicitly whitelisted in the wireless controller's walled garden, or the page will fail to load.
  • Purple Eliminates Backend Complexity: Utilising Purple's portal builder gives developers complete HTML/CSS control via a custom editor, while offloading the immense security, scaling, and compliance burdens of RADIUS, multi-vendor AP integrations, and GDPR-compliant database management [3].

References


Listen to the Technical Briefing

Listen to a senior solutions architect discuss the technical constraints and implementation strategies for custom captive portals:

Définitions clés

Captive Portal

Une page web qui s'affiche pour les utilisateurs nouvellement connectés à un réseau Wi-Fi avant qu'un accès plus large aux ressources du réseau ne leur soit accordé, généralement utilisée pour l'authentification, le paiement ou l'affichage des conditions d'utilisation.

Les équipes informatiques déploient des portails captifs au niveau de la passerelle pour contrôler l'accès des invités, capturer les données des utilisateurs et assurer la conformité légale.

Captive Network Assistant (CNA)

Un mini-navigateur hautement restreint et isolé (sandbox) lancé automatiquement par les systèmes d'exploitation (tels qu'Apple iOS et macOS) lors de la détection d'une redirection de réseau captif, conçu uniquement pour faciliter l'authentification sur le portail.

Les webviews CNA imposent des restrictions strictes, notamment le blocage des CDN externes, des cookies persistants et du stockage local, ce qui perturbe fréquemment les conceptions web standard.

Walled Garden

Une liste restreinte d'adresses IP, de sous-réseaux ou de noms de domaine qu'un utilisateur invité non authentifié est autorisé à consulter via la passerelle avant de terminer le processus de connexion au Captive Portal.

Les développeurs doivent s'assurer que toute ressource externe (telle que les API de connexion sociale ou les passerelles de paiement) est inscrite sur liste blanche dans le walled garden afin d'éviter que le flux de connexion ne se bloque.

Encodage Base64

Un schéma de codage binaire-texte qui représente des données binaires (telles que des images) sous forme de chaîne ASCII, permettant d'intégrer des éléments directement dans des documents HTML ou CSS.

L'utilisation de l'encodage Base64 pour les logos et les icônes élimine les requêtes HTTP externes, garantissant que les éléments s'affichent parfaitement dans les environnements CNA hors ligne.

RADIUS (Remote Authentication Dial-In User Service)

Un protocole réseau qui fournit une gestion centralisée de l'authentification, de l'autorisation et de la comptabilisation (AAA) pour les utilisateurs qui se connectent et utilisent un service réseau.

Le serveur du Captive Portal communique avec un serveur RADIUS pour autoriser l'adresse MAC de l'invité au niveau de la passerelle réseau une fois que les critères d'authentification sont remplis.

System Font Stack

Une déclaration CSS font-family qui donne la priorité aux polices préinstallées du système d'exploitation (telles que San Francisco sur iOS, Segoe UI sur Windows et Roboto sur Android) par rapport aux polices web externes.

L'implémentation d'un system font stack garantit un rendu typographique immédiat sans déclencher de requêtes HTTP externes bloquées vers des services comme Google Fonts.

Canary URL

Une URL HTTP dédiée et non cryptée, gérée par les fournisseurs de systèmes d'exploitation (par exemple, captive.apple.com), pour tester si un appareil dispose d'une connectivité Internet illimitée.

Le gestionnaire de réseau en arrière-plan de l'OS vérifie cette URL pour détecter la présence d'un Captive Portal et déclencher la fenêtre contextuelle de la webview CNA.

Passpoint (Hotspot 2.0)

Une norme de l'industrie développée par la Wi-Fi Alliance qui permet aux appareils mobiles de découvrir automatiquement et de s'authentifier de manière sécurisée auprès des points d'accès Wi-Fi, en évitant les connexions manuelles aux portails captifs.

Les entreprises utilisent Passpoint aux côtés de plateformes comme Purple pour faire passer les invités de pages de connexion fastidieuses à des expériences d'itinérance sécurisées et fluides, similaires au réseau cellulaire.

Exemples concrets

Une chaîne d'hôtels de luxe de 250 chambres [Hospitality](/industries/hospitality) souhaite mettre en œuvre une page de connexion WiFi invité personnalisée qui correspond parfaitement à sa charte graphique haut de gamme. Leur agence de création a conçu une splash page utilisant une typographie de marque personnalisée (hébergée sur Adobe Fonts), plusieurs images d'arrière-plan haute résolution (hébergées sur un compartiment public AWS S3) et un assistant JavaScript animé en plusieurs étapes. Lors du déploiement, les invités sur iOS se connectent au SSID, mais le portail s'affiche sous la forme d'un écran blanc vide et les utilisateurs ne peuvent pas s'authentifier.

Pour résoudre l'écran blanc et la charte graphique défectueuse, nous devons restructurer l'architecture frontend du portail afin de respecter les contraintes du sandbox Apple CNA :

  1. Correction de la typographie : Comme Adobe Fonts nécessite une requête HTTP externe qui est bloquée par le CNA, nous remplaçons l'appel de police personnalisée par une pile de polices système natives et haut de gamme (font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;). Cela garantit un rendu instantané sans appels réseau externes.
  2. Optimisation des ressources : Les images d'arrière-plan sur AWS S3 sont bloquées car S3 ne figure pas dans le walled garden de la passerelle. Nous compressons le logo principal de la marque, le convertissons en un SVG léger et l'encodons directement dans le HTML sous forme d'URI de données Base64. Pour l'arrière-plan, nous remplaçons les images lourdes par un dégradé CSS propre et réactif utilisant les couleurs de la marque de l'hôtel, réduisant ainsi considérablement le poids de la page.
  3. Simplification du JavaScript : L'assistant animé en plusieurs étapes repose sur des bibliothèques externes jQuery et GSAP. Nous supprimons ces dépendances externes et refactorisons le formulaire dans une structure HTML sur une seule page et une seule colonne. La validation du formulaire est réécrite en JavaScript natif et léger.
  4. Handshake d'authentification : La soumission du formulaire est modifiée d'une soumission basée sur AJAX à un formulaire HTML natif <form action="/submit" method="POST"> pour déclencher une redirection de page complète, permettant au Websheet iOS d'exécuter sa vérification canary et d'afficher le bouton 'Terminé'.
Commentaire de l'examinateur : Ce scénario représente le conflit classique entre une conception créative haut de gamme et les contraintes de sécurité rigides des webviews captifs. Les agences de création traitent souvent le Captive Portal comme un site web de bureau standard. Cependant, l'appareil étant dans un état pré-authentifié, le réseau bloque tout le trafic externe. En intégrant le CSS, en utilisant des polices système, en encodant les ressources en Base64 et en utilisant des soumissions de formulaires natives, nous préservons l'esthétique haut de gamme de la marque tout en garantissant une fiabilité opérationnelle à 100 % sur les appareils iOS et Android.

Une chaîne nationale de vente au détail [Retail](/industries/retail) comptant 450 magasins souhaite capturer les e-mails des invités via des splash pages WiFi pour alimenter son CRM. Elle exige que les invités s'inscrivent aux newsletters marketing. La conception initiale comporte une case à cocher pré-cochée « J'accepte de recevoir des e-mails marketing ». De plus, le portail est hébergé sur un seul serveur local à leur siège social. Pendant les heures de pointe (le samedi après-midi), les invités de tout le pays subissent des retards importants et beaucoup ne parviennent pas à charger la page de connexion, ce qui entraîne une baisse massive des taux de capture de données.

Nous devons remédier à la fois à la violation de la conformité et au goulot d'étranglement de l'infrastructure :

  1. Correction de la conformité : En vertu du GDPR et de la CCPA, les cases de consentement pré-cochées sont illégales. Nous modifions le HTML pour que la case de consentement marketing soit décochée par défaut (<input type="checkbox" id="marketing_consent">). Nous ajoutons également une case à cocher obligatoire distincte pour les conditions d'utilisation afin de dissocier l'accord juridique de l'inscription marketing.
  2. Évolutivité de l'infrastructure : L'hébergement d'un Captive Portal national sur un seul serveur centralisé crée un point de défaillance unique et un goulot d'étranglement massif en matière de latence. Nous migrons le frontend du portail vers un réseau de diffusion de contenu (CDN) hautement disponible et distribué à l'échelle mondiale avec mise en cache en périphérie (edge-caching).
  3. Intégration RADIUS : Nous configurons les points d'accès des magasins locaux pour qu'ils pointent vers un cluster RADIUS cloud-native avec redondance active-active, garantissant que les demandes d'authentification sont traitées localement en périphérie avec une latence inférieure à 50 ms, même pendant le trafic de pointe du samedi.
  4. Migration vers Purple : Pour éliminer toute cette charge d'ingénierie, le détaillant migre vers Purple. Les outils de consentement GDPR intégrés de Purple gèrent automatiquement les inscriptions conformes, et leur infrastructure cloud distribuée à l'échelle mondiale gère des millions d'authentifications quotidiennes avec un taux de disponibilité de 99,99 %, résolvant ainsi complètement le goulot d'étranglement de l'évolutivité.
Commentaire de l'examinateur : Les cases de consentement pré-cochées représentent un risque de conformité grave qui peut entraîner des amendes réglementaires massives. Dissocier le consentement marketing des conditions d'utilisation est une bonne pratique technique et juridique. Du côté de l'infrastructure, l'hébergement centralisé des portails captifs est un anti-pattern. Une présence nationale de vente au détail nécessite un frontend décentralisé avec mise en cache en périphérie, combiné à un backend RADIUS cloud-native. Migrer vers une plateforme gérée comme Purple élimine cette complexité architecturale, permettant au détaillant de se concentrer sur les campagnes marketing plutôt que sur l'évolutivité de la base de données.

Questions d'entraînement

Q1. Une équipe informatique d'un grand aéroport international [Transport](/industries/transport) déploie un Captive Portal codé sur mesure. Elle constate que si les utilisateurs d'Android se connectent de manière fluide, une partie importante des utilisateurs d'iOS rencontre un problème : ils s'authentifient avec succès mais ne peuvent pas naviguer sur le web. En y regardant de plus près, les appareils iOS indiquent qu'ils sont connectés au SSID, mais le bouton en haut à droite de la fenêtre contextuelle captive affiche toujours « Annuler » au lieu de « Terminé ». Quelle est la cause profonde de ce problème et comment le développeur doit-il le résoudre ?

Conseil : Analysez comment l'assistant CNA d'Apple détecte qu'un réseau est passé de l'état captif à l'état authentifié, et quelle action du navigateur est requise pour déclencher cette vérification.

Voir la réponse type

La cause profonde est que la page de réussite du portail met à jour l'interface utilisateur de manière dynamique via JavaScript (routage AJAX/SPA) plutôt que d'effectuer une navigation HTTP complète. Le mini-navigateur de l'assistant réseau captif (CNA) d'Apple iOS ne réexécute sa vérification de connectivité en arrière-plan (la requête canary vers captive.apple.com) que lorsqu'une redirection d'URL ou une navigation de page complète se produit. Si le développeur soumet le formulaire de connexion via AJAX et affiche simplement un message de « Réussite » dans le DOM, le CNA ne sait pas que le réseau a été déverrouillé. Par conséquent, le bouton en haut à droite reste sur « Annuler ». Si l'utilisateur clique sur « Annuler » pour quitter, le système d'exploitation suppose que la connexion a échoué et se déconnecte du réseau WiFi.

Solution : Le développeur doit modifier le gestionnaire de réussite de l'authentification pour forcer une redirection de page complète. Cela peut être réalisé en soumettant le formulaire de connexion de manière native via une balise HTML standard <form action="/submit" method="POST"> ou en exécutant window.location.href = '/success_landing_page' en JavaScript une fois que l'API renvoie une réponse d'authentification réussie. Cela déclenche le chargement complet de la page requis, forçant l'assistant CNA à réévaluer l'état du réseau, à vérifier que l'URL canary est désormais accessible et à remplacer le bouton en haut à droite par « Terminé ».

Q2. Une équipe d'exploitation de stade [Events] souhaite lancer un réseau WiFi invité qui collecte des inscriptions marketing. Le responsable de la conformité insiste sur le fait que le portail doit être 100 % conforme au GDPR. L'équipe de développement présente une maquette où le formulaire de connexion comporte une case pré-cochée indiquant « J'accepte les conditions d'utilisation et je consens à recevoir des newsletters marketing ». Pourquoi cette conception n'est-elle pas conforme, et comment la structure HTML/CSS et du formulaire doit-elle être remaniée pour satisfaire au GDPR tout en maintenant un taux de conversion élevé ?

Conseil : Prenez en compte les exigences strictes du GDPR concernant le consentement explicite, la dissociation des inscriptions marketing des conditions d'utilisation, et la visibilité physique des textes juridiques sur les écrans mobiles.

Voir la réponse type

La conception proposée enfreint le GDPR sur deux aspects majeurs : premièrement, les cases pré-cochées ne constituent pas un consentement valide, qui doit être donné librement, de manière spécifique, éclairée et univoque. Deuxièmement, le fait de lier le consentement marketing à l'acceptation des conditions d'utilisation n'est pas conforme ; un utilisateur ne peut pas être contraint d'accepter des e-mails marketing comme condition d'utilisation du service WiFi.

Stratégie de refactorisation :

  1. Dissocier le consentement : Séparez la case à cocher en deux cases distinctes. La case A est obligatoire et concerne les conditions d'utilisation et la politique de confidentialité. La case B est facultative et concerne l'inscription à la newsletter marketing.
  2. Définir sur non cochée : Assurez-vous que les deux cases sont décochées par défaut dans le HTML (attribut checked omis).
  3. Visibilité CSS : Étant donné que plus de 90 % des utilisateurs sont sur mobile, placez les cases à cocher directement au-dessus du bouton « Se connecter » afin qu'elles soient visibles au-dessus de la ligne de flottaison sans défilement. Utilisez une pile de polices système et définissez la taille de la police du libellé à 14px avec une hauteur de ligne de 1.4 pour une lisibilité optimale.
  4. Zone de défilement des conditions : Pour éviter que le texte juridique ne repousse les éléments du formulaire hors de l'écran, placez les conditions d'utilisation détaillées dans un conteneur déroulant avec une hauteur fixe (max-height: 100px; overflow-y: auto; background-color: #F5F1ED; border: 1px solid #D1D5DB; border-radius: 6px;) qui peut être ouvert ou fermé via un lien texte. Cela permet de conserver une mise en page épurée et performante tout en garantissant une conformité juridique absolue.

Q3. Une chaîne de magasins [Retail](/industries/retail) déploie une page d'accueil personnalisée dans 100 points de vente. Le concepteur a utilisé Google Fonts (Montserrat) et a intégré un lien vers une feuille de style Bootstrap hébergée sur un CDN dans l'en-tête HTML. Lors des tests sur un réseau d'entreprise, la page s'affiche parfaitement. Cependant, lorsqu'elle est déployée sur un point d'accès de test en magasin avec une configuration de réseau captif, la page s'affiche avec du texte Times New Roman sans style, un alignement déstructuré et des icônes manquantes. Pourquoi cela se produit-il et comment les ressources doivent-elles être remaniées ?

Conseil : Analysez l'état de la connexion réseau avant qu'un utilisateur ne soit authentifié, et déterminez comment le navigateur gère les requêtes HTTP externes vers des domaines situés en dehors du walled garden.

Voir la réponse type

Cet échec se produit parce que l'appareil est dans un état captif non authentifié lorsque la page d'accueil est chargée. Dans cet état, la passerelle sans fil bloque tout le trafic internet sortant, n'autorisant que les requêtes vers les domaines explicitement autorisés dans le Walled Garden de la passerelle. Étant donné que les domaines CDN pour Bootstrap (cdn.jsdelivr.net) et Google Fonts (fonts.googleapis.com) ne sont pas autorisés, les requêtes du navigateur pour récupérer la feuille de style et les fichiers de polices échouent silencieusement. Par conséquent, le navigateur se rabat sur son moteur de rendu par défaut, ce qui produit un HTML sans style (texte Times New Roman) et des mises en page cassées.

Stratégie de refactorisation :

  1. CSS intégré (Inline) : Supprimez le lien externe vers la feuille de style Bootstrap. Copiez les règles CSS grid/flexbox nécessaires directement dans un bloc <style> dans l'en-tête HTML <head>. Cela garantit que toutes les instructions de mise en page sont fournies dans le chargement initial de la page unique.
  2. Implémenter une pile de polices système : Supprimez l'appel Google Fonts @import ou <link>. Remplacez-le par une pile de polices système native dans le CSS (font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;). Cela force l'appareil à utiliser des polices de haute qualité déjà préinstallées sur le système d'exploitation, éliminant ainsi complètement la dépendance au réseau externe.
  3. Encoder les icônes/logos en Base64 : Si la mise en page repose sur des images externes ou des bibliothèques d'icônes (comme FontAwesome), convertissez ces icônes au format SVG et intégrez-les directement dans le HTML ou sous forme d'URI de données Base64 dans le CSS. Cela garantit que la page est 100 % autonome et s'affiche parfaitement, même sans aucune connectivité internet.