Rewrite ~120 validation error messages across 17 English lesson modules and their localized variants (ar, de, es, pl, uk) to use concept questions, property hints, and directional nudges instead of revealing the exact CSS property-value answers. Priority modules (flexbox, box-model, colors, positioning) fully rewritten. All remaining CSS modules updated. Only message strings changed — no validation logic modifications.
146 lines
6.9 KiB
JSON
146 lines
6.9 KiB
JSON
{
|
|
"$schema": "../schemas/code-crispies-module-schema.json",
|
|
"id": "transitions-animations",
|
|
"title": "CSS Animations",
|
|
"description": "Bring interactivity to your UI by smoothly transitioning properties and creating keyframe-driven animations.",
|
|
"difficulty": "intermediate",
|
|
"lessons": [
|
|
{
|
|
"id": "transitions-1",
|
|
"title": "Transitions",
|
|
"description": "Learn how to apply <kbd>transition</kbd> to properties for smooth changes on state changes.<br><br><pre>transition: property duration;\n/* e.g. transition: background-color 0.3s; */</pre>",
|
|
"task": "Add <kbd>transition: background-color 0.3s</kbd> to <kbd>.btn</kbd> so the color fades smoothly on hover.",
|
|
"previewHTML": "<button class=\"btn\">Hover Me</button>",
|
|
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .btn { background: black; color: white; padding: 0.5rem 1rem; border: none; cursor: pointer; } .btn:hover { background: white; color: black; }",
|
|
"sandboxCSS": "",
|
|
"codePrefix": "/* Add transition */\n.btn {",
|
|
"initialCode": "",
|
|
"codeSuffix": "}",
|
|
"solution": " transition: background-color 0.3s;",
|
|
"previewContainer": "preview-area",
|
|
"validations": [
|
|
{
|
|
"type": "contains",
|
|
"value": "transition",
|
|
"message": "Use the <kbd>transition</kbd> property",
|
|
"options": { "caseSensitive": false }
|
|
},
|
|
{
|
|
"type": "regex",
|
|
"value": "transition:\\s*background-color\\s*0\\.3s",
|
|
"message": "Specify which property to transition and how long it should take.",
|
|
"options": { "caseSensitive": false }
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "transitions-2",
|
|
"title": "Timing Funcs",
|
|
"description": "Explore easing functions like <kbd>ease</kbd>, <kbd>linear</kbd>, <kbd>ease-in</kbd>, <kbd>ease-out</kbd> to control animation pacing.",
|
|
"task": "Set <kbd>transition-timing-function</kbd> to <kbd>ease-in-out</kbd> on <kbd>.btn</kbd>.",
|
|
"previewHTML": "<button class=\"btn\">Timing</button>",
|
|
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .btn { background: navy; color: gold; padding: 0.5rem 1rem; border: none; cursor: pointer; transition: all 0.5s; } .btn:hover { background: gold; color: navy; transform: scale(1.1); }",
|
|
"sandboxCSS": "",
|
|
"codePrefix": "/* Set timing function */\n.btn {",
|
|
"initialCode": "",
|
|
"codeSuffix": "}",
|
|
"solution": " transition-timing-function: ease-in-out;",
|
|
"previewContainer": "preview-area",
|
|
"validations": [
|
|
{
|
|
"type": "contains",
|
|
"value": "transition-timing-function",
|
|
"message": "Use <kbd>transition-timing-function</kbd>",
|
|
"options": { "caseSensitive": false }
|
|
},
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "transition-timing-function", "expected": "ease-in-out" },
|
|
"message": "Which easing keyword starts slow, speeds up, then slows down again?"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "transitions-3",
|
|
"title": "Keyframes",
|
|
"description": "Create named animations using <kbd>@keyframes</kbd> and apply them via the <kbd>animation</kbd> shorthand.<br><br><pre>@keyframes bounce {\n 50% { transform: translateY(-20px); }\n}\n.ball {\n animation: bounce 1s infinite;\n}</pre>",
|
|
"task": "Define a keyframe at <kbd>50%</kbd> with <kbd>transform: translateY(-20px)</kbd> and apply <kbd>animation: bounce 1s infinite</kbd> to <kbd>.ball</kbd>.",
|
|
"previewHTML": "<div class=\"ball\"></div>",
|
|
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .ball { width: 50px; height: 50px; background: crimson; border-radius: 50%; margin: 2rem auto; }",
|
|
"sandboxCSS": "",
|
|
"codePrefix": "/* Define keyframes and apply animation */\n@keyframes bounce {",
|
|
"initialCode": "",
|
|
"codeSuffix": "}\n.ball { }",
|
|
"solution": " 50% { transform: translateY(-20px); }\n}\n.ball {\n animation: bounce 1s infinite;",
|
|
"previewContainer": "preview-area",
|
|
"validations": [
|
|
{
|
|
"type": "contains",
|
|
"value": "@keyframes bounce",
|
|
"message": "Define <kbd>@keyframes bounce</kbd>",
|
|
"options": { "caseSensitive": false }
|
|
},
|
|
{
|
|
"type": "regex",
|
|
"value": "50%.*transform: translateY\\(-20px\\)",
|
|
"message": "At <kbd>50%</kbd>, use <kbd>transform: translateY(-20px)</kbd>",
|
|
"options": { "caseSensitive": false }
|
|
},
|
|
{
|
|
"type": "contains",
|
|
"value": "animation",
|
|
"message": "Use <kbd>animation</kbd> property on <kbd>.ball</kbd>",
|
|
"options": { "caseSensitive": false }
|
|
},
|
|
{
|
|
"type": "regex",
|
|
"value": "animation:.*bounce.*1s.*infinite",
|
|
"message": "Use the <kbd>animation</kbd> shorthand: name, duration, and repeat count.",
|
|
"options": { "caseSensitive": false }
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "transitions-4",
|
|
"title": "Animation Properties",
|
|
"description": "Fine-tune animations with <kbd>animation-delay</kbd>, <kbd>animation-iteration-count</kbd>, <kbd>animation-direction</kbd>, and <kbd>animation-fill-mode</kbd>.",
|
|
"task": "Apply the <kbd>pulse</kbd> animation to <kbd>.box</kbd> with <kbd>animation-name: pulse</kbd>, <kbd>animation-duration: 2s</kbd>, <kbd>animation-delay: 1s</kbd>, <kbd>animation-iteration-count: 2</kbd>, and <kbd>animation-fill-mode: forwards</kbd>.",
|
|
"previewHTML": "<div class=\"box\">Pulse</div>",
|
|
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .box { width: 100px; height: 100px; background: black; color: white; display: flex; align-items: center; justify-content: center; margin: 2rem auto; } @keyframes pulse { 0% { background: black; color: white; transform: scale(1); } 50% { background: white; color: black; transform: scale(1.2); } 100% { background: limegreen; color: black; transform: scale(1); } }",
|
|
"sandboxCSS": "",
|
|
"codePrefix": "/* Apply animation properties */\n.box {",
|
|
"initialCode": "",
|
|
"codeSuffix": "}",
|
|
"solution": " animation-name: pulse;\n animation-duration: 2s;\n animation-delay: 1s;\n animation-iteration-count: 2;\n animation-fill-mode: forwards;",
|
|
"previewContainer": "preview-area",
|
|
"validations": [
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "animation-name", "expected": "pulse" },
|
|
"message": "Which property links an element to a named <kbd>@keyframes</kbd> rule?"
|
|
},
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "animation-duration", "expected": "2s" },
|
|
"message": "How long should one full cycle of the animation take?"
|
|
},
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "animation-delay", "expected": "1s" },
|
|
"message": "Which property makes the animation wait before starting?"
|
|
},
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "animation-iteration-count", "expected": "2" },
|
|
"message": "Which property controls how many times the animation repeats?"
|
|
},
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "animation-fill-mode", "expected": "forwards" },
|
|
"message": "Which property keeps the element styled in its final keyframe state after the animation ends?"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|