Blog: Web Design
Throwing the horns at a heavy metal concert

Build A Quiz In PHP: What Metal Band Are You?

Avatar for John Locke

John Locke is a SEO consultant from Sacramento, CA. He helps manufacturing businesses rank higher through his web agency, Lockedown SEO.

In 2013-2014, I had a series of client projects where I needed to build a quiz in PHP.

Taking what I learned from that, I designed a quiz of my own, where you answer multiple choice questions and determine what heavy metal band your personality resembles.

The subject matter can be changed to whatever your own needs are. The focus of this tutorial is to show how to build this particular quiz and explain how the logic works.

First, let me show you the finished quiz. Go ahead — try it out.

The Concept

This quiz consists of three PHP rendered pages: an intro screen, the quiz page, and a page that tallies the score and serves up the appropriate result. We will call these three files index, test, and grade. We actually only need the Test and Grade files — the Index file is just there to tell people what the quiz is.

This quiz was built to be embedded. The client projects I built from this original concept were also modified further to be responsive. (Thanks to some special developer magic on the destination site.) These “quizzes” were special ad placements for three well-known global brands that appeared on EW.com.

The Test page only shows one question screen at a time, but the real height of the page is greater than what is visible. You can make the Test page a single visible page with all the questions visible with a few small adjustments.

The basic idea is there are four possible outcomes. Each of these outcomes has a “scorecard” that starts at zero and clicking certain answers will add points to certain scorecards. When we get to the Grade screen, the scores are compared, and the outcome with the highest point total is shown. A call to action button asking users if they to play again links back to the Test screen, where the process starts over.

Implementing the Code

Let’s build the index.php file first. Here we have a simple form that collects answers, and when the Submit button is clicked, takes you to the test.php screen. The whole quiz screen is 600 by 450 pixels. There is a CSS folder and Images folder in the same folder as the PHP files.

The body is relatively positioned to stay centered, and many of the quiz elements are absolutely positioned. Your own variations on this may vary, so feel free to experiment.



<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>What Metal Band Are You? Quiz</title>
    <link rel="stylesheet" type="text/css" href="css/style.css" />
    <link href='http://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic' rel='stylesheet' type='text/css'>
</head>
<body>
    <div id="page-wrap">
        <form id="start-quiz" method="post" action="test.php">
            <div class="overlay index">
            <div class="quiz-overlay"></div>
	        <h1 class="index-headline">What Metal Band Are You?</h1>
		<p class="index-sell">This personality quiz will reveal which iconic metal band you resemble most.</p>
                <input type="submit" id="submit" class="take-quiz-btn index-btn" value="Take The Quiz" />
            </div>                       
        </form>
    </div>	     
</body>
</html>


/* CSS Part One */
* { 
  margin: 0; 
  padding: 0; 
}
html {
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  margin: 0 auto;
  width: 600px;
}
body { 
  background: #020305 url('../imgs/bg-texture.jpg') center center no-repeat;
  color: #fff; 
  font-family: 'Droid Serif', Times, serif; 
  font-size: 14px;
  max-width: 600px;
}
#page-wrap { 
  height: 450px;
  margin: 0 auto;
  overflow: hidden;
  position: relative;
  width: 600px;
}
h1 { 
  letter-spacing: 3px;
  margin: 25px 0; 
  text-transform: uppercase;
}
.index-sell, .index-headline {
  color: #1c2d37;
  left: 100px;
  margin: 0;
  position: absolute;
  text-align: center;
  width: 400px;
}
.index-headline {
  font-size: 36px;
  height: 0;
  letter-spacing: 1px;
  text-shadow: 1px 1px 2px #fff;
  top: 55px;
}
.index-sell {
  font-size: 21px;
  line-height: 28px;
  text-transform: uppercase;
}
.index-sell { top: 155px; }
.transparent {
  color: transparent;
  display: none;
  opacity: 0;
  visibility: hidden;
}
.take-quiz-btn, .embed-btn, .close-btn {
  -webkit-appearance: none;
  border: none;
  background: #28505e;
  color: #f3f4ef;
  cursor: pointer;
  font-family: 'Droid Serif', Times, serif;
}
.take-quiz-btn, .close-btn {
  background: #28505e;
  font-size: 21px;
  text-shadow: 1px 1px rgba(66,66,66,.666);
  text-transform: uppercase;
}
.take-quiz-btn {
  top: 267px; 
  width: 259px;
}
.index-btn {
  height: 49px;
  left: 168px;
  padding: 9px 0 6px 0;
  position: absolute;
  top: 267px; 
}
.quiz-overlay, .result {
  height: 325px;
  position: absolute;
  width: 552px;
  z-index: -1;
}
.index .quiz-overlay, .quiz-overlay { 
  background: rgba(226,255,246,.52) url(../imgs/horns-up.png); 
  background-size: cover;
}
.index .quiz-overlay {
  left: 24px;
}

The Test Questions

Now the test.php file is loaded. Here, the test questions are wrapped in a form tag and the answers will be recorded for the grade.php file, then evaluated, and an outcome determined.

Each question is the height of the visible screen. When an answer (or any element with the .fwrd class) is clicked on, a jQuery script moves the screen height up to display the next question. Each of the answers are radio buttons, meaning there can only be one answer accepted for each question input. The labels for each radio button lay on top of the buttons themselves, and have the illusion of being clickable links or buttons. These form labels can be styled in any manner you wish with CSS.


<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>What Metal Band Are You? Quiz</title>
    <link rel="stylesheet" type="text/css" href="css/style.css" />
    <link href='http://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic' rel='stylesheet' type='text/css'>
