Développement Web

Tutoriel : Créer une page de tarification (pricing) responsive

13 min de lecture

Prérequis

  • Niveau : bases HTML/CSS/JS, notion de Grid + Flexbox.
  • Outils : VS Code + Live Server, navigateur moderne.
  • Temps estimé : 1 h 30.

Pourquoi soigner sa page de pricing ?

C’est l’une des 3 pages les plus consultées sur un site SaaS ou de services. Une page mal conçue (trop d’options, prix cachés, mauvais CTA) fait fuir les prospects qualifiés. Une bonne page guide vers le plan « le plus populaire » et augmente la valeur moyenne des contrats.

La page de pricing : anatomie d’un composant essentiel

La page de tarification est l’une des pages les plus consultées sur un site SaaS ou de services. Elle doit être claire, responsive et guider l’utilisateur vers le plan recommandé. Dans ce tutoriel, vous construisez une page de pricing complète avec HTML et CSS, incluant un switch mensuel/annuel, un plan mis en avant, et un design qui fonctionne sur mobile et desktop.

Le HTML structuré

<section class="pricing">
  <h2 class="pricing-title">Choisissez votre plan</h2>
  <p class="pricing-subtitle">Commencez gratuitement, évoluez quand vous êtes prêt</p>
  
  <!-- Switch mensuel/annuel -->
  <div class="billing-toggle">
    <span class="toggle-label">Mensuel</span>
    <label class="toggle-switch">
      <input type="checkbox" id="billingToggle">
      <span class="toggle-slider"></span>
    </label>
    <span class="toggle-label">Annuel <span class="badge">-20%</span></span>
  </div>

  <div class="pricing-cards">
    <!-- Plan Starter -->
    <div class="pricing-card">
      <h3 class="card-plan">Starter</h3>
      <div class="card-price">
        <span class="price-amount" data-monthly="0" data-annual="0">0</span>
        <span class="price-currency">FCFA</span>
        <span class="price-period">/mois</span>
      </div>
      <p class="card-description">Pour découvrir et tester</p>
      <ul class="card-features">
        <li class="feature-included">1 site web</li>
        <li class="feature-included">5 Go de stockage</li>
        <li class="feature-included">Support par email</li>
        <li class="feature-excluded">Domaine personnalisé</li>
        <li class="feature-excluded">Analytics avancés</li>
      </ul>
      <a href="#" class="card-button">Commencer gratuitement</a>
    </div>

    <!-- Plan Pro (recommandé) -->
    <div class="pricing-card featured">
      <span class="card-badge">Le plus populaire</span>
      <h3 class="card-plan">Pro</h3>
      <div class="card-price">
        <span class="price-amount" data-monthly="15000" data-annual="12000">15 000</span>
        <span class="price-currency">FCFA</span>
        <span class="price-period">/mois</span>
      </div>
      <p class="card-description">Pour les professionnels et freelances</p>
      <ul class="card-features">
        <li class="feature-included">10 sites web</li>
        <li class="feature-included">50 Go de stockage</li>
        <li class="feature-included">Support prioritaire</li>
        <li class="feature-included">Domaine personnalisé</li>
        <li class="feature-included">Analytics avancés</li>
      </ul>
      <a href="#" class="card-button primary">Choisir Pro</a>
    </div>

    <!-- Plan Business -->
    <div class="pricing-card">
      <h3 class="card-plan">Business</h3>
      <div class="card-price">
        <span class="price-amount" data-monthly="45000" data-annual="36000">45 000</span>
        <span class="price-currency">FCFA</span>
        <span class="price-period">/mois</span>
      </div>
      <p class="card-description">Pour les équipes et entreprises</p>
      <ul class="card-features">
        <li class="feature-included">Sites illimités</li>
        <li class="feature-included">Stockage illimité</li>
        <li class="feature-included">Support 24/7 par téléphone</li>
        <li class="feature-included">Domaine personnalisé</li>
        <li class="feature-included">API et intégrations</li>
      </ul>
      <a href="#" class="card-button">Contacter l'équipe</a>
    </div>
  </div>
</section>

Le CSS complet

/* Layout général */
.pricing {
  max-width: 1100px;
  margin: 0 auto;
  padding: 60px 20px;
  text-align: center;
}

.pricing-title { font-size: 2.5rem; margin-bottom: 8px; }
.pricing-subtitle { color: #666; margin-bottom: 30px; }

/* Toggle mensuel/annuel */
.billing-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-bottom: 40px;
}

.toggle-switch {
  position: relative;
  width: 52px;
  height: 28px;
}

.toggle-switch input { display: none; }

