← Retour aux TPs

Chapitre 4 — TP Complet

CSS3 & Web Design

Solutions pratiques couvrant les Sélecteurs, le Box Model, Flexbox, Grid, le Responsive Design et les Animations.

Exercice 1 : Sélecteurs et spécificité

1.1 Sélecteurs

Étant donné le HTML suivant, écrivez les sélecteurs CSS demandés :

Code HTML fourni :

<nav class="main-nav">
  <ul>
    <li><a href="/" class="active">Accueil</a></li>
    <li><a href="/about">À propos</a></li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>
<main>
  <article class="post featured">
    <h2>Premier article</h2>
    <p>Contenu...</p>
  </article>
  <article class="post">
    <h2>Deuxième article</h2>
    <p>Contenu...</p>
  </article>
</main>

Solutions :

  • Sélectionnez tous les liens dans la navigation : .main-nav a ou nav.main-nav ul li a
  • Sélectionnez uniquement le lien actif : .main-nav a.active ou a.active
  • Sélectionnez l'article qui a la classe featured : article.post.featured
  • Sélectionnez le premier paragraphe de chaque article : article.post p:first-of-type
  • Sélectionnez les éléments <li> pairs : li:nth-child(even)

1.2 Spécificité

Questions : Classez ces sélecteurs par spécificité croissante : p, .text, #main, p.text, #main .text p. Si deux règles ont la même spécificité, laquelle gagne ? Pourquoi faut-il éviter !important ?

Solutions :

  • Ordre croissant : p (0,0,1) < .text (0,1,0) < p.text (0,1,1) < #main (1,0,0) < #main .text p (1,1,1)
  • Égalité de spécificité : C'est la règle déclarée en dernier dans le fichier CSS qui l'emporte (effet de cascade).
  • Pourquoi éviter !important : Cela casse la cascade naturelle et rend la surcharge impossible sans réutiliser !important, ce qui rend le code incontrôlable.

Exercice 2 : Box Model

2.1 Comprendre le Box Model

Code CSS fourni :

.box {
    width: 300px;
    padding: 20px;
    border: 5px solid #333;
    margin: 15px;
}

Questions : Avec box-sizing: content-box (défaut), quelle est la largeur totale visible ? Avec box-sizing: border-box, quelle est la largeur totale visible ? Écrivez le reset CSS universel pour box-sizing.

Solutions :

  • Largeur totale avec content-box : 350px (300 width + 40 padding + 10 border)
  • Largeur totale avec border-box : 300px (le bord et le padding sont inclus dans la largeur donnée)

Reset CSS Universel (code complet) :

*, *::before, *::after {
    box-sizing: border-box;
}

2.2 Centrer un élément

Centrez horizontalement un élément <div> de 600px de large, puis centrez-le aussi verticalement dans la page.

Solutions :

On peut utiliser position: absolute; (une très belle alternative moderne serait display: grid; place-items: center; sur le parent).