</head>
<body>
    <div id="page-wrap">
        <h1 class="transparent index-headline">Lockedown SEO: What Metal Band Are You?</h1>
	<form action="grade.php" method="post" id="quiz">
            <ul id="test-questions">
                <li>
                    <div class="quiz-overlay"></div>
                    <h3>What do you enjoy watching on TV?</h3>
                    <div class="mtm">
                        <input type="radio" name="question-1-answers" id="question-1-answers-A" value="A" />
                        <label for="question-1-answers-A" class="fwrd labela">a.  Science Fiction movies</label>
                    </div>
                    <div>
                        <input type="radio" name="question-1-answers" id="question-1-answers-B" value="B" />
                        <label for="question-1-answers-B" class="fwrd labelb">b.  CNN and MSNBC</label>
                    </div>
                    <div>
                        <input type="radio" name="question-1-answers" id="question-1-answers-C" value="C" />
                        <label for="question-1-answers-C" class="fwrd labelc">c.  History Channel</label>
                    </div>
                    <div>
                        <input type="radio" name="question-1-answers" id="question-1-answers-D" value="D" />
                        <label for="question-1-answers-D" class="fwrd labeld">d.  Fantasy movies, like <em>Lord of the Rings</em></label>
                    </div>
                    <p class="quiz-progress">1 of 5</p>
                </li>
                <li>
                    <div class="quiz-overlay"></div>
                    <h3>What’s your preferred method of travel?</h3>
                    <div class="mtm">
                        <input type="radio" name="question-2-answers" id="question-2-answers-A" value="A" />
                        <label for="question-2-answers-A" class="fwrd labela">a.  Riding a Harley Davidson</label>
                    </div>
                    <div>
                        <input type="radio" name="question-2-answers" id="question-2-answers-B" value="B" />
                        <label for="question-2-answers-B" class="fwrd labelb">b.  Offroading in a 4 by 4</label>
                    </div>
                    <div>
                        <input type="radio" name="question-2-answers" id="question-2-answers-C" value="C" />
                        <label for="question-2-answers-C" class="fwrd labelc">c.  Piloting my own plane</label>
                    </div>
                    <div>
                        <input type="radio" name="question-2-answers" id="question-2-answers-D" value="D" />
                        <label for="question-2-answers-D" class="fwrd labeld">d.  Riding a horse across the countryside</label>
                    </div>
                    <p class="quiz-progress">2 of 5</p>
                </li>
                <li>
                    <div class="quiz-overlay"></div>
                    <h3>What’s your favorite piece of clothing that you wear?</h3>
                    <div class="mtm">
                        <input type="radio" name="question-3-answers" id="question-3-answers-A" value="A" />
                        <label for="question-3-answers-A" class="fwrd labela">a.  My leather jacket</label>
                    </div>
                    <div>
                        <input type="radio" name="question-3-answers" id="question-3-answers-B" value="B" />
                        <label for="question-3-answers-B" class="fwrd labelb">b.  A dress shirt or nice pair of jeans</label>
                    </div>
                    <div>
                        <input type="radio" name="question-3-answers" id="question-3-answers-C" value="C" />
                        <label for="question-3-answers-C" class="fwrd labelc">c.  My favorite concert T shirt</label>
                    </div>
                    <div>
                        <input type="radio" name="question-3-answers" id="question-3-answers-D" value="D" />
                        <label for="question-3-answers-D" class="fwrd labeld">d.  Custom handmade clothing by a local artisan</label>
                    </div>
                    <p class="quiz-progress">3 of 5</p>
                </li>
                <li>
                    <div class="quiz-overlay"></div>
                    <h3>Out of these, what is your favorite type of music?</h3>
                    <div class="mtm">
                        <input type="radio" name="question-4-answers" id="question-4-answers-A" value="A" />
                        <label for="question-4-answers-A" class="fwrd labela">a.  Softer rock, like Fleetwood Mac or folk music</label>
                    </div>
                    <div>
                        <input type="radio" name="question-4-answers" id="question-4-answers-B" value="B" />
                        <label for="question-4-answers-B" class="fwrd labelb">b.  Punk rock, like the Sex Pistols</label>
                    </div>
                    <div>
                        <input type="radio" name="question-4-answers" id="question-4-answers-C" value="C" />
                        <label for="question-4-answers-C" class="fwrd labelc">c.  70s hard rock and arena rock</label>
                    </div>
                    <div>
                        <input type="radio" name="question-4-answers" id="question-4-answers-D" value="D" />
                        <label for="question-4-answers-D" class="fwrd labeld">d.  Classical music from the masters</label>
                    </div>
                    <p class="quiz-progress">4 of 5</p>
                </li>
                <li>
                    <div class="quiz-overlay"></div>
                    <h3>If you could meet anyone from history, who would you choose?</h3>
                    <div class="mtm">
                        <input type="radio" name="question-5-answers" id="question-5-answers-A" value="A" />
                        <label for="question-5-answers-A" class="fwrd labela">a.  Someone mythic, like Nostradamus or Rasputin</label>
                    </div>
                    <div>
                        <input type="radio" name="question-5-answers" id="question-5-answers-B" value="B" />
                        <label for="question-5-answers-B" class="fwrd labelb">b.  A famous writer, like John Steinbeck</label>
                    </div>
                    <div>
                        <input type="radio" name="question-5-answers" id="question-5-answers-C" value="C" />
                        <label for="question-5-answers-C" class="fwrd labelc">c.  A famous conquerer, like Alexander the Great</label>
                    </div>
                    <div>
                        <input type="radio" name="question-5-answers" id="question-5-answers-D" value="D" />
                        <label for="question-5-answers-D" class="fwrd labeld">d.  One of the Egyptian Pharaoahs</label>
                    </div>
                    <p class="quiz-progress">5 of 5</p>
                </li>
                <li>
                    <div class="quiz-overlay"></div>
                    <h3 class="anticipate">Now it’s time to see your results...</h3>
                    <input type="submit" value="Submit Quiz" id="submit-quiz" />
                </li>
            </ul>
	</form>
        <div class="nomargin"></div>
    </div>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js" ></script>
    <script>
           (function($) {
              var timeout= null;
              var $mt = 0;
              $("#quiz .fwrd").click(function(){
                clearTimeout(timeout);
                timeout = setTimeout(function(){ 
                    $mt = $mt - 430;
                    $("#test-questions").css("margin-top", $mt); 
                }, 333);
              });
           }(jQuery))
    </script>