.toggle-slider {
  position: absolute;
  inset: 0;
  background: #ccc;
  border-radius: 28px;
  cursor: pointer;
  transition: background 0.3s;
}

.toggle-slider::before {
  content: '';
  position: absolute;
  width: 22px;
  height: 22px;
  background: white;
  border-radius: 50%;
  top: 3px;
  left: 3px;
  transition: transform 0.3s;
}

.toggle-switch input:checked + .toggle-slider {
  background: #4a90d9;
}

.toggle-switch input:checked + .toggle-slider::before {
  transform: translateX(24px);
}

.badge {
  background: #e8f5e9;
  color: #2e7d32;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 0.8rem;
  font-weight: 600;
}

/* Cartes de prix */
.pricing-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  align-items: start;
}

.pricing-card {
  background: white;
  border: 2px solid #e8e8e8;
  border-radius: 16px;
  padding: 40px 30px;
  position: relative;
  transition: transform 0.2s, box-shadow 0.2s;
}

.pricing-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 40px rgba(0,0,0,0.1);
}

.pricing-card.featured {
  border-color: #4a90d9;
  transform: scale(1.05);
  box-shadow: 0 8px 30px rgba(74, 144, 217, 0.2);
}

.card-badge {
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%);
  background: #4a90d9;
  color: white;
  padding: 4px 16px;
  border-radius: 20px;
  font-size: 0.85rem;
  font-weight: 600;
}

