HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
Any URLs added here will be added as <link>
s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
Any URL's added here will be added as <script>
s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
Search for and use JavaScript packages from npm here. By selecting a package, an import
statement will be added to the top of the JavaScript editor for this package.
Using packages here is powered by esm.sh, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CodePen - Multiple Choice Quiz</title>
<style>
@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600);
* {
margin: 0px;
padding: 0px;
font: 16px 'Source Sans Pro', sans-serif;
border: none;
box-sizing: border-box;
}
html, body {
background: #2E706C;
text-align: center;
width: 100%;
height: 100%;
}
html {
display: table;
}
body {
display: table-cell;
vertical-align: middle;
}
#quiz {
margin: -44px 50px 0px;
position: relative;
width: calc(100% - 100px);
}
#quiz h1 {
color: #FAFAFA;
font-weight: 600;
font-size: 36px;
text-transform: uppercase;
text-align: left;
line-height: 44px;
}
#quiz button {
float: right;
margin: 8px 0px 0px 8px;
padding: 4px 8px;
background: #9ACFCC;
color: #00403C;
font-size: 14px;
cursor: pointer;
outline: none;
}
#quiz button:hover {
background: #36a39c;
color: #FFF;
}
#quiz button:disabled {
opacity: 0.5;
background: #9ACFCC;
color: #00403C;
cursor: default;
}
#question {
padding: 20px;
background: #FAFAFA;
}
#question h2 {
margin-bottom: 16px;
font-weight: 600;
font-size: 20px;
}
#question input[type=radio] {
display: none;
}
#question label {
display: inline-block;
margin: 4px;
padding: 8px;
background: #FAE3BB;
color: #4C3000;
width: calc(50% - 8px);
min-width: 100px;
cursor: pointer;
}
#question label:hover {
background: #EBBB67;
}
#question input[type=radio]:checked + label {
background: #CB8306;
color: #FAFAFA;
}
#quiz-results {
display: flex;
flex-direction: column;
justify-content: center;
position: absolute;
top: 44px;
left: 0px;
background: #FAFAFA;
width: 100%;
height: calc(100% - 44px);
}
#quiz-results-message {
display: block;
color: #00403C;
font-size: 20px;
font-weight: bold;
}
#quiz-results-score {
display: block;
color: #31706c;
font-size: 20px;
}
#quiz-results-score b {
color: #00403C;
font-weight: 600;
font-size: 20px;
}
</style>
</head>
<body translate="no">
<div id="quiz">
<h1 style="font-size: 45px;" id="quiz-name"></h1><br>
<button id="submit-button">Submit Answers</button>
<button id="next-question-button">Next Question</button>
<button id="prev-question-button">Previous</button>
<div id="quiz-results">
<p id="quiz-results-message"></p>
<p id="quiz-results-score"></p>
</div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script id="rendered-js">
// Array of all the questions and choices to populate the questions. This might be saved in some JSON file or a database and we would have to read the data in.
var all_questions = [{
question_string: "¿A quién quieres nominar para la Presidenta de las Damas?",
choices: {
correct: "Blue",
wrong: ["Pink", "Orange", "Green"]
}
}, {
question_string: "¿A quién quieres nominar para la Presidenta de las Damas?",
choices: {
correct: "Summer",
wrong: ["Winter", "Autumn", "Spring"]
}
}, {
question_string: "¿A quién quieres nominar para la Presidenta de las Damas?",
choices: {
correct: "Three",
wrong: ["One", "Two", "Four"]
}
}, {
question_string: '¿A quién quieres nominar para la Presidenta de las Damas?',
choices: {
correct: "Harry Potter",
wrong: ["Hermione Granger", "Ron Weasley", "Voldemort"]
}
}];
// An object for a Quiz, which will contain Question objects.
var Quiz = function(quiz_name) {
// Private fields for an instance of a Quiz object.
this.quiz_name = quiz_name;
// This one will contain an array of Question objects in the order that the questions will be presented.
this.questions = [];
}
// A function that you can enact on an instance of a quiz object. This function is called add_question() and takes in a Question object which it will add to the questions field.
Quiz.prototype.add_question = function(question) {
// Randomly choose where to add question
var index_to_add_question = Math.floor(Math.random() * this.questions.length);
this.questions.splice(index_to_add_question, 0, question);
}
// A function that you can enact on an instance of a quiz object. This function is called render() and takes in a variable called the container, which is the <div> that I will render the quiz in.
Quiz.prototype.render = function(container) {
// For when we're out of scope
var self = this;
// Hide the quiz results modal
$('#quiz-results').hide();
// Write the name of the quiz
$('#quiz-name').text(this.quiz_name);
// Create a container for questions
var question_container = $('<div>').attr('id', 'question').insertAfter('#quiz-name');
// Helper function for changing the question and updating the buttons
function change_question() {
self.questions[current_question_index].render(question_container);
$('#prev-question-button').prop('disabled', current_question_index === 0);
$('#next-question-button').prop('disabled', current_question_index === self.questions.length - 1);
// Determine if all questions have been answered
var all_questions_answered = true;
for (var i = 0; i < self.questions.length; i++) {
if (self.questions[i].user_choice_index === null) {
all_questions_answered = false;
break;
}
}
$('#submit-button').prop('disabled', !all_questions_answered);
}
// Render the first question
var current_question_index = 0;
change_question();
// Add listener for the previous question button
$('#prev-question-button').click(function() {
if (current_question_index > 0) {
current_question_index--;
change_question();
}
});
// Add listener for the next question button
$('#next-question-button').click(function() {
if (current_question_index < self.questions.length - 1) {
current_question_index++;
change_question();
}
});
// Add listener for the submit answers button
$('#submit-button').click(function() {
// Determine how many questions the user got right
var score = 0;
for (var i = 0; i < self.questions.length; i++) {
if (self.questions[i].user_choice_index === self.questions[i].correct_choice_index) {
score++;
}
}
// Display the score with the appropriate message
var percentage = score / self.questions.length;
console.log(percentage);
var message;
if (percentage === 1) {
message = 'Great job!'
} else if (percentage >= .75) {
message = 'You did alright.'
} else if (percentage >= .5) {
message = 'Better luck next time.'
} else {
message = 'Maybe you should try a little harder.'
}
$('#quiz-results-message').text(message);
$('#quiz-results-score').html('You got <b>' + score + '/' + self.questions.length + '</b> questions correct.');
$('#quiz-results').slideDown();
$('#quiz button').slideUp();
});
// Add a listener on the questions container to listen for user select changes. This is for determining whether we can submit answers or not.
question_container.bind('user-select-change', function() {
var all_questions_answered = true;
for (var i = 0; i < self.questions.length; i++) {
if (self.questions[i].user_choice_index === null) {
all_questions_answered = false;
break;
}
}
$('#submit-button').prop('disabled', !all_questions_answered);
});
}
// An object for a Question, which contains the question, the correct choice, and wrong choices. This block is the constructor.
var Question = function(question_string, correct_choice, wrong_choices) {
// Private fields for an instance of a Question object.
this.question_string = question_string;
this.choices = [];
this.user_choice_index = null; // Index of the user's choice selection
// Random assign the correct choice an index
this.correct_choice_index = Math.floor(Math.random() * wrong_choices.length + 1);
// Fill in this.choices with the choices
var number_of_choices = wrong_choices.length + 1;
for (var i = 0; i < number_of_choices; i++) {
if (i === this.correct_choice_index) {
this.choices[i] = correct_choice;
} else {
// Randomly pick a wrong choice to put in this index
var wrong_choice_index = Math.floor(Math.random(0, wrong_choices.length));
this.choices[i] = wrong_choices[wrong_choice_index];
// Remove the wrong choice from the wrong choice array so that we don't pick it again
wrong_choices.splice(wrong_choice_index, 1);
}
}
}
// A function that you can enact on an instance of a question object. This function is called render() and takes in a variable called the container, which is the <div> that I will render the question in. This question will "return" with the score when the question has been answered.
Question.prototype.render = function(container) {
// For when we're out of scope
var self = this;
// Fill out the question label
var question_string_h2;
if (container.children('h2').length === 0) {
question_string_h2 = $('<h2>').appendTo(container);
} else {
question_string_h2 = container.children('h2').first();
}
question_string_h2.text(this.question_string);
// Clear any radio buttons and create new ones
if (container.children('input[type=radio]').length > 0) {
container.children('input[type=radio]').each(function() {
var radio_button_id = $(this).attr('id');
$(this).remove();
container.children('label[for=' + radio_button_id + ']').remove();
});
}
for (var i = 0; i < this.choices.length; i++) {
// Create the radio button
var choice_radio_button = $('<input>')
.attr('id', 'choices-' + i)
.attr('type', 'radio')
.attr('name', 'choices')
.attr('value', 'choices-' + i)
.attr('checked', i === this.user_choice_index)
.appendTo(container);
// Create the label
var choice_label = $('<label>')
.text(this.choices[i])
.attr('for', 'choices-' + i)
.appendTo(container);
}
// Add a listener for the radio button to change which one the user has clicked on
$('input[name=choices]').change(function(index) {
var selected_radio_button_value = $('input[name=choices]:checked').val();
// Change the user choice index
self.user_choice_index = parseInt(selected_radio_button_value.substr(selected_radio_button_value.length - 1, 1));
// Trigger a user-select-change
container.trigger('user-select-change');
});
}
// "Main method" which will create all the objects and render the Quiz.
$(document).ready(function() {
// Create an instance of the Quiz object
var quiz = new Quiz('Elecciones - El Buen Pastor');
// Create Question objects from all_questions and add them to the Quiz object
for (var i = 0; i < all_questions.length; i++) {
// Create a new Question object
var question = new Question(all_questions[i].question_string, all_questions[i].choices.correct, all_questions[i].choices.wrong);
// Add the question to the instance of the Quiz object that we created previously
quiz.add_question(question);
}
// Render the quiz
var quiz_container = $('#quiz');
quiz.render(quiz_container);
});
</script>
</body>
</html>
@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600);
* {
margin: 0px;
padding: 0px;
font: 16px 'Source Sans Pro', sans-serif;
border: none;
box-sizing: border-box;
}
html, body {
background: #2E706C;
text-align: center;
width: 100%;
height: 100%;
}
html {
display: table;
}
body {
display: table-cell;
vertical-align: middle;
}
#quiz {
margin: -44px 50px 0px;
position: relative;
width: calc(100% - 100px);
}
#quiz h1 {
color: #FAFAFA;
font-weight: 600;
font-size: 36px;
text-transform: uppercase;
text-align: left;
line-height: 44px;
}
#quiz button {
float: right;
margin: 8px 0px 0px 8px;
padding: 4px 8px;
background: #9ACFCC;
color: #00403C;
font-size: 14px;
cursor: pointer;
outline: none;
}
#quiz button:hover {
background: #36a39c;
color: #FFF;
}
#quiz button:disabled {
opacity: 0.5;
background: #9ACFCC;
color: #00403C;
cursor: default;
}
#question {
padding: 20px;
background: #FAFAFA;
}
#question h2 {
margin-bottom: 16px;
font-weight: 600;
font-size: 20px;
}
#question input[type=radio] {
display: none;
}
#question label {
display: inline-block;
margin: 4px;
padding: 8px;
background: #FAE3BB;
color: #4C3000;
width: calc(50% - 8px);
min-width: 100px;
cursor: pointer;
}
#question label:hover {
background: #EBBB67;
}
#question input[type=radio]:checked + label {
background: #CB8306;
color: #FAFAFA;
}
#quiz-results {
display: flex;
flex-direction: column;
justify-content: center;
position: absolute;
top: 44px;
left: 0px;
background: #FAFAFA;
width: 100%;
height: calc(100% - 44px);
}
#quiz-results-message {
display: block;
color: #00403C;
font-size: 20px;
font-weight: bold;
}
#quiz-results-score {
display: block;
color: #31706c;
font-size: 20px;
}
#quiz-results-score b {
color: #00403C;
font-weight: 600;
font-size: 20px;
}
Also see: Tab Triggers