/* La méthode position absolue pour le centrage complet */
.center-div {
    width: 600px;
    padding: 20px;
    background-color: #007bff;
    color: white;

    /* Le centrage vertical/horizontal */
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
Div Centrée

Exercice 3 : Flexbox

3.1 Barre de navigation

Créez une barre de navigation horizontale avec un logo à gauche et des liens à droite :

Code HTML fourni :

<nav class="navbar">
  <div class="logo">MonSite</div>
  <ul class="nav-links">
    <li><a href="#">Accueil</a></li>
    <li><a href="#">Services</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>

Solutions :

.navbar {
    display: flex;
    justify-content: space-between; /* Espace équitable entre la gauche et la droite */
    align-items: center; /* Aligné verticalement au centre */
    background-color: #333;
    padding: 1rem 2rem;
    color: white;
}

.nav-links { 
    display: flex; 
    gap: 20px; /* Écartement entre les liens */
    list-style: none; /* Enlève les puces de 
  • */ margin: 0; padding: 0; } .nav-links li a { color: white; text-decoration: none; }

  • 3.2 Cartes de même hauteur

    Créez 3 cartes côte à côte avec un footer qui reste toujours en bas :

    Code HTML fourni :

    <div class="cards">
      <div class="card">
        <h3>Carte 1</h3>
        <p>Contenu court.</p>
        <a href="#" class="card-link">En savoir plus</a>
      </div>
      <!-- autres cartes... -->
    </div>

    Solutions :

    .cards { 
        display: flex; 
        gap: 20px; 
    }
    
    .card {
        display: flex;
        flex-direction: column; /* Agence les enfants de haut en bas */
        padding: 20px;
        border: 1px solid #ddd;
        border-radius: 8px;
        flex: 1; /* Permet aux cartes de partager l'espace horizontal équitablement */
    }
    
    .card-link { 
        margin-top: auto; /* Aligne le bouton tout en bas même s'il manque du texte */
        display: inline-block;
        padding: 10px 15px;
        background-color: #007bff;
        color: white;
        text-decoration: none;
        text-align: center;
        border-radius: 4px;
    }

    Carte 1

    Contenu court.

    En savoir plus

    Carte 2

    Contenu beaucoup plus long pour tester l'alignement vertical des boutons. Flexbox garantit que le bouton du bas reste poussé vers le bas grâce à margin-top: auto en étant en flex-direction: column.

    En savoir plus

    Carte 3

    Contenu moyen.

    En savoir plus

    Exercice 4 : CSS Grid

    4.1 Grille de cartes responsive

    Créez une grille de cartes qui s'adapte automatiquement au nombre de colonnes :

    Code HTML fourni :

    <div class="grid-cards">
      <div class="card">Carte 1</div>
      ...
      <div class="card">Carte 6</div>
    </div>

    Solutions :

    .grid-cards {
        display: grid;
        /* auto-fit répartit les colonnes, minmax garantit une largeur minimale de 250px */
        grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
        gap: 20px;
    }
    
    .card {
        padding: 20px;
        background-color: #28a745;
        color: white;
        border-radius: 6px;
        text-align: center;
    }
    Carte 1
    Carte 2
    Carte 3
    Carte 4
    Carte 5
    Carte 6

    4.2 Layout complet avec Grid Areas

    Créez une mise en page complète : header, sidebar, main, footer.

    Code HTML fourni :

    <div class="page-layout">
      <header class="header">Header</header>
      <nav class="sidebar">Sidebar</nav>
      <main class="main">Contenu principal</main>
      <footer class="footer">Footer</footer>
    </div>

    Solutions :

    .page-layout {
        display: grid;
        /* On nomme nos emplacements de layout */
        grid-template-areas:
            "header header"
            "sidebar main"
            "footer footer";
        grid-template-columns: 250px 1fr;
        grid-template-rows: auto 1fr auto;
        min-height: 100vh;
        gap: 10px;
    }
    
    /* Attachement aux zones */
    .header  { grid-area: header; background: #333; color: white; padding: 20px; }
    .sidebar { grid-area: sidebar; background: #f4f4f4; padding: 20px; }
    .main    { grid-area: main; padding: 20px; }
    .footer  { grid-area: footer; background: #333; color: white; padding: 20px; text-align: center; }
    Header
    Contenu principal
    Footer

    Exercice 5 : Responsive Design

    5.1 Mobile First

    Transformez cette page pour qu'elle soit responsive (mobile first). Ajoutez les media queries pour tablette et desktop :

    Code CSS fourni :

    /* Base mobile */
    .container { width: 100%; padding: 15px; }
    .nav-menu { display: flex; flex-direction: column; gap: 5px; }
    .content { display: block; }
    .sidebar { display: none; }

    Solutions :

    /* Base mobile */
    .container { 
        width: 100%; 
        padding: 15px; 
    }
    .nav-menu { 
        display: flex; 
        flex-direction: column; 
        gap: 5px; 
    }
    .content { 
        display: block; 
    }
    .sidebar { 
        display: none; /* Caché sur mobile */
    }
    
    /* Tablette */
    @media (min-width: 768px) {
        .nav-menu { 
            flex-direction: row; 
            justify-content: space-around;
        }
    }
    
    /* Desktop */
    @media (min-width: 1024px) {
        .container {
            display: grid;
            grid-template-columns: 250px 1fr;
            gap: 30px;
        }
        .sidebar { 
            display: block; /* On affiche la sidebar sur grand écran */
        }
    }

    Exercice 6 : Variables CSS et thèmes

    6.1 Système de couleurs

    Créez un système de variables CSS pour un thème clair et sombre :

    Solutions :

    /* Thème Clair - Par défaut */
    :root {
        --bg-color: #ffffff;
        --text-color: #333333;
        --primary-color: #007bff;
    }
    
    /* Thème Sombre - Appliqué quand dataset theme="dark" */
    [data-theme="dark"] {
        --bg-color: #1a1a1a;
        --text-color: #f5f5f5;
        --primary-color: #4da3ff;
    }
    
    /* Autre méthode: Media query système native */
    @media (prefers-color-scheme: dark) {
        :root {
            --bg-color: #1a1a1a;
            --text-color: #f5f5f5;
        }
    }
    
    /* Application au Body et aux éléments globaux */
    body {
        background-color: var(--bg-color);
        color: var(--text-color);
        /* Transition douce au changement de couleur */
        transition: background-color 0.3s ease, color 0.3s ease;
    }
    
    button {
        background-color: var(--primary-color);
        color: white;
        border: none;
        padding: 10px 20px;
    }

    Thème Clair

    Utilise --bg-color: #f8f9fa;

    Thème Sombre

    Utilise --bg-color: #212529;

    Exercice 7 : Transitions et animations

    7.1 Bouton animé

    Créez un bouton avec des transitions au survol :

    Solutions :

    .btn { 
        padding: 10px 20px;
        background-color: #007bff;
        color: white;
        border: none;
        border-radius: 5px;
        cursor: pointer;
    
        /* La propriété transition gère tous les effets d'animation (fond et taille) */
        transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.2s ease; 
    }
    
    /* Effets animés lors du survol du bouton */
    .btn:hover {
        background-color: #0056b3;
        transform: translateY(-3px); /* Fait monter le bouton de 3px */
        box-shadow: 0 4px 10px rgba(0,0,0,0.2); /* Ajoute de l'ombre de profondeur */
    }

    7.2 Animation de chargement

    Créez un spinner de chargement avec @keyframes :

    Solutions :

    .spinner {
        width: 50px; 
        height: 50px;
        border: 6px solid #e9ecef; /* Couleur de l'anneau de base */
        border-top: 6px solid #17a2b8; /* Couleur de la barre de temps qui tourne */
        border-radius: 50%; /* Arrondi parfait = cercle */
    
        /* Animation: "spin" tourne pendant 1 seconde de façon linéaire à l'infini */
        animation: spin 1s linear infinite;
    }
    
    /* L'animation fait tourner l'objet de 0 à 360 degrés */
    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }

    Exercice 8 : Quiz de révision

    1. Quel sélecteur a la spécificité la plus haute ?

    • [ ] a) .header .nav a
    • [x] b) #header a (ID a la plus grosse valeur : 100)
    • [ ] c) header nav a
    • [ ] d) a.active

    2. Avec box-sizing: border-box, un élément avec width: 200px et padding: 20px a une largeur totale de :

    • [ ] a) 240px
    • [x] b) 200px (Le padding est inclus à l'intérieur de la largeur configurée)
    • [ ] c) 220px
    • [ ] d) 160px

    3. Pour centrer un élément verticalement et horizontalement avec Flexbox :

    • [ ] a) justify-content: center
    • [ ] b) align-items: center
    • [x] c) justify-content: center ET align-items: center
    • [ ] d) text-align: center

    4. La valeur 1fr en CSS Grid signifie :

    • [ ] a) 1 pixel
    • [x] b) 1 fraction de l'espace disponible
    • [ ] c) 1 pourcentage
    • [ ] d) 1 rem

    5. L'approche "Mobile First" utilise :

    • [ ] a) max-width dans les media queries
    • [x] b) min-width dans les media queries (Le code par défaut est pour mobile, min-width surpasse pour grands écrans)
    • [ ] c) device-width
    • [ ] d) orientation