</body>
</html>


/* CSS Part Two */
#quiz {
  margin: 0 18px;
  padding: 0 0 0 1px;
  position: relative;
  -webkit-transition: all linear .35s;
  -moz-transition: all linear .35s;
  -o-transition: all linear .35s;
  -ms-transition: all linear .35s;
  transition: all linear .35s;
}
#quiz .anticipate {
  color: #1c2d37;
  font-size: 32px;
  line-height: 41px;
  padding: 50px 0 0 0;
  text-shadow: 1px 1px rgba(255,255,255,.666);
}
#start-quiz {
  margin-top: 25px;
}
#quiz ul li div.quiz-overlay { margin: 0; }
#quiz ul {
  list-style-type: none;
  margin-top: 0;
}
#quiz h3 {
  color: #222;
  font-size: 22px; 
  font-weight: 400;
  line-height: 32px; 
  margin: 0 0 1px 0;
  min-height: 64px;  
  padding: 9px 50px 0;
  text-align: center;
}
#quiz ul li {
  height: 335px;
  margin: 25px 0 95px 0;
  max-height: 335px;
  min-height: 335px;
}
#quiz ul li div {
  color: #ebe9e6;
  margin: 10px 0;
  padding: 1px 0;
}
#quiz ul li div.mtm {
  margin-top: 20px;
}
#quiz input {
  opacity: 0;
  vertical-align: middle;
  width: 20px;
}
#quiz label, #quiz input#submit-quiz {
  background-color: #1f4c5b; 
  cursor: pointer;
  display: inline-block;
  z-index: 99;
}
#quiz label {
  height: 31px; 
  font-size: 13px;  
  line-height: 2.55em;  
  margin: 0 30px 0 0;
  max-width: 476px;
  min-width: 476px;
  padding: 2px 0 4px 16px;
  width: 476px;
}
#quiz input#submit-quiz {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background: #1f4c5b; 
  border: none;
  color: #ebe9e6;
  display: block;
  font-family: 'Droid Serif', Times, serif;
  font-size: 21px;
  height: 74px;
  margin: 43px auto 0;
  opacity: 1;
  width: 250px;
}
#quiz label, #quiz input[type=radio]:checked + label, #quiz input#submit-quiz, #replay, .take-quiz-btn {
  -webkit-transition: all ease .11s;
  -moz-transition: all ease .11s;
  -o-transition: all ease .11s;
  -ms-transition: all ease .11s;
  transition: all ease .11s;
}
#quiz label:hover, #quiz input[type=radio]:checked + label, #quiz input#submit-quiz:hover, #replay:hover, .take-quiz-btn:hover {
  background: #098636; 
  color: #fbfbfb;
}
#quiz .quiz-progress {
  color: #ebe9e6;
  font-size: 14px;
  padding: 7px 30px 5px 0; 
  text-align: right;
  text-shadow: 1px 1px #131313;
}
.nomargin { margin: 0;}

Many of the class names on this page are unused. What is necessary is the name attribute on each radio button. These must be present for the grading portion of the quiz to work.

The Submit Quiz button at the end takes us to the grading file, where the scores are assessed.

Grading The Answers, Choosing An Outcome

Next, we will build the grade.php. We had to think about how the scoring and outcomes would be determined before we build a test.php to gather those scores. Remember each outcome has its own score, which will be stored in the variables $totalA, $totalB, $totalC and $totalD.

There is a second set of variables, the $answer1 through $answer5 variables. These correspond to the answers for each question, which are



<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>What Classic Metal Band Are You? Quiz Results</title>
    <link rel="stylesheet" type="text/css" href="css/style.css" />
    <link href='http://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic' rel='stylesheet' type='text/css'>
</head>
<body>
    <div id="page-wrap">
        <h1 class="transparent index-headline" >Here’s What Metal Band You Are</h1>
        
        <?php
            $answer1 = $_POST['question-1-answers'];
            $answer2 = $_POST['question-2-answers'];
            $answer3 = $_POST['question-3-answers'];
            $answer4 = $_POST['question-4-answers'];
            $answer5 = $_POST['question-5-answers'];

            $totalA = 0;
            $totalB = 0;
            $totalC = 0;
            $totalD = 0;

            if ($answer1 == "A") { $totalA = $totalA + 1.17; $totalD = $totalD + .06; }
            if ($answer1 == "B") { $totalB = $totalB + 1.15; $totalC = $totalC + .05; }
            if ($answer1 == "C") { $totalC = $totalC + 1.13; $totalA = $totalA + .05; }
            if ($answer1 == "D") { $totalD = $totalD + 1.16; $totalA = $totalA + .07; }

            if ($answer2 == "A") { $totalA = $totalA + 1.23; }
            if ($answer2 == "B") { $totalB = $totalB + 1.15; }
            if ($answer2 == "C") { $totalC = $totalC + 1.13; }
            if ($answer2 == "D") { $totalD = $totalD + 1.16; }

            if ($answer3 == "A") { $totalA = $totalA + 1.17; $totalC = $totalC + .05; }
            if ($answer3 == "B") { $totalB = $totalB + 1.15; $totalC = $totalC + .03; }
            if ($answer3 == "C") { $totalC = $totalC + 1.13; $totalB = $totalB + .07; }
            if ($answer3 == "D") { $totalD = $totalD + 1.16; }

            if ($answer4 == "A") { $totalA = $totalA + 1.17; }
            if ($answer4 == "B") { $totalB = $totalB + 1.15; }
            if ($answer4 == "C") { $totalC = $totalC + 1.13; $totalA = $totalA + .05; $totalB = $totalB + .06; $totalD = $totalD + .07; }
            if ($answer4 == "D") { $totalD = $totalD + 1.16; $totalB = $totalB + .04; $totalA = $totalA + .045; $totalC = $totalC + .034; }

            if ($answer5 == "A") { $totalA = $totalA + 1.17; $totalD = $totalD + .08; }
            if ($answer5 == "B") { $totalB = $totalB + 1.15; }
            if ($answer5 == "C") { $totalC = $totalC + 1.14; $totalA = $totalA + .06; $totalD = $totalD + .08; }
            if ($answer5 == "D") { $totalD = $totalD + 1.16; $totalC = $totalC + .04; }

            ?>

