├── .gitignore ├── README.md ├── Requirements.md ├── app.js ├── assets ├── fonts │ ├── OFL.txt │ ├── README.txt │ ├── Rubik-Italic-VariableFont_wght.ttf │ ├── Rubik-VariableFont_wght.ttf │ └── static │ │ ├── Rubik-Italic.ttf │ │ ├── Rubik-Medium.ttf │ │ └── Rubik-Regular.ttf └── images │ ├── favicon-32x32.png │ ├── icon-accessibility.svg │ ├── icon-correct.svg │ ├── icon-css.svg │ ├── icon-error.svg │ ├── icon-html.svg │ ├── icon-incorrect.svg │ ├── icon-js.svg │ ├── icon-moon-dark.svg │ ├── icon-moon-light.svg │ ├── icon-sun-dark.svg │ ├── icon-sun-light.svg │ ├── pattern-background-desktop-dark.svg │ ├── pattern-background-desktop-light.svg │ ├── pattern-background-mobile-dark.svg │ ├── pattern-background-mobile-light.svg │ ├── pattern-background-tablet-dark.svg │ └── pattern-background-tablet-light.svg ├── data.json ├── index.html ├── preview.jpg ├── screenshots ├── desktop-dark.png ├── desktop-light.png ├── mobile-dark.png └── mobile-light.png └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | # Avoid accidental upload of the Sketch and Figma design files 2 | ##################################################### 3 | ## Please do not remove lines 5 and 6 - thanks! 🙂 ## 4 | ##################################################### 5 | *.sketch 6 | *.fig 7 | 8 | # Avoid accidental XD upload if you convert the design file 9 | ############################################### 10 | ## Please do not remove line 12 - thanks! 🙂 ## 11 | ############################################### 12 | *.xd 13 | 14 | # Avoid your project being littered with annoying .DS_Store files! 15 | .DS_Store 16 | .prettierignore -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Frontend Mentor - Frontend quiz app solution 2 | 3 | This is a solution to the [Frontend quiz app challenge on Frontend Mentor](https://www.frontendmentor.io/challenges/frontend-quiz-app-BE7xkzXQnU). Frontend Mentor challenges help you improve your coding skills by building realistic projects. 4 | 5 | ## Table of contents 6 | 7 | - [Overview](#overview) 8 | - [The challenge](#the-challenge) 9 | - [Screenshot](#screenshot) 10 | - [Links](#links) 11 | - [My process](#my-process) 12 | - [Built with](#built-with) 13 | - [What I learned](#what-i-learned) 14 | - [Continued development](#continued-development) 15 | - [Useful resources](#useful-resources) 16 | - [Author](#author) 17 | 18 | ## Overview 19 | 20 | ### The challenge 21 | 22 | Users should be able to: 23 | 24 | - Select a quiz subject 25 | - Select a single answer from each question from a choice of four 26 | - See an error message when trying to submit an answer without making a selection 27 | - See if they have made a correct or incorrect choice when they submit an answer 28 | - Move on to the next question after seeing the question result 29 | - See a completed state with the score after the final question 30 | - Play again to choose another subject 31 | - View the optimal layout for the interface depending on their device's screen size 32 | - See hover and focus states for all interactive elements on the page 33 | - Navigate the entire app only using their keyboard 34 | - **Bonus**: Change the app's theme between light and dark 35 | 36 | ### Screenshot 37 | 38 | ![desktop Light](./screenshots/desktop-light.png "Light mode desktop view") 39 | ![desktop dark](./screenshots/desktop-dark.png "Dark mode desktop view") 40 | ![mobile Dark](./screenshots/mobile-dark.png "dark mode mobile view") 41 | ![mobile light](./screenshots/mobile-light.png "light mode mobile view") 42 | 43 | ### Links 44 | 45 | - Solution URL: [Solution URL](https://github.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app) 46 | - Live Site URL: [Live site URL](https://rainsaxfrontend-mentor-projects.github.io/frontend-quiz-app/) 47 | 48 | ## My process 49 | 50 | ### Built with 51 | 52 | - Semantic HTML5 markup 53 | - CSS custom properties 54 | - Flexbox 55 | - CSS Grid 56 | - Mobile-first workflow 57 | 58 | ### What I learned 59 | 60 | In doing this project I got a ton of practice with javascript and CSS. One of the biggest new things I learned was how to retrive data from a .json file. This involved learning and working with fetch(), Promises, await, and .json(), all of which were new to me. Another new approach I got more comfortable with was the practice of creating a class in CSS such as .visible, and having js simply toggle that class on and off when appropriate. This was my refactored approach to each of the quiz screens and through the CSS I was able to delegate .visible's activities via media queries. 61 | 62 | ```js 63 | async function getQuiz(type) { 64 | const response = await fetch('./data.json'); 65 | const data = await response.json(); 66 | for (const quiz of data.quizzes) { 67 | if (quiz.title == type) { 68 | quizChosen = quiz; 69 | totalQuestions = quizChosen.questions.length; 70 | document.querySelector(".question-total").textContent = totalQuestions 71 | increment = (1 / totalQuestions) * 100; 72 | } 73 | } 74 | makeQuestions(quizChosen) 75 | } 76 | ``` 77 | 78 | ### Continued development 79 | 80 | I think it will be fun to continue working on this assignment as an on going project. For the future, I plan to add difficulty levels with different sets of questions. The program already allows for a variable number of questions. 81 | 82 | ### Useful resources 83 | 84 | - [fetch with json](https://dmitripavlutin.com/fetch-with-json/) - This helped me understand how to use await, fetch, and .json() 85 | 86 | ## Author 87 | 88 | - Frontend Mentor - [@rainSax](https://www.frontendmentor.io/profile/rainSax) 89 | -------------------------------------------------------------------------------- /Requirements.md: -------------------------------------------------------------------------------- 1 | -Light / Dark toggle, need to research this - DONE 2 | - reading data from json file 3 | - organize content in a grid -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | // light dark switch section 2 | const toggleSwitch = document.querySelector('.light-dark-switch input[type="checkbox"]'); 3 | document.querySelector(".start-menu").classList.toggle("visible") 4 | 5 | function switchMode(event) { 6 | if (event.target.checked) { 7 | document.documentElement.setAttribute('data-theme', 'dark'); 8 | } 9 | else { 10 | document.documentElement.setAttribute('data-theme', 'light'); 11 | } 12 | } 13 | 14 | toggleSwitch.addEventListener('change', switchMode, false); 15 | 16 | var quizButtons = document.querySelectorAll(".quiz-type"); 17 | var quizType; 18 | 19 | for (var i = 0; i < quizButtons.length; i++) { 20 | quizButtons[i].addEventListener("click", function () { 21 | quizType = this.id; 22 | questionScreen(quizType); 23 | }) 24 | } 25 | 26 | function questionScreen(type) { 27 | document.querySelector(".start-menu").classList.toggle("visible") 28 | setSubjectBars(type) 29 | document.querySelector(".question-screen").classList.toggle("visible") 30 | 31 | //retrieve quiz data based on selection 32 | getQuiz(type); 33 | } 34 | 35 | function setSubjectBars(type) { 36 | var bars = document.querySelectorAll(".curr-subject"); 37 | for (let bar of bars) { 38 | bar.lastElementChild.innerHTML = type 39 | if (type == "HTML") { 40 | bar.firstElementChild.firstElementChild.src = "./assets/images/icon-html.svg" 41 | } 42 | else if (type == "CSS") { 43 | bar.firstElementChild.firstElementChild.src = "./assets/images/icon-css.svg" 44 | } 45 | else if (type == "JavaScript") { 46 | bar.firstElementChild.firstElementChild.src = "./assets/images/icon-js.svg" 47 | } 48 | else { 49 | bar.firstElementChild.firstElementChild.src = "./assets/images/icon-accessibility.svg" 50 | } 51 | bar.style.visibility = "visible" 52 | } 53 | } 54 | 55 | var quizChosen; 56 | var qCount = -1; 57 | var totalQuestions; 58 | var score = 0; 59 | var submit = document.querySelector(".submit-answer"); 60 | var increment; 61 | 62 | // fetch returns a Promise, .json() returns a *2nd* Promise, therefore 2 .thens 63 | async function getQuiz(type) { 64 | const response = await fetch('./data.json'); 65 | const data = await response.json(); 66 | for (const quiz of data.quizzes) { 67 | if (quiz.title == type) { 68 | quizChosen = quiz; 69 | totalQuestions = quizChosen.questions.length; 70 | document.querySelector(".question-total").textContent = totalQuestions 71 | increment = (1 / totalQuestions) * 100; 72 | } 73 | } 74 | makeQuestions(quizChosen) 75 | } 76 | 77 | // quiz flow: 78 | // populate fields -> submit event handler validates (wrong - show wrong, do nothing. right - show right, move on) 79 | 80 | function makeQuestions(quizChoice) { 81 | qCount++; 82 | document.querySelector(".question-number").textContent = (qCount + 1); 83 | document.querySelector(".progress-bar.done").style.width = (increment * (qCount + 1)).toString() + "%"; 84 | submit.textContent = "Submit" 85 | let options = document.querySelectorAll(".option"); 86 | 87 | document.querySelector(".question").textContent = quizChoice.questions[qCount].question; 88 | 89 | for (let option of options) { 90 | option.classList.remove("selected") 91 | option.classList.remove("invalid") 92 | option.classList.remove("correct") 93 | } 94 | 95 | for (let i = 0; i < options.length; i++) { 96 | switch (i) { 97 | case 0: options[i].innerHTML = "
A
" 98 | break; 99 | case 1: options[i].innerHTML = "
B
" 100 | break; 101 | case 2: options[i].innerHTML = "
C
" 102 | break; 103 | case 3: options[i].innerHTML = "
D
" 104 | break; 105 | } 106 | options[i].append(quizChoice.questions[qCount].options[i]) 107 | } 108 | } 109 | 110 | var options = document.querySelectorAll(".option"); 111 | 112 | for (let i = 0; i < options.length; i++) { 113 | options[i].addEventListener("click", function () { 114 | for (option of options) { 115 | option.classList.remove("selected") 116 | option.firstChild.classList.remove("selected-box") 117 | } 118 | options[i].classList.add("selected") 119 | options[i].firstChild.classList.add("selected-box") 120 | }) 121 | } 122 | 123 | submit.addEventListener("click", function () { 124 | let selectedBox, answerText; 125 | 126 | if (submit.textContent == "Next Question") { 127 | makeQuestions(quizChosen); 128 | return; 129 | } 130 | if (submit.textContent == "See Results") { 131 | showQuizComplete(); 132 | return; 133 | } 134 | if (selectedBox = document.querySelector(".selected")) { 135 | 136 | // remove selection letter from string 137 | answerText = selectedBox.textContent.slice(1, selectedBox.textContent.length); 138 | 139 | // once submit is pressed, is a selected box exists, remove it's selected classes 140 | selectedBox.classList.remove("selected") 141 | selectedBox.firstChild.classList.remove("selected-box") 142 | } 143 | else { 144 | document.querySelector(".select-prompt").style.visibility = "visible" 145 | return 146 | } 147 | 148 | if (validate(answerText)) { 149 | // instead of makeQuestions, change styling to green look, and submit button to next question text 150 | if (!selectedBox.classList.contains("correct")) { 151 | score++; 152 | selectedBox.innerHTML += "" 153 | } 154 | selectedBox.classList.add("correct") 155 | selectedBox.firstChild.classList.add("correct-box") 156 | document.querySelector(".select-prompt").style.visibility = "hidden" 157 | } 158 | else { 159 | // apply some invalid css styles to boxes 160 | if (!selectedBox.classList.contains("invalid")) { 161 | selectedBox.innerHTML += "" 162 | } 163 | 164 | selectedBox.classList.add("invalid") 165 | selectedBox.firstChild.classList.add("invalid-box") 166 | document.querySelector(".select-prompt").style.visibility = "hidden" 167 | } 168 | 169 | revealAnswers(); 170 | 171 | if (qCount >= (totalQuestions - 1)) { 172 | submit.textContent = "See Results" 173 | 174 | } 175 | else { 176 | submit.textContent = "Next Question"; 177 | } 178 | return; 179 | }) 180 | 181 | function revealAnswers() { 182 | for (option of options) { 183 | let text = option.textContent.slice(1, option.textContent.length) 184 | 185 | if (validate(text)) { 186 | if (!option.classList.contains("correct")) { 187 | option.classList.add("correct") 188 | option.firstChild.classList.add("correct-box") 189 | option.innerHTML += "" 190 | 191 | } 192 | } 193 | else { 194 | if (!option.classList.contains("invalid")) { 195 | option.classList.add("invalid") 196 | option.firstChild.classList.add("invalid-box") 197 | option.innerHTML += "" 198 | } 199 | } 200 | } 201 | } 202 | 203 | function validate(selected) { 204 | let question = quizChosen.questions[qCount]; 205 | return (question.answer === selected) 206 | } 207 | 208 | function showQuizComplete() { 209 | document.querySelector(".question-screen").classList.toggle("visible") 210 | document.querySelector(".quiz-complete").classList.toggle("visible") 211 | document.querySelector(".final-score").textContent = score 212 | document.querySelector(".complete-question-total").textContent = totalQuestions 213 | } 214 | 215 | document.querySelector(".restart").addEventListener("click", function () { 216 | document.querySelector(".quiz-complete").classList.toggle("visible") 217 | document.querySelector(".start-menu").classList.toggle("visible") 218 | document.querySelector(".curr-subject").style.visibility = "hidden" 219 | qCount = -1 220 | score = 0 221 | }) -------------------------------------------------------------------------------- /assets/fonts/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright 2015 The Rubik Project Authors (https://github.com/googlefonts/rubik) 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /assets/fonts/README.txt: -------------------------------------------------------------------------------- 1 | Rubik Variable Font 2 | =================== 3 | 4 | This download contains Rubik as both variable fonts and static fonts. 5 | 6 | Rubik is a variable font with this axis: 7 | wght 8 | 9 | This means all the styles are contained in these files: 10 | Rubik-VariableFont_wght.ttf 11 | Rubik-Italic-VariableFont_wght.ttf 12 | 13 | If your app fully supports variable fonts, you can now pick intermediate styles 14 | that aren’t available as static fonts. Not all apps support variable fonts, and 15 | in those cases you can use the static font files for Rubik: 16 | static/Rubik-Light.ttf 17 | static/Rubik-Regular.ttf 18 | static/Rubik-Medium.ttf 19 | static/Rubik-SemiBold.ttf 20 | static/Rubik-Bold.ttf 21 | static/Rubik-ExtraBold.ttf 22 | static/Rubik-Black.ttf 23 | static/Rubik-LightItalic.ttf 24 | static/Rubik-Italic.ttf 25 | static/Rubik-MediumItalic.ttf 26 | static/Rubik-SemiBoldItalic.ttf 27 | static/Rubik-BoldItalic.ttf 28 | static/Rubik-ExtraBoldItalic.ttf 29 | static/Rubik-BlackItalic.ttf 30 | 31 | Get started 32 | ----------- 33 | 34 | 1. Install the font files you want to use 35 | 36 | 2. Use your app's font picker to view the font family and all the 37 | available styles 38 | 39 | Learn more about variable fonts 40 | ------------------------------- 41 | 42 | https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts 43 | https://variablefonts.typenetwork.com 44 | https://medium.com/variable-fonts 45 | 46 | In desktop apps 47 | 48 | https://theblog.adobe.com/can-variable-fonts-illustrator-cc 49 | https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts 50 | 51 | Online 52 | 53 | https://developers.google.com/fonts/docs/getting_started 54 | https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide 55 | https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts 56 | 57 | Installing fonts 58 | 59 | MacOS: https://support.apple.com/en-us/HT201749 60 | Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux 61 | Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows 62 | 63 | Android Apps 64 | 65 | https://developers.google.com/fonts/docs/android 66 | https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts 67 | 68 | License 69 | ------- 70 | Please read the full license text (OFL.txt) to understand the permissions, 71 | restrictions and requirements for usage, redistribution, and modification. 72 | 73 | You can use them in your products & projects – print or digital, 74 | commercial or otherwise. 75 | 76 | This isn't legal advice, please consider consulting a lawyer and see the full 77 | license for all details. 78 | -------------------------------------------------------------------------------- /assets/fonts/Rubik-Italic-VariableFont_wght.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app/4bd0ced7bc4bbae8adaa39ed26b6e72a30ab91ce/assets/fonts/Rubik-Italic-VariableFont_wght.ttf -------------------------------------------------------------------------------- /assets/fonts/Rubik-VariableFont_wght.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app/4bd0ced7bc4bbae8adaa39ed26b6e72a30ab91ce/assets/fonts/Rubik-VariableFont_wght.ttf -------------------------------------------------------------------------------- /assets/fonts/static/Rubik-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app/4bd0ced7bc4bbae8adaa39ed26b6e72a30ab91ce/assets/fonts/static/Rubik-Italic.ttf -------------------------------------------------------------------------------- /assets/fonts/static/Rubik-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app/4bd0ced7bc4bbae8adaa39ed26b6e72a30ab91ce/assets/fonts/static/Rubik-Medium.ttf -------------------------------------------------------------------------------- /assets/fonts/static/Rubik-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app/4bd0ced7bc4bbae8adaa39ed26b6e72a30ab91ce/assets/fonts/static/Rubik-Regular.ttf -------------------------------------------------------------------------------- /assets/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app/4bd0ced7bc4bbae8adaa39ed26b6e72a30ab91ce/assets/images/favicon-32x32.png -------------------------------------------------------------------------------- /assets/images/icon-accessibility.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/icon-correct.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/icon-css.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/icon-error.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/icon-html.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/icon-incorrect.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/icon-js.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/icon-moon-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/icon-moon-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/icon-sun-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/icon-sun-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/pattern-background-desktop-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/pattern-background-desktop-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/pattern-background-mobile-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/pattern-background-mobile-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/pattern-background-tablet-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/pattern-background-tablet-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data.json: -------------------------------------------------------------------------------- 1 | { 2 | "quizzes": [ 3 | { 4 | "title": "HTML", 5 | "icon": "./assets/images/icon-html.svg", 6 | "questions": [ 7 | { 8 | "question": "What does HTML stand for?", 9 | "options": [ 10 | "Hyper Trainer Marking Language", 11 | "Hyper Text Marketing Language", 12 | "Hyper Text Markup Language", 13 | "Hyper Text Markup Leveler" 14 | ], 15 | "answer": "Hyper Text Markup Language" 16 | }, 17 | { 18 | "question": "Which of the following is the correct structure for an HTML document?", 19 | "options": [ 20 | "", 21 | "", 22 | "", 23 | "" 24 | ], 25 | "answer": "" 26 | }, 27 | { 28 | "question": "Which HTML element is used to define the title of a document?", 29 | "options": [ 30 | "", 31 | "", 32 | "<header>", 33 | "<top>" 34 | ], 35 | "answer": "<title>" 36 | }, 37 | { 38 | "question": "What is the purpose of the <body> tag in HTML?", 39 | "options": [ 40 | "It defines the document's head section.", 41 | "It contains all the content such as text, images, and links.", 42 | "It is used to define the main content of an HTML document.", 43 | "It specifies the body of the email content in HTML." 44 | ], 45 | "answer": "It contains all the content such as text, images, and links." 46 | }, 47 | { 48 | "question": "Which HTML tag is used to create a hyperlink?", 49 | "options": [ 50 | "<hyperlink>", 51 | "<link>", 52 | "<a>", 53 | "<href>" 54 | ], 55 | "answer": "<a>" 56 | }, 57 | { 58 | "question": "Which tag is used to display images in HTML?", 59 | "options": [ 60 | "<img>", 61 | "<image>", 62 | "<src>", 63 | "<pic>" 64 | ], 65 | "answer": "<img>" 66 | }, 67 | { 68 | "question": "What attribute is used to provide the path of an image in the <img> tag?", 69 | "options": [ 70 | "link", 71 | "src", 72 | "href", 73 | "url" 74 | ], 75 | "answer": "src" 76 | }, 77 | { 78 | "question": "Which HTML tag is used to create an unordered list?", 79 | "options": [ 80 | "<ul>", 81 | "<ol>", 82 | "<list>", 83 | "<li>" 84 | ], 85 | "answer": "<ul>" 86 | }, 87 | { 88 | "question": "What does the <br> tag do?", 89 | "options": [ 90 | "It breaks the text into two sections.", 91 | "It creates a bold text.", 92 | "It inserts a line break.", 93 | "It adds a new row in a table." 94 | ], 95 | "answer": "It inserts a line break." 96 | }, 97 | { 98 | "question": "In HTML, what does the `fieldset` tag do?", 99 | "options": [ 100 | "It is used to group related data in a form.", 101 | "It sets the field to a fixed size.", 102 | "It automatically validates the fields within a form.", 103 | "It hides the fields in a form." 104 | ], 105 | "answer": "It is used to group related data in a form." 106 | } 107 | ] 108 | }, 109 | { 110 | "title": "CSS", 111 | "icon": "./assets/images/icon-css.svg", 112 | "questions": [ 113 | { 114 | "question": "What does CSS stand for?", 115 | "options": [ 116 | "Colorful Style Sheets", 117 | "Computer Style Sheets", 118 | "Cascading Style Sheets", 119 | "Creative Style Sheets" 120 | ], 121 | "answer": "Cascading Style Sheets" 122 | }, 123 | { 124 | "question": "Which HTML attribute is used to define inline styles?", 125 | "options": [ 126 | "styles", 127 | "style", 128 | "class", 129 | "font-style" 130 | ], 131 | "answer": "style" 132 | }, 133 | { 134 | "question": "How do you insert a comment in a CSS file?", 135 | "options": [ 136 | "// this is a comment //", 137 | "/* this is a comment */", 138 | "-- this is a comment --", 139 | "<!-- this is a comment -->" 140 | ], 141 | "answer": "/* this is a comment */" 142 | }, 143 | { 144 | "question": "Which property is used to change the background color of an element?", 145 | "options": [ 146 | "color", 147 | "bgcolor", 148 | "background-color", 149 | "background" 150 | ], 151 | "answer": "background-color" 152 | }, 153 | { 154 | "question": "How do you apply a style to all <p> elements?", 155 | "options": [ 156 | "p { }", 157 | ".p { }", 158 | "#p { }", 159 | "all.p { }" 160 | ], 161 | "answer": "p { }" 162 | }, 163 | { 164 | "question": "Which property is used to change the font of an element?", 165 | "options": [ 166 | "font-style", 167 | "text-style", 168 | "font-family", 169 | "typeface" 170 | ], 171 | "answer": "font-family" 172 | }, 173 | { 174 | "question": "How do you make each word in a text start with a capital letter?", 175 | "options": [ 176 | "text-transform: capitalize", 177 | "text-transform: uppercase", 178 | "text-style: capital", 179 | "font-transform: capitalize" 180 | ], 181 | "answer": "text-transform: capitalize" 182 | }, 183 | { 184 | "question": "How do you select an element with the class name 'header'?", 185 | "options": [ 186 | ".header", 187 | "#header", 188 | "header", 189 | "*header" 190 | ], 191 | "answer": ".header" 192 | }, 193 | { 194 | "question": "What is the default value of the 'position' property?", 195 | "options": [ 196 | "relative", 197 | "fixed", 198 | "absolute", 199 | "static" 200 | ], 201 | "answer": "static" 202 | }, 203 | { 204 | "question": "What is the purpose of the z-index property in CSS?", 205 | "options": [ 206 | "To count the number of elements", 207 | "To set the magnification level of an element", 208 | "To specify the stack order of an element", 209 | "To create a zoom effect" 210 | ], 211 | "answer": "To specify the stack order of an element" 212 | } 213 | ] 214 | }, 215 | { 216 | "title": "JavaScript", 217 | "icon": "./assets/images/icon-js.svg", 218 | "questions": [ 219 | { 220 | "question": "Which syntax is correct to output 'Hello World' in an alert box?", 221 | "options": [ 222 | "alertBox('Hello World');", 223 | "msg('Hello World');", 224 | "alert('Hello World');", 225 | "msgBox('Hello World');" 226 | ], 227 | "answer": "alert('Hello World');" 228 | }, 229 | { 230 | "question": "How do you call a function named 'myFunction'?", 231 | "options": [ 232 | "call function myFunction()", 233 | "call myFunction()", 234 | "myFunction()", 235 | "execute myFunction()" 236 | ], 237 | "answer": "myFunction()" 238 | }, 239 | { 240 | "question": "How to write an IF statement in JavaScript?", 241 | "options": [ 242 | "if i = 5 then", 243 | "if (i == 5)", 244 | "if i == 5", 245 | "if i = 5" 246 | ], 247 | "answer": "if (i == 5)" 248 | }, 249 | { 250 | "question": "How to write an IF statement for executing some code if 'i' is NOT equal to 5?", 251 | "options": [ 252 | "if (i <> 5)", 253 | "if i =! 5 then", 254 | "if (i != 5)", 255 | "if i not = 5" 256 | ], 257 | "answer": "if (i != 5)" 258 | }, 259 | { 260 | "question": "How does a FOR loop start?", 261 | "options": [ 262 | "for (i = 0; i <= 5)", 263 | "for i = 1 to 5", 264 | "for (i <= 5; i++)", 265 | "for (i = 0; i <= 5; i++)" 266 | ], 267 | "answer": "for (i = 0; i <= 5; i++)" 268 | }, 269 | { 270 | "question": "How can you add a comment in a JavaScript?", 271 | "options": [ 272 | "'This is a comment", 273 | "//This is a comment", 274 | "<!--This is a comment-->", 275 | "/* This is a comment */" 276 | ], 277 | "answer": "//This is a comment" 278 | }, 279 | { 280 | "question": "What is the correct way to write a JavaScript array?", 281 | "options": [ 282 | "var colors = (1:'red', 2:'green', 3:'blue')", 283 | "var colors = ['red', 'green', 'blue']", 284 | "var colors = 'red', 'green', 'blue'", 285 | "var colors = 1 = ('red'), 2 = ('green'), 3 = ('blue')" 286 | ], 287 | "answer": "var colors = ['red', 'green', 'blue']" 288 | }, 289 | { 290 | "question": "How do you find the number with the highest value of x and y?", 291 | "options": [ 292 | "Math.ceil(x, y)", 293 | "top(x, y)", 294 | "Math.max(x, y)", 295 | "Math.highest(x, y)" 296 | ], 297 | "answer": "Math.max(x, y)" 298 | }, 299 | { 300 | "question": "Which operator is used to assign a value to a variable?", 301 | "options": [ 302 | "-", 303 | "*", 304 | "=", 305 | "x" 306 | ], 307 | "answer": "=" 308 | }, 309 | { 310 | "question": "What is the correct way to write a JavaScript object?", 311 | "options": [ 312 | "var person = {firstName: 'John', lastName: 'Doe'};", 313 | "var person = {firstName = 'John', lastName = 'Doe'};", 314 | "var person = (firstName: 'John', lastName: 'Doe');", 315 | "var person = (firstName = 'John', lastName = 'Doe');" 316 | ], 317 | "answer": "var person = {firstName: 'John', lastName: 'Doe'};" 318 | } 319 | ] 320 | }, 321 | { 322 | "title": "Accessibility", 323 | "icon": "./assets/images/icon-accessibility.svg", 324 | "questions": [ 325 | { 326 | "question": "What does 'WCAG' stand for?", 327 | "options": [ 328 | "Web Content Accessibility Guidelines", 329 | "Web Compliance Accessibility Guide", 330 | "Web Content Accessibility Goals", 331 | "Website Compliance and Accessibility Guidelines" 332 | ], 333 | "answer": "Web Content Accessibility Guidelines" 334 | }, 335 | { 336 | "question": "Which element is used to provide alternative text for images for screen reader users?", 337 | "options": [ 338 | "<alt>", 339 | "<figcaption>", 340 | "<description>", 341 | "<img alt='description'>" 342 | ], 343 | "answer": "<img alt='description'>" 344 | }, 345 | { 346 | "question": "What does ARIA stand for in web development?", 347 | "options": [ 348 | "Accessible Rich Internet Applications", 349 | "Advanced Responsive Internet Assistance", 350 | "Accessible Responsive Internet Applications", 351 | "Automated Responsive Internet Actions" 352 | ], 353 | "answer": "Accessible Rich Internet Applications" 354 | }, 355 | { 356 | "question": "Which of the following is not a principle of the WCAG?", 357 | "options": [ 358 | "Perceivable", 359 | "Dependable", 360 | "Operable", 361 | "Understandable" 362 | ], 363 | "answer": "Dependable" 364 | }, 365 | { 366 | "question": "Which of these color contrast ratios defines the minimum WCAG 2.1 Level AA requirement for normal text?", 367 | "options": [ 368 | "3:1", 369 | "4.5:1", 370 | "7:1", 371 | "2:1" 372 | ], 373 | "answer": "4.5:1" 374 | }, 375 | { 376 | "question": "Which of the following elements is inherently focusable, meaning it can receive focus without a 'tabindex' attribute?", 377 | "options": [ 378 | "<div>", 379 | "<span>", 380 | "<a href='...'>", 381 | "<p>" 382 | ], 383 | "answer": "<a href='...'>" 384 | }, 385 | { 386 | "question": "What is the purpose of the 'lang' attribute in an HTML page?", 387 | "options": [ 388 | "To specify the scripting language", 389 | "To define the character set", 390 | "To indicate the language of the page content", 391 | "To declare a language pack" 392 | ], 393 | "answer": "To indicate the language of the page content" 394 | }, 395 | { 396 | "question": "Which guideline ensures that content is accessible by keyboard as well as by mouse?", 397 | "options": [ 398 | "Keyboard Accessible", 399 | "Mouse Independence", 400 | "Device Independence", 401 | "Operable Controls" 402 | ], 403 | "answer": "Keyboard Accessible" 404 | }, 405 | { 406 | "question": "What is the role of 'skip navigation' links in web accessibility?", 407 | "options": [ 408 | "To skip over primary navigation to the main content", 409 | "To provide shortcuts to different sections of the website", 410 | "To help users skip unwanted sections like advertisements", 411 | "To bypass broken links in the navigation" 412 | ], 413 | "answer": "To skip over primary navigation to the main content" 414 | }, 415 | { 416 | "question": "Which of these tools can help in checking the accessibility of a website?", 417 | "options": [ 418 | "W3C Validator", 419 | "Google Lighthouse", 420 | "CSS Validator", 421 | "JavaScript Console" 422 | ], 423 | "answer": "Google Lighthouse" 424 | } 425 | ] 426 | } 427 | ] 428 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html lang="en"> 3 | 4 | <head> 5 | <meta charset="UTF-8"> 6 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 | 8 | <link rel="icon" type="image/png" sizes="32x32" href="./assets/images/favicon-32x32.png"> 9 | <link rel="stylesheet" href="./style.css"> 10 | 11 | <link rel="preconnect" href="https://fonts.googleapis.com"> 12 | <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 13 | <link href="https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,400;0,500;1,400&display=swap" rel="stylesheet"> 14 | 15 | <title>Frontend Mentor | Frontend quiz app 16 | 17 | 18 | 19 |
20 |
21 |
22 |
23 | subject icon 24 |
25 | 26 |

