body {
font-family: ‘Segoe UI’, Tahoma, Geneva, Verdana, sans-serif;
max-width: 100%;
margin: 0 auto;
padding: 20px;
background-color: #f9f9f9;
}
h1, h2, h3 {
color: #2c3e50;
}
.container {
background-color: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
max-width: 100%;
margin: 0 auto;
}
.subscription-form {
background-color: #e8f4f8;
padding: 20px;
border-radius: 8px;
margin-bottom: 30px;
}
.exercise-container {
display: none;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input, select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
button {
background-color: #3498db;
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}
button:hover {
background-color: #2980b9;
}
.exercise-text {
line-height: 2;
font-size: 18px;
}
.pluriel-input {
width: 150px;
padding: 5px;
border: 1px solid #ddd;
border-radius: 4px;
margin: 0 5px;
font-size: 16px;
}
.pluriel-input.correct {
background-color: #d4edda;
border-color: #c3e6cb;
}
.pluriel-input.incorrect {
background-color: #f8d7da;
border-color: #f5c6cb;
}
.result {
margin-top: 30px;
padding: 20px;
background-color: #eafaf1;
border-radius: 8px;
display: none;
}
.certificate {
text-align: center;
margin-top: 30px;
padding: 20px;
border: 2px solid #2c3e50;
border-radius: 8px;
display: none;
}
.difficulty-selector {
margin-bottom: 20px;
}
.error {
color: red;
font-size: 14px;
}
#certificatePreview {
position: relative;
width: 100%;
height: 100%;
background-color: #fff;
border: 10px solid transparent;
border-image: linear-gradient(45deg, #3498db, #2980b9, #1abc9c, #16a085, #27ae60) 1;
box-sizing: border-box;
overflow: hidden;
margin-bottom: 20px;
}
.certificate-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.07;
z-index: 0;
background-position: center;
background-repeat: no-repeat;
background-size: 70%;
}
.certificate-content {
position: relative;
z-index: 1;
padding: 20px;
width: 100%;
height: 100%;
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.certificate-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.certificate-title {
flex-grow: 1;
text-align: center;
}
.certificate-logo {
width: 120px;
height: 60px;
background-color: #3498db;
border-radius: 5px;
}
.certificate-footer {
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.certificate-qr {
width: 120px;
height: 120px;
display: flex;
justify-content: center;
align-items: center;
background-color: #f9f9f9;
border: 1px solid #ddd;
}
.certificate-qr img {
max-width: 100%;
max-height: 100%;
}
.certificate-signature {
flex-grow: 1;
text-align: center;
}
.triangle-pattern {
position: absolute;
width: 150px;
height: 120px;
}
.triangle-pattern.top-right {
top: 0;
right: 0;
}
.triangle-pattern.bottom-left {
bottom: 0;
left: 0;
}
.info-tooltip {
display: inline-block;
position: relative;
margin-left: 5px;
cursor: help;
}
.info-tooltip:after {
content: “?”;
display: inline-block;
width: 18px;
height: 18px;
line-height: 18px;
text-align: center;
border-radius: 50%;
background-color: #3498db;
color: white;
font-weight: bold;
font-size: 14px;
}
.info-tooltip .tooltip-text {
visibility: hidden;
width: 250px;
background-color: #2c3e50;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -125px;
opacity: 0;
transition: opacity 0.3s;
}
.info-tooltip:hover .tooltip-text {
visibility: visible;
opacity: 1;
}
.loading {
display: none;
margin-top: 15px;
font-style: italic;
color: #666;
}
.exercise-level {
margin-bottom: 20px;
}
.rule-section {
background-color: #f3f8ff;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border-left: 5px solid #3498db;
}
Exercice de Grammaire: La Formation du Pluriel des Noms Composés en Français
Inscrivez-vous pour commencer l’exercice
Veuillez vous abonner et remplir vos informations pour accéder à l’exercice.
Écrivez le pluriel des noms composés
Choisissez le niveau de difficulté:
Facile
Moyen
Difficile
Règles pour former le pluriel des noms composés
En français, les règles du pluriel des noms composés dépendent de la nature des mots qui les forment et de leur relation grammaticale:
- Nom + nom: Les deux mots prennent la marque du pluriel (ex: un chou-fleur → des choux-fleurs)
- Nom + préposition + nom: Seul le premier nom prend généralement la marque du pluriel (ex: un arc-en-ciel → des arcs-en-ciel)
- Verbe + nom: Le nom prend généralement la marque du pluriel (ex: un porte-monnaie → des porte-monnaies)
- Préposition/adverbe + nom: Seul le nom prend la marque du pluriel (ex: une avant-garde → des avant-gardes)
- Mots invariables: Les noms composés avec des mots invariables (verbes, prépositions, adverbes) ne changent pas (ex: des on-dit)
Attention: Il existe de nombreuses exceptions et particularités!
Pour chaque nom composé au singulier, écrivez sa forme au pluriel.
Du Singulier au Pluriel (Niveau Facile)
1. un chef-lieu →
2. un porte-monnaie →
3. une pomme de terre →
4. un tire-bouchon →
5. un coffre-fort →
6. un chou-fleur →
7. une arrière-boutique →
8. un timbre-poste →
9. un arc-en-ciel →
10. un grand-père →
11. une belle-mère →
12. un après-midi →
13. un portefeuille →
14. une machine à laver →
15. un garde-robe →
16. un chemin de fer →
17. un porte-parole →
18. un micro-onde →
19. un nouveau-né →
20. un chef-d’œuvre →
Du Singulier au Pluriel (Niveau Moyen)
1. un abat-jour →
2. un wagon-lit →
3. une demi-heure →
4. un faire-part →
5. un rez-de-chaussée →
6. une libre-pensée →
7. un compte rendu →
8. un vice-président →
9. un haut-parleur →
10. une arrière-pensée →
11. un passe-temps →
12. un beau-frère →
13. un pot-au-feu →
14. un tête-à-tête →
15. un sous-titre →
16. une sage-femme →
17. un rond-point →
18. un porte-clés →
19. un garde-côte →
20. un aide-mémoire →
Du Singulier au Pluriel (Niveau Difficile)
1. un trompe-l’œil →
2. une mère grand →
3. un va-et-vient →
4. un pied-à-terre →
5. un couvre-lit →
6. un hors-la-loi →
7. un sans-abri →
8. un laissez-passer →
9. un on-dit →
10. une bonne d’enfant →
11. un état-major →
12. un ayant droit →
13. une grand-croix →
14. un prêt-à-porter →
15. un gagne-pain →
16. un corps-mort →
17. un blanc-seing →
18. un terre-plein →
19. un cache-nez →
20. une arrière-saison →
Résultats
Certificat de réussite
Certificat d’Excellence
Maîtrise du Pluriel des Noms Composés en Français
Ce certificat est décerné à
pour avoir complété avec succès l’exercice sur
la formation du pluriel des noms composés en français au niveau
avec un score de
Date:
document.addEventListener(‘DOMContentLoaded’, function() {
// S’assurer que jsPDF est disponible
if (typeof window.jspdf === ‘undefined’) {
window.jspdf = window.jsPDF;
}
// Références aux éléments DOM
const subscriptionForm = document.getElementById(‘subscriptionForm’);
const exerciseContainer = document.getElementById(‘exerciseContainer’);
const startButton = document.getElementById(‘startButton’);
const verifyButton = document.getElementById(‘verifyButton’);
const difficultySelect = document.getElementById(‘difficultySelect’);
const changeDifficultyButton = document.getElementById(‘changeDifficultyButton’);
const resultContainer = document.getElementById(‘resultContainer’);
const resultText = document.getElementById(‘resultText’);
const mistakesContainer = document.getElementById(‘mistakesContainer’);
const showCertificateButton = document.getElementById(‘showCertificateButton’);
const certificateContainer = document.getElementById(‘certificateContainer’);
const downloadCertificateButton = document.getElementById(‘downloadCertificateButton’);
const pdfLoading = document.getElementById(‘pdfLoading’);
// Informations de l’utilisateur
let userData = {
prenom: ”,
nom: ”,
email: ”,
difficulty: ‘facile’,
score: 0
};
// Fonction pour afficher l’exercice selon le niveau de difficulté
function showExerciseByDifficulty(difficulty) {
// Masquer tous les exercices
document.querySelectorAll(‘.exercise-level’).forEach(el => {
el.style.display = ‘none’;
});
// Afficher l’exercice correspondant à la difficulté
const exerciseId = ‘exercise’ + difficulty.charAt(0).toUpperCase() + difficulty.slice(1);
document.getElementById(exerciseId).style.display = ‘block’;
userData.difficulty = difficulty;
}
// Démarrer l’exercice
startButton.addEventListener(‘click’, function() {
// Valider le formulaire
const prenom = document.getElementById(‘prenom’).value.trim();
const nom = document.getElementById(‘nom’).value.trim();
const email = document.getElementById(‘email’).value.trim();
const subscribe = document.getElementById(‘subscribe’).checked;
// Réinitialiser les messages d’erreur
document.getElementById(‘prenomError’).textContent = ”;
document.getElementById(‘nomError’).textContent = ”;
document.getElementById(‘emailError’).textContent = ”;
document.getElementById(‘subscribeError’).textContent = ”;
// Valider les champs
let isValid = true;
if (!prenom) {
document.getElementById(‘prenomError’).textContent = ‘Veuillez entrer votre prénom’;
isValid = false;
}
if (!nom) {
document.getElementById(‘nomError’).textContent = ‘Veuillez entrer votre nom’;
isValid = false;
}
if (!email) {
document.getElementById(‘emailError’).textContent = ‘Veuillez entrer votre email’;
isValid = false;
} else if (!validateEmail(email)) {
document.getElementById(‘emailError’).textContent = ‘Veuillez entrer un email valide’;
isValid = false;
}
if (!subscribe) {
document.getElementById(‘subscribeError’).textContent = ‘Vous devez accepter de vous abonner pour continuer’;
isValid = false;
}
if (isValid) {
// Enregistrer les données de l’utilisateur
userData.prenom = prenom;
userData.nom = nom;
userData.email = email;
// Masquer le formulaire et afficher l’exercice
subscriptionForm.style.display = ‘none’;
exerciseContainer.style.display = ‘block’;
// Afficher l’exercice selon la difficulté sélectionnée
showExerciseByDifficulty(userData.difficulty);
}
});
// Validation d’email
function validateEmail(email) {
const re = /^[^s@]+@[^s@]+.[^s@]+$/;
return re.test(email);
}
// Changer la difficulté
changeDifficultyButton.addEventListener(‘click’, function() {
const difficulty = difficultySelect.value;
showExerciseByDifficulty(difficulty);
// Réinitialiser les résultats
resultContainer.style.display = ‘none’;
certificateContainer.style.display = ‘none’;
// Réinitialiser les inputs
document.querySelectorAll(‘.pluriel-input’).forEach(input => {
input.value = ”;
input.classList.remove(‘correct’, ‘incorrect’);
});
});
// Vérifier les réponses
verifyButton.addEventListener(‘click’, function() {
const inputs = document.querySelectorAll(‘#exercise’ + userData.difficulty.charAt(0).toUpperCase() + userData.difficulty.slice(1) + ‘ .pluriel-input’);
let correctAnswers = 0;
let mistakes = [];
inputs.forEach(input => {
const userAnswer = input.value.trim().toLowerCase();
const correctAnswer = input.dataset.answer.toLowerCase();
const number = input.dataset.number;
if (userAnswer === correctAnswer) {
input.classList.add(‘correct’);
input.classList.remove(‘incorrect’);
correctAnswers++;
} else {
input.classList.add(‘incorrect’);
input.classList.remove(‘correct’);
mistakes.push({
number: number,
question: input.previousElementSibling.textContent.trim(),
userAnswer: userAnswer,
correctAnswer: correctAnswer
});
}
});
// Calculer le score
userData.score = Math.round((correctAnswers / inputs.length) * 100);
// Afficher les résultats
resultText.textContent = `Votre score: ${userData.score}% (${correctAnswers} réponses correctes sur ${inputs.length})`;
// Afficher les erreurs
mistakesContainer.innerHTML = ”;
if (mistakes.length > 0) {
const errorsTitle = document.createElement(‘h4’);
errorsTitle.textContent = ‘Vos erreurs:’;
mistakesContainer.appendChild(errorsTitle);
const errorsList = document.createElement(‘ul’);
mistakes.forEach(mistake => {
const errorItem = document.createElement(‘li’);
errorItem.innerHTML = `Question ${mistake.number}: ${mistake.question} – Votre réponse: “${mistake.userAnswer}” – Réponse correcte: “${mistake.correctAnswer}”`;
errorsList.appendChild(errorItem);
});
mistakesContainer.appendChild(errorsList);
}
// Afficher le conteneur de résultats
resultContainer.style.display = ‘block’;
// Afficher le bouton de certificat si score >= 70%
if (userData.score >= 70) {
showCertificateButton.style.display = ‘block’;
} else {
showCertificateButton.style.display = ‘none’;
}
});
// Afficher le certificat
showCertificateButton.addEventListener(‘click’, function() {
// Afficher le conteneur de certificat
certificateContainer.style.display = ‘block’;
// Populer le certificat
document.getElementById(‘certificateName’).textContent = `${userData.prenom} ${userData.nom}`;
document.getElementById(‘certificateLevel’).textContent = userData.difficulty;
document.getElementById(‘certificateScore’).textContent = `${userData.score}%`;
// Date du jour
const today = new Date();
const options = { year: ‘numeric’, month: ‘long’, day: ‘numeric’ };
document.getElementById(‘certificateDate’).textContent = today.toLocaleDateString(‘fr-FR’, options);
// Générer le QR code
generateQRCode(`Certificat de ${userData.prenom} ${userData.nom} – Score: ${userData.score}% – Date: ${today.toLocaleDateString(‘fr-FR’)}`);
// Générer des motifs triangulaires
generateTrianglePatterns();
// Définir l’image d’arrière-plan
const certificateBackground = document.querySelector(‘.certificate-background’);
certificateBackground.style.backgroundImage = “url(‘data:image/svg+xml;utf8,FLE’)”;
});
// Générer les motifs triangulaires
function generateTrianglePatterns() {
const topRightTriangle = document.querySelector(‘.triangle-pattern.top-right’);
const bottomLeftTriangle = document.querySelector(‘.triangle-pattern.bottom-left’);
topRightTriangle.style.backgroundImage = “url(‘data:image/svg+xml;utf8,’)”;
bottomLeftTriangle.style.backgroundImage = “url(‘data:image/svg+xml;utf8,’)”;
}
// Générer un QR code
function generateQRCode(text) {
if (typeof qrcode !== ‘undefined’) {
const qrDiv = document.querySelector(‘.certificate-qr’);
qrDiv.innerHTML = ”;
const qr = qrcode(0, ‘M’);
qr.addData(text);
qr.make();
const img = document.createElement(‘img’);
img.src = qr.createDataURL();
qrDiv.appendChild(img);
}
}
// Télécharger le certificat
downloadCertificateButton.addEventListener(‘click’, function() {
// Afficher le chargement
pdfLoading.style.display = ‘block’;
// Utiliser html2canvas pour capturer le certificat
html2canvas(document.getElementById(‘certificatePreview’)).then(canvas => {
const imgData = canvas.toDataURL(‘image/png’);
// Créer un PDF avec jsPDF
const { jsPDF } = window.jspdf;
const pdf = new jsPDF(‘landscape’, ‘mm’, ‘a4’);
const pageWidth = pdf.internal.pageSize.getWidth();
const pageHeight = pdf.internal.pageSize.getHeight();
// Calculer les dimensions pour que l’image s’adapte à la page
const ratio = canvas.width / canvas.height;
let imgWidth = pageWidth – 20;
let imgHeight = imgWidth / ratio;
// S’assurer que l’image ne dépasse pas la hauteur de la page
if (imgHeight > pageHeight – 20) {
imgHeight = pageHeight – 20;
imgWidth = imgHeight * ratio;
}
// Ajouter l’image au PDF
pdf.addImage(imgData, ‘PNG’, (pageWidth – imgWidth) / 2, (pageHeight – imgHeight) / 2, imgWidth, imgHeight);
// Télécharger le PDF
pdf.save(`certificat_${userData.prenom}_${userData.nom}.pdf`);
// Masquer le chargement
pdfLoading.style.display = ‘none’;
});
});
// Initialiser l’exercice au niveau facile par défaut
showExerciseByDifficulty(‘facile’);
});