One of the issue you will have to address in any quiz is how to score tie breakers. Since we have five questions on this quiz, we can end up with two outcomes with two votes apiece (Example: 2 “A” answers, 2 “C” answers, 1 “D” answer).

One way to solve this is to weigh all the outcomes slightly different. To clarify, if all of the outcome questions have the same amount of votes, there will be a predetermined pecking order, where one outcome always wins, and one outcome always loses. You could also make one particular question a tie-breaker, weighted heavier than the other questions.

Another way to solve this problem is to select certain questions, add full points for the “most correct” answer, and add small increments to the other scores for that answer. Because many of the questions I wrote related to more than one of the four outcomes, this is what I used for this particular quiz.

The downside to this solution is that you will have to experiment with how to weight the scores for each answer. I found very small fractions work best in this scenario. The more questions your quiz contains, the less feasible this is for a tie-breaker solution. The code above is what I went with for this quiz — you will have to adjust this for your own content.

The Outcomes

Below is the remainder of the grade.php file. For each outcome, the scores are being compared. For Outcome A to win, it must be greater than B, C, and D. If not, it goes to Outcome B, which must be greater than A, C, and D…and so on.

Whichever outcome scores highest is displayed. The HTML is output via an echo statement for each possible outcome.


 <div class="results-overlay">

            <?php
            if ($totalA > $totalB && $totalA > $totalC && $totalA > $totalD) {
                  echo '<div class="quiz-overlay result priest"></div><div class="results-text"><p class="you-chose">You Scored:</p><img src="../imgs/priest.jpg" alt="Judas Priest" class="results-img" /><div class="results test-results2"><p class="score">Judas Priest</p><p class="score-details">Judas Priest brought heavy metal to a new level with the twin guitars of Glen Tipton and KK Downing and vocals of Rob Halford. Songs you should listen to: Sinner, Victim of Changes, The Ripper, Beyond The Realms of Death, Delivering The Goods, Breaking The Law, Solar Angels, The Sentinel, Painkiller, Nightcrawler, Burn In Hell, Hellrider, Judas Rising.</p><a id="replay" class="take-quiz-btn" href="/test.php">Play Again?</a></div>';
            }
            elseif ($totalB > $totalA && $totalB > $totalC && $totalB > $totalD) {
                  echo '<div class="quiz-overlay result megadeth"></div><div class="results-text"><p class="you-chose">You Scored:</p><img src="../imgs/megadeth.jpg" alt="Megadeth" class="results-img" /><div class="results test-results2"><p class="score">Megadeth</p><p class="score-details">After getting tossed from Metallica, guitarist/singer Dave Mustaine formed Megadeth with bassist Dave Ellefson, one of the iconic thrash metal bands. Songs to check out: Peace Sells (But Who’s Buying), In My Darkest Hour, Holy Wars, Hangar 18, Tornado Of Souls, High Speed Dirt, Sweating Bullets, Angry Again, Trust, Kill The King.</p><a id="replay" class="take-quiz-btn" href="/test.php">Play Again?</a></div>';
            }
            elseif ($totalC > $totalA && $totalC > $totalB && $totalC > $totalD) {
                  echo '<div class="quiz-overlay result maiden"></div><div class="results-text"><p class="you-chose">You Scored:</p><img src="../imgs/maiden.jpg" alt="Iron Maiden" class="results-img" /><div class="results test-results2"><p class="score">Iron Maiden</p><p class="score-details">Iron Maiden was one of the first bands to play with extreme speed and precision, and were forerunners of speed and thrash metal. Their mascot, Eddie, is another part of their appeal. Be aure to check out these songs: Running Free, Number of the Beast, The Prisoner, Run To The Hills, The Trooper, 2 Minutes To Midnight, Deja Vu, Fear Of The Dark.<p></p><a id="replay" class="take-quiz-btn" href="/test.php">Play Again</a></div>';
            }
            elseif ($totalD > $totalA && $totalD > $totalB && $totalD > $totalC) {
                  echo '<div class="quiz-overlay result dio"></div><div class="results-text"><p class="you-chose">You Scored:</p><img src="../imgs/rjd.jpg" alt="Ronnie James Dio" class="results-img" /><div class="results test-results2"><p class="score">Ronnie James Dio</p><p class="score-details">Ronnie James Dio possessed one of the most powerful voices in rock history. He sang for Rainbow and Black Sabbath before forming his own band, Dio. Noteworthy songs to check out include: Heaven and Hell, Neon Nights, The Mob Rules, Holy Diver, Rainbow in The Dark, Don’t Talk To Strangers, The Last In Line, I, The Devil Cried.</p><a id="replay" class="take-quiz-btn" href="test.php">Play Again</a></div>';
            }   
        ?>     
                </div>
            </div>


/* CSS Part Three */
#replay {
  display: block;
  height: 46px;
  line-height: 46px;
  margin: 20px 0 0 0;
  padding: 0;
  text-align: center;
  text-decoration: none;
}
.results-img {
  border: 4px solid #ebe9e6;
  left: -25px;
  position: absolute;
  top: 8px;
  width: 208px;
}
.test-results2 {
  color: #fff;
  font-size: 15px;
  line-height: 21px;
  text-shadow: 1px 1px rgba(2,3,5,.666);
}
.test-results2 .score {
  color: #678792; 
  font-size: 22px; 
  line-height: 30px; 
  margin-bottom: 4px;
  text-transform: uppercase;
}
.results-overlay {
  background-color: transparent;
  margin: 42px 0 0 65px;
  max-height: 325px; 
  position: relative;
  width: 510px;
}
.results-overlay .quiz-overlay {
  left: -41px;
  top: -7px;
}
.results-text {
  padding: 5px 35px 30px 215px; 
}
.score-details {
  font-size: 12px; 
  line-height: 19px; 
}
.score-details-sm {
  font-size: 12px;
  line-height: 19px;
}
.result {
  height: 325px;
}
.priest {
  background: url(../imgs/priest-bg.jpg) no-repeat;
}
.megadeth {
  background: url(../imgs/megadeth-bg.jpg) no-repeat;
}
.maiden {
  background: url(../imgs/maiden-bg.jpg) no-repeat;
}
.dio {
  background: url(../imgs/dio-bg.jpg) no-repeat;
}

At the end, there is a simple JavaScript modal that displays the embed code when the appropriate button at the top right of the screen is clicked. Note this is a button element made to resemble a text link.


<p class="embed"><button class="embed-btn" onclick="modalshow()">Embed This Quiz</button></p>
    <div id="modalbg"></div>
    <div id="modalwindow">
        <p id="modalmsg">Copy the code below to embed it into your own website.</p>
        <textarea class="c-p"><iframe src="http://metalquiz.lockedownseo.com/" height="450" width="600"></iframe></textarea>
        <button class="close-btn" onclick="modalhide()">Close</button>
    </div>
</body>
</html>


/* CSS Part Four */
.embed {
  font-size: 14px;
  position: absolute;
  right: 26px; 
  text-shadow: 1px 1px #131313;
  top: 8px; 
}
#modalbg {
  background: #333; 
  display: none;
  height: 100%;  
  left: 0; 
  opacity: .4; 
  position: fixed; 
  top: 0;
  width: 100%;
  z-index: 9;
}
#modalwindow {
  background: rgba(255,255,255,.95); 
  border: 3px outset #ccc; 
  display: none; 
  height: 254px; 
  left: 25px;
  padding: 32px; 
  position: absolute; 
  top: 35px;
  width: 480px;
  z-index:10;
}
#modalmsg {
  color: #222;
  text-align: center; 
}
.embed-btn {
  background-color: transparent;
  font-size: 14px;
}
textarea.c-p {
  display: block;
  height: 50px;
  margin: 25px auto;
  width: 420px;
}
.close-btn {
  display: block;
  margin: 70px auto 0; 
  padding: 12px 24px;
}

Additional Notes

If you Right-Click > View Source on the actual iframe or subdomain where the quiz is located, you’ll notice most of the code is minified for the sake of speed. If you want to analyze the regular the source code for this project, be sure to take a look at the GitHub repo.

Much thanks to Chris Coyier and CSS-Tricks for giving me an idea of how to get this started.

I’d love to see some quizzes that you have put together yourselves. Post your links in the comments below!

Avatar for John Locke

John Locke is a SEO consultant from Sacramento, CA. He helps manufacturing businesses rank higher through his web agency, Lockedown SEO.

79 comments on “Build A Quiz In PHP: What Metal Band Are You?

  1. Very nice work, I am currently working on a questionnaire script that will be tallying up answers to questions in the same way that your script does so. I found this tutorial to be very helpful and the best explanation I have found online yet. Great work and thank you very much for sharing your method to this madness!

    -David

  2. The quiz looks really nice!
    I have been searching for something similar and I wonder if it is possible to group the questions into x amount of subgroups, have the answers weighted (like on a likert-scale from “never” to “always” where “never” sometimes gives you 5 points and sometimes 1 point, depending on the question), randomize the order of the questions, and then display the total of each subgroup with a corresponding answer?
    Brgds

    Hans

  3. Hello Hans:

    The randomization is the only part that I’m unsure about, but I’m sure there’s a way.

    You can change the weights of each answer, the questions and answers themselves can be changed. The results screens can be altered to display the count of each value (A, B, C, D). Just echo out the variable for each.

    If you publish your modified quiz, come back and post a link to it when it is online. I’m sure other readers would like to see it.

    Thanks,
    John

  4. 
    
    if ($answer1 == "A") { $totalA = $totalA + 5; }
                if ($answer1 == "B") { $totalB = $totalB + 4; }
                if ($answer1 == "C") { $totalC = $totalC + 3; }
                if ($answer1 == "D") { $totalD = $totalD + 2; }
    
    
    

    How would I make this more simple?
    Because I’m going to make 90 questions.

  5. Hi R: You’ll have to add this condition for each question in the quiz. Each PHP variable testing what the user answered is responsible for adding the values to the $totals variables.

  6. if make loop script from answer1 to answer2, etc (from the previous question)
    is it possible to make it loop??

  7. You might be able to loop through the different results if all the ‘A’ answers line up with result A, ‘B’ answers with B results and so forth. Seems like you could loop through each answer and add to the appropriate variable. Now if you need to randomize the answers, that might not be as feasible.

  8. Hi Rohmat: I originally chose 600 by 450 as a size, because that is a common widget or ad size. If you changed the page-wrap to height: 550px, you’ll also have to change how many pixels the form moves when an answer is clicked.

    Find the following line in test.php:
    $mt = $mt - 430;
    You might try changing this to 530, but test to see how it looks. Find the value that works for your particular changes.

  9. Hi Rohmat,

    In this quiz, the label for each radio button is laying over the width and height of each radio button input. If you look at the CSS Part #2, you’ll see explicit CSS declarations for height, width, and background-color. (Most browsers will let you find this in the page by using Crtl+F, and then typing in #quiz label).

    Be sure to give each label a background-color for the :hover state as well.

    I hope this helps.

  10. John this is very cool. We are creating a new web site and will use your code. We do want some pretty serious changes for a personalized template. What are your rates to sat, work with us for about 5 hours of your time?

    Rory

  11. Hi John,
    Cool quiz, I was wondering how I would go about creating sub questions? What I want to do is ask certain questions based on the previous answer? For example if the user selects answer ‘A’ then ask ‘question A’ else ask ‘question B’

  12. Hi Anthony:

    That’s a good question, and it depends on how many forks you plan on taking with your questions. The first step might be to map out all the possible paths quiz takers would be able to encounter and assess how complex you want this to be.

    Off the top of my dome, the easiest way to take this open source quiz and give it that flexibility might be to output different questions and possible answers using if-then logic and echo statements.

    A pseudo-code example could be:

    if question 1 response = A
    then question 2 = echo "Alternate question 1"
    else question 1 response = B
    then question 2 = echo "Alternate question 2"

    And so on down the line. Naturally, you’d have to tailor this to your specific needs and test it out. This quiz is much simpler than that, with static questions and a grading function at the very end.

    I hope this helps point you in the right direction.

  13. Hi John i was wondering if you could help me out, I’m having issues with the grade.php output it seems to be displaying all of the possible outcomes and not just the highest total. Any help would be appreciated thanks.

    Grant.

      1. I haven’t put it up anywhere yet. Do you have any suggestions where I can upload it for free for you to have a look? So far I’ve just changed the names and that nothing too major I have jQuery downloaded also.

        Thanks, Grant.

          1. That could be it then, thank you i will have a try using one of them then report back.

            Thanks, Grant.

  14. Hi there John,

    Nice quiz I’ve been using it as a guide for my PHP exam at school. I need to create a project and I decided an test.
    Anyways I don’t understand why the .fwrd class isn’t working anymore, could it be because I have changed the form’s pixel dimension? how can I fix it?

    1. Hi Ben:

      Can you what you mean by “not working”?

      If it is not advancing at all, make sure you have included a link to your jQuery file.

      If the proportions are not correct because the height of the form has changed, you will have to adjust that to fit your new dimensions.
      This will be the line you are looking for in test.php

      $mt = $mt - 430;

      If the measurement is off on frame advance, adjust the number being subtracted in the $mt variable.

      If this is not what is wrong, let me know, and I will try to help.

      1. Hi there,
        i’ve tried to change $mt variable but nothing has changed, so i tried to download all of your original source code and neither does it work, when i click on an answer it doesn’t do anything..(the query doesn’t get launched)…what can i do? thanks for the help

        1. Hi Ben:

          If your quiz is on a server running PHP, and you can make it to the test.php page, and on clicking an answer, nothing happens, I would check to make sure that jQuery is linked correctly.

          The only reasons I can think of the frames would not advance would be a problem with jQuery.

          Without knowing what else you have tried, it is difficult to diagnose further.

  15. Great tutorial! I noticed I can’t click the “Take the Quiz” button in IE10 (it does work in IE11). It doesn’t highlight or change the pointer to show it’s a click-able button. Same is true of the Share buttons and Built by link. How do I go about adjusting the code to get it to work in older IE versions?

    1. Hi Lindsey:

      I couldn’t replicate the bug you are experiencing. What browser/device combo are you getting this with? I can investigate further.

      If you want to troubleshoot on your own, you can add pointer: cursor; to show clickable elements. This is already there, so the other things that may affect that may be z-index or display. Try increasing the z-index value of the problem links and see if that makes your particular setup work.

      I tested this on Windows 8 w/ IE 11 and Windows 7 w/ IE 9 and 10, and couldn’t find the same bug.

      1. I tested on Windows 7 Enterprise w/ IE 10 and I can’t click on anything in the quiz display.

        I also tested on Windows 7 Professional w/ IE11, Firefox 37.0.2, and Chrome. All work.

          1. Hi Lindsey:

            I’m not familiar with any inconsistencies between Windows 7 and Windows 7 Enterprise with IE10. I don’t have access to Windows Enterprise, so my testing was limited to regular Windows 7 /IE10 and I couldn’t replicate your bug.

            If you’re comfortable editing the CSS, you should make sure the z-index for the buttons is above the surrounding elements.

            Clickable elements are already set to cursor: pointer; on hover, so z-index would be the first place I would look in debugging.

            The

        1. Hi Lindsey:

          I found the source of your problem. It wasn’t in the quiz or the iframe, but in another feature on this site.

          I debugged this issue for IE9 and IE10 on this site, and the iframe on this page works.

          Basically, there was a page element stacked above the iframe in IE9 and IE10, but in no other browsers. This prevented you from clicking on any quiz elements.

          Thanks,
          John

      2. Ok, I’ll set something up. I noticed your site (this page) wasn’t working properly in IE10. I hadn’t even gotten as far as creating my own yet.

        1. Ahhh — now I see what issued you’re having. It looks like there is a bug with some embedded iframes in IE10. It works — until you embed it in another site.

          I’ve been looking into it this morning, but haven’t found the solution yet. I’ll send you an email when I do figure it out.

  16. Dear John!
    Thank you a lot for your short tutorial. It is really useful. I am economist and try mastering my skills in web-development and Python, so I find your site very helpful.
    I am gonna use your tips as a basis for my little project (I try to create something like https://www.politicalcompass.org/test, but do not get how to create a final graph with results).
    Will be watching your site further.

    1. Hi Dima:

      Thanks for reading. On the Political Compass test, it looks like on the results page, the top part is there on all results. For the graph part, the graph could just be a background image of a certain width and height. For where they place the dot, they compute some questions for the x-axis and some for the y-axis, so when the results come back, the grading part just says “put the dot so far to the left/right and top/bottom” based on those scores.

      At least, that’s how I would replicate it. I hope this helps!

  17. Hi Shweta:

    You will need to run this in a hosting environment with PHP installed. You will also need JavaScript enabled, as this quiz uses jQuery to advance frames. Make sure you are correctly linking to the CSS. This will set the dimensions of the bounding box, and keep the other questions off screen.

  18. Você pode não entender meu comentário , mas fico muito agradecido pela explicação, cabe a mim estudar agora.
    Muito Obrigado…

  19. Olá Cezar ! Graças ao Google Translate , posso undertand seu comentário. Estou feliz que você encontrou algum uso deste tutorial. Deixe-me saber se isso faz sentido para você. Desejo-lhe sucesso em seu estudo . Obrigado por dizer Olá !

  20. Hi John! A very clever way to create the “step wizard” feeling without actually having to use jquery steps etc. The only question i have is, how to make it responsive without using static height and width? Or is it even possible?

    I have made a few changes to the code, and it works great on big screens where i can display the full height. But im stuck trying to make it responsive. I beg you to help me here as we are creating this landingpage for a client.

    Link to our project: http://bilbutikk1.zapto.org/ (Warning: The website is in Norwegian language).

    Thanks!

  21. Hi Knut:

    It looks like you are doing a great job so far. You can absolutely make this responsive: so long as you keep a few things in mind.

    1. The height of each question frame must stay the same on each screen size.
    2. It is best if you have the same number of answers for each question.
    3. You can adjust anything besides the static height of each frame.

    I have actually redone this template a few times for a specific client partner, as an iframe.

    (Yes, I know iframes are not normally responsive, but this partner puts the code into a special portal that renders device width and height as the native window. So, basically black magic).

    Keep on the solution path you are currently on, and keep it in the page, like you are doing.

    Pick a number of answer choices (three, four, or five), and stick with that, it will make things easier. Adding more will mess you up on smaller screens, as you will make those frames taller, and you won’t be able to advance the frame like you want to.

    This actually does use jQuery, but that’s okay 😉

  22. Hey..John, superb bro. fantastic code u done it.but i wanna to store the questions in a database and fetch from it??? How is it possible??

  23. Hi Ben:

    This quiz isn’t built to store data in a MySQL database. You could certainly use this as a starting point, but you’d have to add more code infrastructure to this to store data permanently.

  24. Hi John,
    We’re looking to build something where people have points to distribute across multiple options and then the results show the top 2 answers. Any thoughts?

    ~Jaime

  25. Hi Jaime:

    You can use this code as a foundation to expand on to realize your idea. You already have the ability to assign different point values to specific answers in grade.php. Just decide what points correlate where, and assign values.

    For displaying the top two answers, you’ll have to modify the display code further. It’s currently set to compare the totals of the four options and depending on which one has the highest score, it displays the corresponding result. This is in the code block there that is fourth up from the bottom in the tutorial.

    You’ll have to have someone help you with this and adjust it to where it displays your top two answers instead of one.

    Thanks,
    John

  26. Hi! How would I make the quiz answers of equal weight? For example if the player answered 2 questions with ‘A’ and 2 questions with ‘B’ and I want both possible responses to be printed. Thanks in advance!

  27. Hi Lyndsey:

    There are two parts to your questions, so let me answer each part. First, you want to weight every answer the same. To do that, at the top of the grade.php file, you can set each answer to add a certain amount of points to whichever outcome you want.

    So, you can set each question to just give one point each to your A, B, C, or D questions as you see fit. Go ahead and open your code editor and make those changes.

    Next, go to the bottom of grade.php and you’ll see the place where it does comparisons and then displays whichever results screen the points comparison comes up with. (Part of the reason I made the point scoring uneven was to avoid having to go to tie-breakers).

    The part that displays the results screens is inside of <div class="reults-overlay"></div>

    What you’d want to do is add a final elseif statement(s) for when results points match exactly.

    Then you would echo out the HTML for that custom screen for your tie results.

    Feel free to break the code apart and do something totally new with it, that’s what it’s there for! 🙂
    I would love to see the final results when you launch it onto the web.

  28. Hi, is there a way to select how many questions you would like to answer, for example if you only want to answer 2 then you can select 2 or 4 and so on?

  29. Hi Paul:

    If I understand your question correctly, you’d like a way to select how many questions you’d like to answer on each frame.

    This tutorial is more developer-centric, but you can certainly modify the source code to change how many questions appear on each slide, or even the number of questions. You’ll have to modify the original code, and get your hands dirty, but it’s very possible.

  30. Hi John,
    Great code! Thank You So Much for sharing this!

    I have a question… How to add more results? I added one more question so there are altogether 6 questions, and I would like to add more results, from 4 to 8 different results. Is that possible?

    So far there are 4 results, and I understand that you compared the ABCD scores and use that to differentiate the results:

    
    if ($totalA > $totalB && $totalA > $totalC && $totalA > $totalD)
    
    

    Is it possible to increase the results page to 8 different metal bands?
    Thanks Tons!

    Kenneth

  31. Hi Kenneth:

    You can indeed add more results to this quiz. I just left it to four bands, because it is easier to manage than six or eight or ten results.

    You’ll want to add your extra variable for the totals to grade.php If you have eight results, that would look like this:

    
                $totalA = 0;
                $totalB = 0;
                $totalC = 0;
                $totalD = 0;
                $totalE = 0;
                $totalF = 0;
                $totalG = 0;
                $totalH = 0;
    
    

    Now, the tricky part is you will have to figure out how you want to weight the responses in your quiz to deliver the results you want. This is trickier than it sounds, and gets tougher the more results you add to the mix, unless you have some heavily contrasting results.

    For example, if you had a eight results screens with bands ranging from say, Enuff Z’Nuff on the low end and Slayer on the high end, you could add “heaviness points” for heavy answers, and add nothing (or add negative points) for soft answers.

    You will need to add the new formulas to the next section in grade.php. What will each answer add to each of the eight variables?

    Then at the end of the grade.php file, you will need to add the new elseif statements and HTML to render the results screens.

    You are adding the same types of patterns that already exist in the two main PHP files (test, grade). The hardest part will be figuring out how to weigh the answers to give you the results you are expecting each and every time.

    Thanks,
    John

  32. Hi John, I just downloaded your source code and performed it in the browser, and that is so amazing and helpful for a newbie or beginner in this field like me. But in the PHP source code…can we change points like 1.17, 1.15 into other numbers? What do we have to consider when changing them ?

  33. Hi Ilham:

    Yes, you absolutely can change the point values in grade.php. Here are the things you will need to consider when changing the scoring values:

    Consider how much weight you want to give to each answer. Does each answer fit neatly into a results screen?

    In my original quiz, some answers give points to different results. You may want to make the answers for each question correlate more closely to a specific result.

    One additional thing to consider is what happens if you have a “tie vote”. For example, what happens if there are two votes for “A”, two votes for “B”, and one vote for “C”?

    How do you break that tie? How do you determine what shows on the results screen?

    This is why the points in my original grade.php are uneven, and not just integers or round numbers. I wanted to make sure there would always be a clear winner for the final results screen.

    Best of luck!

  34. Very nice tutorial!

    But I’d suggest making a switch case instead of using ‘if’.

    
    switch ($answer1) {
        case "A":
            
            break;
        case "B":
            
            break;
        case "C":
            
            break;
        case "D":
        break;
    }
    
    
  35. Hello!

    This is fantastic stuff! I have implemented this and modified it some. I want to make one more modification that seems like it should be simple but isn’t so far:

    I want to have a text field where a user has to fill out their email address before they submit the quiz to get their results. I will worry about storing the email address and the result. My issue is getting the Text Input field to even show up. I have modified things so let me know if you need to see my Stylesheet.

    Thanks for this excellent starting point!
    -Sam Gibson

  36. Hi Sam:

    To add a field where people must enter their email address, you could add a form to the last screen and have the email address sent to you. Additional PHP and functionality would need to be added to this basic quiz.

    You may also want to look at validating the email address before having the Submit button appear. Again, you would need to add more functionality to this quiz to make that work.

    Thanks,
    John

  37. Hello!

    This idea and the code helped me a lot as a beginner. I’ve implemented it on my website for a school project and changed the PHP a little bit. Thank you so much for sharing this and good luck with your further works!

    ~Daria

  38. Hi Daria:

    Thanks so much for trying it out! I used this code base for four or five client projects that I did a few years ago when I was first starting out. I’m glad you got some use out of it as well. 🙂

    I would love to see your finished project!

    Best regards,
    John

  39. Very useful this code for me!Thank you…but i have a problem! It only loads the first question and nothing else. I have downloaded the code from github and install xampp…what should i do?
    Thank you in advance!

  40. Hello sir,

    I am developing a career counseling system using PHP, MySQL and Bootstrap.

    All I need to know is that can I connect my own database to your system, i.e. for the questions, and secondly my system needs to have recommendation as your system does, so kindly specify the code for the recommendation.
    I really need your help because I have to do my final year project. Thank you.

    1. Hi Shariq. I’ve just read your comment and we actually have the same kind of project. Mine is to counsel also a students using personality questionnaires and give recommendations. So we’re exactly the same. I’m wondering if you have finished your project since you’ve commented it a year ago. If you did, kindly help me please. I’m having a problem on this because we only have 1 month to finish this project. If you don’t mind, kindly send me the source code of your project please. I’m begging for your help. I would appreciate it a lot.

      Thank you in advance!

  41. Hi Shariq:

    This code doesn’t connect to MySQL or store the results in a database. This particular code evaluates the answers and assigns a score for each answer. Whichever answer has the most points is the recommendation at the end.

    You would have to do some extra work to store the values in MySQL.

    Thanks,
    John

  42. Thank you for posting this code. Here’s what I made using your code as a starting place: What Breed of Cat Are You? cats.elmvalefarm.com

  43. Hi John, I was wondering what changes I would need to make to either the CSS or the divs in the test.php section to get the potential answers to be side by side instead of above/below each other. I plan on adding images to the answers as well but I think I can handle that if I can make this change correctly first.

    1. Hi Tim:

      It might take some experimentation to get the effect you’re looking for, but I would probably start with making the clickable area/answers inline-block, make the width half what it is now, and position them to where they line up next to one another. It will likely be more complicated than that, but that’s where I would start.

      Thanks,
      John

  44. woow your code helped me here in SA . but i have a question. im designing a quiz which the answers are not numbers but strings …at the end i need to determine most dominating string answer then it becomes the right answer

    1. I don’t know the exact thing you are trying to do, but this may help. The answers in this quiz are buttons that correspond to numerical values.

      Ahead of time, I know what answers correlate to the results. So each question is weighted to a result. Whichever “bucket” gets the most points ends up as the result (A, B, C, or D).

      If someone has to type in strings, you’re out of luck with this tutorial. But if you have preset multiple choice questions, then that’s how you would do it.

      Each answer weights more heavily to one of the four end results. Hope that helps.

Join the Conversation

Your email address will be kept private. Required fields marked *.