some Subject

27 |
28 |
29 |
30 | picture of sun 31 |
32 | 36 |
37 | picture of moon 38 |
39 |
40 |
41 | 42 | 43 | 44 |
45 |
46 |

Welcome to the Frontend Quiz!

47 |

Pick a subject to get started.

48 |
49 | 50 |
51 | 56 | 61 | 67 | 73 |
74 |
75 | 76 | 77 | 78 | 79 | 80 |
81 |
82 |
83 |

Question of

85 |

Placeholder

86 |
87 |
88 |
89 | 90 |
91 |
92 |
93 |
94 | 97 | 100 | 103 | 106 | 107 | 108 |
109 | error icon 110 |

Please select an answer

111 |
112 |
113 |
114 | 115 | 116 | 117 | 118 | 119 |
120 |
121 |

Quiz completed 122 | You scored... 123 |

124 |
125 | 126 |
127 |
128 |
129 |
130 | subject icon 131 |
132 | 133 |

some Subject

134 |
135 |

136 |

out of totalQ

137 |
138 | 139 |
140 | 141 |
142 | 143 | 144 | 145 |
146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app/4bd0ced7bc4bbae8adaa39ed26b6e72a30ab91ce/preview.jpg -------------------------------------------------------------------------------- /screenshots/desktop-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app/4bd0ced7bc4bbae8adaa39ed26b6e72a30ab91ce/screenshots/desktop-dark.png -------------------------------------------------------------------------------- /screenshots/desktop-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app/4bd0ced7bc4bbae8adaa39ed26b6e72a30ab91ce/screenshots/desktop-light.png -------------------------------------------------------------------------------- /screenshots/mobile-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app/4bd0ced7bc4bbae8adaa39ed26b6e72a30ab91ce/screenshots/mobile-dark.png -------------------------------------------------------------------------------- /screenshots/mobile-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rainSaxFrontend-Mentor-Projects/frontend-quiz-app/4bd0ced7bc4bbae8adaa39ed26b6e72a30ab91ce/screenshots/mobile-light.png -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --html-bg: #FFF1E9; 3 | --css-bg: #E0FDEF; 4 | --js-bg: #EBF0FF; 5 | --accessibility-bg: #F6E7FF; 6 | --text-color: #313E51; 7 | --text-color-p: #626C7F; 8 | --purple: #A729F5; 9 | --bg-col: white; 10 | --button-bg: white; 11 | --option-bg: #F4F6FA; 12 | --option-color: #626C7F; 13 | --correct-color: #26D782; 14 | --invalid-color: #EE5454; 15 | --bg: url("./assets/images/pattern-background-mobile-light.svg"); 16 | --sun-src: url("./assets/images/icon-sun-dark.svg"); 17 | --moon-src: url("./assets/images/icon-moon-dark.svg"); 18 | } 19 | 20 | [data-theme="dark"] { 21 | --text-color: #FFF; 22 | --text-color-p: #ABC1E1; 23 | --bg-col: #313E51; 24 | --button-bg: #3B4D66; 25 | --bg: url("./assets/images/pattern-background-mobile-dark.svg"); 26 | --sun-src: url("./assets/images/icon-sun-light.svg"); 27 | --moon-src: url("./assets/images/icon-moon-light.svg"); 28 | } 29 | 30 | /**************** begin css reset ****************/ 31 | 32 | html { 33 | box-sizing: border-box; 34 | } 35 | 36 | body { 37 | font-family: 'Rubik', sans-serif; 38 | background-color: var(--bg-col); 39 | background-image: var(--bg); 40 | background-repeat: no-repeat; 41 | background-size: cover; 42 | } 43 | 44 | *, 45 | *::before, 46 | *::after { 47 | box-sizing: inherit; 48 | } 49 | 50 | * { 51 | margin: 0; 52 | } 53 | 54 | img, 55 | svg { 56 | display: block; 57 | max-width: 100%; 58 | } 59 | 60 | button { 61 | font: inherit; 62 | } 63 | 64 | /*************** End of css reset ****************/ 65 | 66 | /*************** Start Hide Other Screens ****************/ 67 | .start-menu { 68 | display: none; 69 | } 70 | 71 | .quiz-complete { 72 | display: none; 73 | flex-direction: column; 74 | } 75 | 76 | .question-screen { 77 | display: none; 78 | flex-direction: column; 79 | } 80 | 81 | .row-top { 82 | display: flex; 83 | justify-content: space-between; 84 | margin-bottom: 1rem; 85 | } 86 | 87 | .curr-subject { 88 | display: flex; 89 | align-items: center; 90 | visibility: hidden; 91 | gap: 1rem; 92 | } 93 | 94 | /*************** End Hide Other Screens ****************/ 95 | 96 | /*************** Start - Light / Dark Toggle Switch ****************/ 97 | 98 | .light-dark-toggle { 99 | display: flex; 100 | align-items: center; 101 | gap: .5rem; 102 | } 103 | 104 | .light-dark-switch { 105 | display: inline-block; 106 | position: relative; 107 | width: clamp(2rem, 1.647887323943662rem + 1.5023474178403755vw, 3rem); 108 | height: clamp(1.25rem, 1.073943661971831rem + 0.7511737089201878vw, 1.75rem); 109 | } 110 | 111 | .light-dark-switch input { 112 | display: none; 113 | } 114 | 115 | .slider { 116 | background-color: var(--purple); 117 | bottom: 0; 118 | cursor: pointer; 119 | left: 0; 120 | position: absolute; 121 | right: 0; 122 | top: 0; 123 | transition: .4s; 124 | } 125 | 126 | .slider:before { 127 | background-color: #fff; 128 | bottom: 4px; 129 | content: ""; 130 | height: clamp(0.75rem, 0.573943661971831rem + 0.7511737089201878vw, 1.25rem); 131 | left: 4px; 132 | position: absolute; 133 | transition: .4s; 134 | width: clamp(0.75rem, 0.573943661971831rem + 0.7511737089201878vw, 1.25rem); 135 | } 136 | 137 | input:checked+.slider:before { 138 | transform: translateX(clamp(0.8125rem, 0.7033450704225352rem + 0.46572769953051646vw, 1.1225rem)); 139 | } 140 | 141 | .slider.round { 142 | border-radius: 62.4375rem; 143 | } 144 | 145 | .slider.round:before { 146 | border-radius: 50%; 147 | } 148 | 149 | .sun-container, 150 | .moon-container { 151 | width: clamp(1rem, 0.823943661971831rem + 0.7511737089201878vw, 1.5rem); 152 | height: clamp(1rem, 0.823943661971831rem + 0.7511737089201878vw, 1.5rem); 153 | } 154 | 155 | .sun-container>img { 156 | content: var(--sun-src); 157 | } 158 | 159 | .moon-container>img { 160 | content: var(--moon-src); 161 | } 162 | 163 | /*************** End - Light / Dark Toggle Switch ****************/ 164 | body { 165 | height: 100vh; 166 | display: flex; 167 | justify-content: center; 168 | } 169 | 170 | article { 171 | padding: 1rem 1.5rem; 172 | } 173 | 174 | h1 { 175 | color: var(--text-color); 176 | font-weight: 300; 177 | font-size: 2.5rem; 178 | font-size: clamp(2.5rem, 1.972rem + 2.25vw, 4rem); 179 | } 180 | 181 | h1>span { 182 | font-weight: 500; 183 | } 184 | 185 | h2 { 186 | color: var(--text-color); 187 | font-size: 1.125rem; 188 | font-size: clamp(1.125rem, 0.905rem + 0.939vw, 1.75rem); 189 | font-weight: 500; 190 | } 191 | 192 | .question { 193 | font-size: 1.25rem; 194 | font-size: clamp(1.25rem, 0.898rem + 1.502vw, 2.25rem); 195 | } 196 | 197 | p { 198 | color: var(--text-color-p); 199 | font-style: italic; 200 | font-weight: 400; 201 | margin-top: 1rem; 202 | margin-bottom: 2.5rem; 203 | } 204 | 205 | .progress-bar.whole { 206 | width: 100%; 207 | height: 1rem; 208 | background-color: white; 209 | margin-top: 1.5rem; 210 | margin-bottom: 2.5rem; 211 | padding: .25rem; 212 | border-radius: 62.4375rem; 213 | } 214 | 215 | .progress-bar.done { 216 | background-color: var(--purple); 217 | border-radius: 6.5rem; 218 | width: 0%; 219 | height: .5rem; 220 | } 221 | 222 | .choices { 223 | display: flex; 224 | flex-direction: column; 225 | gap: .75rem; 226 | } 227 | 228 | button { 229 | background-color: var(--button-bg); 230 | color: var(--text-color); 231 | font-size: 1.125rem; 232 | font-weight: 500; 233 | display: grid; 234 | grid-template-rows: 1fr; 235 | grid-template-columns: 1fr 3fr 1fr; 236 | align-items: center; 237 | justify-items: start; 238 | width: 100%; 239 | gap: 1rem; 240 | border-radius: .75rem; 241 | border: 0; 242 | padding: .75rem; 243 | box-shadow: 0px 16px 40px 0px rgba(143, 160, 193, .14); 244 | } 245 | 246 | button:hover { 247 | cursor: pointer; 248 | } 249 | 250 | .option { 251 | border: 3px solid transparent; 252 | } 253 | 254 | .submit-answer, 255 | .restart { 256 | display: flex; 257 | align-items: center; 258 | justify-content: center; 259 | background-color: var(--purple); 260 | color: white; 261 | } 262 | 263 | .submit-answer:hover, 264 | .restart:hover { 265 | background: linear-gradient(0deg, rgba(255, 255, 255, .5) 0%, rgba(255, 255, 255, 0.50) 100%), var(--purple); 266 | } 267 | 268 | .button-icon-container>img { 269 | border-radius: .75rem; 270 | padding: .15rem; 271 | } 272 | 273 | .button-icon-container>img[src="./assets/images/icon-html.svg"] { 274 | background-color: var(--html-bg); 275 | } 276 | 277 | .button-icon-container>img[src="./assets/images/icon-css.svg"] { 278 | background-color: var(--css-bg); 279 | } 280 | 281 | .button-icon-container>img[src="./assets/images/icon-js.svg"] { 282 | background-color: var(--js-bg); 283 | } 284 | 285 | .button-icon-container>img[src="./assets/images/icon-accessibility.svg"] { 286 | background-color: var(--accessibility-bg); 287 | } 288 | 289 | .option-box { 290 | display: flex; 291 | align-items: center; 292 | justify-content: center; 293 | color: var(--option-color); 294 | width: 2.5rem; 295 | height: 2.5rem; 296 | border-radius: .75rem; 297 | background-color: var(--option-bg); 298 | } 299 | 300 | .select-prompt { 301 | display: flex; 302 | align-items: center; 303 | justify-content: center; 304 | visibility: hidden; 305 | gap: 1rem; 306 | } 307 | 308 | .select-prompt>p { 309 | color: var(--invalid-color); 310 | margin: 0; 311 | font-style: normal; 312 | } 313 | 314 | .selected-box { 315 | background-color: var(--purple); 316 | color: white; 317 | } 318 | 319 | .selected { 320 | border-color: var(--purple); 321 | } 322 | 323 | .correct-box { 324 | background-color: var(--correct-color); 325 | color: white; 326 | } 327 | 328 | .correct { 329 | border-color: var(--correct-color); 330 | } 331 | 332 | .correct-icon { 333 | justify-self: end; 334 | } 335 | 336 | .invalid-box { 337 | background-color: var(--invalid-color); 338 | color: white; 339 | } 340 | 341 | .invalid { 342 | border-color: var(--invalid-color); 343 | } 344 | 345 | .invalid-icon { 346 | justify-self: end; 347 | } 348 | 349 | .question-count { 350 | margin-top: 0; 351 | } 352 | 353 | .left-content { 354 | display: flex; 355 | flex-direction: column; 356 | justify-content: space-between; 357 | } 358 | 359 | .start-menu>.left-content { 360 | justify-content: flex-start; 361 | gap: 3rem; 362 | } 363 | 364 | .visible { 365 | display: block; 366 | } 367 | 368 | .score-container { 369 | background: var(--bg-col); 370 | color: var(--text-color); 371 | display: flex; 372 | flex-direction: column; 373 | align-items: center; 374 | justify-content: center; 375 | gap: 1rem; 376 | margin-bottom: 2rem; 377 | margin-top: 2.5rem; 378 | border-radius: 1.5rem; 379 | padding: 2rem; 380 | } 381 | 382 | .score-container>p { 383 | margin: 0; 384 | } 385 | 386 | .scored { 387 | font-weight: 500; 388 | } 389 | 390 | .score-out-of { 391 | font-style: normal; 392 | } 393 | 394 | .final-score { 395 | font-weight: 500; 396 | font-size: clamp(5.5rem, 4.268rem + 5.258vw, 9rem); 397 | text-align: center; 398 | font-style: normal; 399 | } 400 | 401 | @media (min-width: 768px) { 402 | button { 403 | font-size: 1.75rem; 404 | } 405 | 406 | article { 407 | padding: 2.5rem 4rem; 408 | } 409 | 410 | .question-screen { 411 | flex-direction: column; 412 | } 413 | 414 | .quiz-complete { 415 | flex-direction: column; 416 | } 417 | 418 | .row-top { 419 | margin-bottom: 0; 420 | } 421 | 422 | h1 { 423 | width: 29rem; 424 | } 425 | } 426 | 427 | @media (min-width: 1440px) { 428 | 429 | body { 430 | align-items: center; 431 | } 432 | 433 | .left-content { 434 | max-width: 35rem; 435 | } 436 | 437 | .visible { 438 | display: flex; 439 | } 440 | 441 | .start-menu { 442 | justify-content: space-between; 443 | gap: 10rem; 444 | } 445 | 446 | .question-screen { 447 | flex-direction: row; 448 | gap: 10rem; 449 | } 450 | 451 | .quiz-complete { 452 | flex-direction: row; 453 | gap: 10rem; 454 | } 455 | 456 | .choices { 457 | width: 35rem; 458 | height: 28rem; 459 | gap: 1.5rem; 460 | } 461 | } --------------------------------------------------------------------------------