.price-amount { font-size: 3rem; font-weight: 800; }
.price-currency { font-size: 1.2rem; }
.price-period { color: #999; }

.card-features {
  list-style: none;
  padding: 0;
  text-align: left;
  margin: 24px 0;
}

.card-features li {
  padding: 8px 0;
  border-bottom: 1px solid #f5f5f5;
}

.feature-included::before { content: '✓ '; color: #4caf50; font-weight: bold; }
.feature-excluded { color: #ccc; }
.feature-excluded::before { content: '✕ '; }

.card-button {
  display: block;
  padding: 14px;
  border: 2px solid #4a90d9;
  color: #4a90d9;
  border-radius: 8px;
  text-decoration: none;
  font-weight: 600;
  transition: all 0.2s;
}

.card-button:hover {
  background: #4a90d9;
  color: white;
}

.card-button.primary {
  background: #4a90d9;
  color: white;
}

.card-button.primary:hover {
  background: #3a7bc8;
}

/* Responsive */
@media (max-width: 768px) {
  .pricing-cards {
    grid-template-columns: 1fr;
    max-width: 400px;
    margin: 0 auto;
  }
  .pricing-card.featured {
    transform: none;
    order: -1; /* Le plan recommandé en premier sur mobile */
  }
}

Le JavaScript : switch des prix

const toggle = document.getElementById('billingToggle');
const prices = document.querySelectorAll('.price-amount');

toggle.addEventListener('change', () => {
  const isAnnual = toggle.checked;
  
  prices.forEach(price => {
    const amount = isAnnual 
      ? parseInt(price.dataset.annual)
      : parseInt(price.dataset.monthly);
    
    // Animation de transition
    price.style.opacity = '0';
    setTimeout(() => {
      price.textContent = amount.toLocaleString('fr-FR');
      price.style.opacity = '1';
    }, 200);
  });
});

Bonnes pratiques UX pour une page pricing

  • 3 plans maximum — au-delà, l’utilisateur est paralysé par le choix
  • Mettre en avant le plan recommandé — bordure colorée, badge, taille plus grande
  • Nommer les plans simplement — Starter, Pro, Business (pas Plan A, Plan B)
  • Montrer ce qui est inclus ET exclu — les ✕ aident à comparer
  • Prix en monnaie locale — FCFA au Sénégal, pas USD
  • CTA clair — « Commencer gratuitement » > « S’inscrire »

Erreurs fréquentes

Trop de plans (5 ou plus)

Cause : on veut couvrir tous les profils.
Solution : 3 plans maximum. Au-delà, le visiteur est paralysé par le choix (paradoxe de Hick).

Plans tarifés en USD pour un public africain

Cause : import de templates anglo-saxons.
Solution : affichez le prix dans la monnaie locale (FCFA, MAD, NGN…). Évitez les conversions à la volée qui dégradent la confiance.

CTA générique (« Commencer »)

Cause : texte de bouton vide.
Solution : CTA spécifique au plan : « Commencer gratuitement », « Choisir Pro », « Contacter l’équipe ».

Switch mensuel/annuel sans visualisation de l’économie

Cause : on bascule juste les chiffres.
Solution : ajoutez un badge « -20 % » à côté de « Annuel » (déjà fait ici), et affichez l’économie absolue (« vous économisez 36 000 FCFA/an »).

Exercice

  1. Reproduisez cette page de pricing avec vos propres services
  2. Ajoutez une FAQ sous les cartes avec des accordéons
  3. Ajoutez une animation d’entrée avec Intersection Observer quand l’utilisateur scrolle jusqu’aux cartes
  4. Rendez le toggle mensuel/annuel accessible au clavier

Pour approfondir

Étape 1 — Cadrer la stratégie tarifaire avant d’écrire la moindre ligne

Avant de toucher au code, définissez votre offre. Une page de pricing efficace présente 3 plans maximum : trop d’options paralysent la décision (paradoxe du choix démontré par Sheena Iyengar). Pour le marché ouest-africain, nommez les plans simplement (« Starter », « Pro », « Business ») et affichez les prix en FCFA en premier, avec équivalent EUR optionnel pour la diaspora.

Différenciez les plans par 5 à 7 features clés visibles d’un coup d’œil. Mettez en évidence le plan recommandé (souvent celui du milieu) avec un badge « Le plus populaire » et un encadré coloré. Documentez la stratégie dans un mini-brief avant de coder : prix, features, plan mis en avant, CTA cible. Ce cadrage évite les itérations sans fin pendant le développement.

Étape 2 — Préparer la structure HTML sémantique

Ouvrez votre éditeur (VS Code recommandé) et créez index.html. Utilisez les balises sémantiques HTML5 : section, article, header. Un seul h1 par page (le titre principal de la section pricing), des h2 pour chaque plan, des ul pour les listes de features.

<section class="pricing" aria-label="Nos tarifs">
  <h1>Nos tarifs</h1>
  <div class="grid">
    <article class="card">
      <h2>Starter</h2>
      <p class="price">25 000 <span>FCFA/mois</span></p>
      <ul><li>Feature 1</li></ul>
      <a href="#" class="btn">Choisir</a>
    </article>
  </div>
</section>

Cette structure garantit l’accessibilité (lecteurs d’écran, navigation clavier) et le SEO. Les attributs aria-label clarifient le contexte pour les technologies d’assistance. Output : un squelette HTML lisible sans CSS, déjà fonctionnel pour les utilisateurs malvoyants.

Étape 3 — Concevoir la grille CSS responsive avec CSS Grid

CSS Grid est l’outil moderne pour les pricing tables. Il permet une mise en page fluide sans media queries multiples. Créez style.css et appliquez :

.grid {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  max-width: 1100px;
  margin: 0 auto;
  padding: 2rem 1rem;
}
.card {
  background: #fff;
  border-radius: 12px;
  padding: 2rem;
  box-shadow: 0 4px 20px rgba(0,0,0,.08);
}

La règle auto-fit + minmax adapte automatiquement le nombre de colonnes : 1 colonne sous 320px, 2 colonnes entre 600 et 900px, 3 colonnes au-delà. Aucune media query nécessaire. L’output : ouvrez la page dans Chrome, redimensionnez la fenêtre — la grille s’adapte fluidement à toutes les tailles d’écran.

Étape 4 — Mettre en valeur le plan recommandé

Le plan recommandé doit attirer l’œil sans agresser. Ajoutez une classe CSS featured et stylez-la pour qu’elle se démarque : bordure colorée, légèrement plus haute, badge en haut.

.card.featured {
  border: 2px solid #f97316;
  transform: translateY(-12px);
  position: relative;
}
.card.featured::before {
  content: "Le plus populaire";
  position: absolute;
  top: -14px; left: 50%;
  transform: translateX(-50%);
  background: #f97316; color: #fff;
  padding: .25rem 1rem;
  border-radius: 999px;
  font-size: .85rem;
}

Sur mobile, désactivez le translateY pour éviter que la carte mise en avant ne casse l’alignement vertical. Ajoutez @media (max-width: 600px) { .card.featured { transform: none; } }. L’output : le plan recommandé saute aux yeux sur desktop, reste visible et lisible sur smartphone d’entrée de gamme courant à Dakar et Abidjan.

Étape 5 — Afficher les prix avec hiérarchie typographique

Le prix est l’information centrale. Donnez-lui la place qu’il mérite avec une typographie hiérarchisée : montant en gros (3 à 4 rem), période en petit (1 rem). Sur le marché ouest-africain, affichez systématiquement « FCFA » plutôt que le sigle CFA pour éviter toute ambiguïté.

.price {
  font-size: 3rem;
  font-weight: 700;
  line-height: 1;
  margin: 1rem 0;
}
.price span {
  font-size: 1rem;
  font-weight: 400;
  color: #6b7280;
}

Si vous ciblez aussi la diaspora, ajoutez un toggle EUR/FCFA en JavaScript qui convertit avec le taux fixe (1 EUR = 655,957 FCFA). Stockez le choix dans localStorage pour persistance. L’output : un visiteur dakarois voit immédiatement « 25 000 FCFA », un visiteur parisien peut basculer en « 38 EUR » d’un clic.

Étape 6 — Optimiser les boutons CTA pour le clic

Le bouton CTA est l’élément de conversion. Taille minimale 44×44px (recommandation Apple HIG et Google Material), couleur contrastée (orange vif #f97316 ou vert #16a34a), texte explicite (« Choisir Pro », pas « En savoir plus »).

.btn {
  display: inline-block;
  padding: .9rem 2rem;
  background: #f97316;
  color: #fff;
  text-decoration: none;
  border-radius: 8px;
  font-weight: 600;
  transition: transform .15s, background .15s;
}
.btn:hover { background: #ea580c; transform: translateY(-2px); }
.btn:focus-visible { outline: 3px solid #fb923c; outline-offset: 2px; }

L’état :focus-visible est crucial pour l’accessibilité clavier. Sans lui, les utilisateurs qui naviguent au Tab ne savent pas où ils sont. L’output : un bouton qui invite au clic visuellement, accessible au clavier et au lecteur d’écran, conforme WCAG 2.1 niveau AA.

Étape 7 — Ajouter les features avec icônes check accessibles

Les listes de features doivent être scannables en moins de 3 secondes. Utilisez une icône check (SVG inline pour la performance) avant chaque ligne. Évitez les emojis (rendu inconsistant entre OS).

.features li {
  display: flex;
  align-items: flex-start;
  gap: .5rem;
  padding: .4rem 0;
  list-style: none;
}
.features svg { flex: 0 0 1.2rem; color: #16a34a; margin-top: .2rem; }

Pour différencier les features incluses des features absentes, utilisez deux icônes (check vert et croix grise) plutôt que de masquer les lignes. La transparence rassure le visiteur. L’output : une liste claire, lisible, qui répond instantanément à la question « qu’est-ce que j’ai dans ce plan ».

Étape 8 — Tester l’accessibilité au clavier et au lecteur d’écran

Avant de publier, testez la page sans souris. Naviguez entièrement au Tab : chaque carte doit être atteignable, chaque CTA doit afficher un focus visible, l’ordre de tabulation doit suivre l’ordre visuel (pas de saut bizarre). Testez ensuite avec un lecteur d’écran : NVDA gratuit sous Windows, VoiceOver natif macOS et iOS, TalkBack natif Android.

Le lecteur d’écran doit annoncer : « Région nos tarifs, titre niveau 1 nos tarifs, article, titre niveau 2 Starter, prix 25 000 FCFA par mois, liste de 5 éléments… ». Si l’annonce est confuse, retravaillez la sémantique HTML. L’output : une page utilisable par les visiteurs malvoyants, segment sous-estimé qui représente plusieurs millions d’utilisateurs en Afrique de l’Ouest.

Étape 9 — Mesurer la performance avec Lighthouse mobile

Ouvrez Chrome DevTools (F12) > onglet Lighthouse > catégorie Performance + Accessibility + Best Practices + SEO, mode Mobile, throttling Slow 4G. Lancez l’audit. Cible : tous les scores au-dessus de 90.

Si la performance est inférieure, vérifiez : poids total de la page (objectif <200 KB), polices Google chargées en preload, CSS minifié, pas de JS bloquant le rendu. Une page de pricing pure HTML/CSS sans framework devrait charger en moins d'une seconde sur 4G dakaroise. L'output : un rapport Lighthouse avec 4 cercles verts, base solide pour le référencement et la conversion.

Étape 10 — Intégrer dans WordPress, Webflow ou framework moderne

Si votre site tourne sur WordPress, copiez le HTML dans un bloc Code personnalisé Gutenberg ou dans une template Page Builder (Elementor accepte un widget HTML). Le CSS va dans Apparence > Personnaliser > CSS additionnel ou dans un fichier enfant style.css.

Sur Webflow, recréez la structure avec les éléments natifs en réutilisant les classes CSS Grid. Sur Next.js, encapsulez le tout dans un composant Pricing.tsx avec props pour les plans. Quel que soit le framework, conservez la sémantique HTML et l’accessibilité. Reliez la page de pricing à votre guide principal et à votre page services pour un tunnel de conversion cohérent.

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité