The Web Standards Model

Coding explainers for web design students

Coding explainer source code

The three files that make up the opening times widget are set out below. Simply copy and paste the code into your code editor to try it for yourself. All three files should be saved to the same folder. The HTML should be saved as index.html, the CSS as style.css, and the JavaScript as script.js.

index.html — the structure layer

<!DOCTYPE html>
<html lang="en">
   <meta charset="utf-8">
   <title>Opening times | Coding Explainers</title>
   <link rel="stylesheet" href="style.css"> <!-- link to CSS -->
   <link rel="preconnect" href="">
   <link rel="preconnect" href="" crossorigin>
   <link rel="stylesheet" href=";500&display=swap" >
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <section id="widget"> <!-- open widget -->
      <h1>Opening times</h1>
         <dd>9:00am to 5:00pm</dd>
         <dd>9:00am to 5:00pm</dd>
         <dd>9:00am to 5:00pm</dd>
         <dd>9:00am to 5:00pm</dd>
         <dd>9:00am to 8:00pm</dd>
         <dd>8:00am to 6:00pm</dd>
   </section> <!-- close widget -->
   <footer>Written for MA Web Design &amp; Content Planning by David Watson</footer>
   <script src="script.js"></script> <!-- link to JavaScript -->

Notes: The HTML markup is kept as simple as possible, but forms a complete, well-formed document that validates without errors or warnings. The markup includes links to both the style.css file and to the script.js file. Note that the one difference between this markup and that shown on the explainer page is that the heading for our widget is <h1> here. That's because the context in this document is different from that in the main document. In the main document, the heading is marked up as <h3> because that is consistent with the document outline. In this document, there is no other <h1>, so it is correct to mark up our widget header as <h1>. If you want to use this widget in another document, make sure that you change the heading level, so it is consistent with its context.

The one area of markup that is not as minimal as it could be is the <head> section of our document where there are three additional links to Google Fonts. The reason I've chosen to do this is that the type design of our widget is quite important — it conveys the information about today's opening times. I have therefore left nothing to chance and am using webfonts to ensure that the widget retains its visual integrity.

style.css — the presentation layer

/* == Minimal reset for a simple document == */
html {
	box-sizing: border-box;
*, *::before, *::after {
	box-sizing: inherit;
	padding: 0;
	margin: 0;

/* == Page styling == */
body {
	font-family: Roboto, Arial, Helvetica, sans-serif;
	font-weight: 300;
	color: #333;
	background-color: #ddd;

/* == The organism container == */
#widget {
	background-color: #fff;
	width: 410px;
	padding: 0 0 2.0rem;
	border-radius: 14px;
	margin: 4.2rem auto 0;
	box-shadow: 0 0 14px #666;
	transition-duration: 400ms;
#widget:hover {
	transform: scale(1.02);
	box-shadow: 0 0 28px #666;
	/* Using Material Design principles
    to make the card appear to move
    towards the viewer rather than
    simply getting bigger */

/* == The organism children == */
#widget h1 {
	font-family: 'Fira Sans Condensed', Arial, Helvetica, sans-serif;
	font-weight: 600;
	font-size: 3.2rem;
	text-align: center;
	background-color: #eee;
	padding: 1.2rem 0;
	border-top-left-radius: 14px;
	border-top-right-radius: 14px;
#widget dl {
	/* Using grid to layout the definition list */
	display: grid;
	grid-template-columns: 150px 200px;
	width: 350px;
	font-size: 1.2rem;
	line-height: 2;
	margin: 1.7rem auto 0;
#widget dt, #widget dd {
	padding: 0 0 1px 20px;
	border-bottom: 1px dotted #888;
#widget dt:first-of-type, #widget dd:first-of-type {
	border-top: 1px dotted #888;
.today, .today + dd {
	/* This class is added by JavaScript */
	font-weight: 500;
	color: #000;

/* == The document footer == */
footer {
	text-align: center;
	font-size: 0.8rem;
	margin: 2.0rem 0;

Notes: The CSS rules for our sample page include a minimal browser reset. Ordinarily we would use something more comprehensive such as the Meyer Reset, but this document is very simple, and we can cover all our reset requirements in a more compact form. In addition, we have added some simple page styling for <body>, and the styling for the heading has been changed to #widget h1 (see note above). Finally, I have added a footer to the document, so we have a style rule for that. Other than those few differences, the CSS is identical to that shown on the explainer page.

script.js — the behaviour layer


// get the day number from a new date object
// assign to a variable
let today = new Date().getDay();

// Sunday is the first JavaScript day but it's
// the last day in our list so change 0 to 6
// and decrement all other day numbers so they
// match with the node list indexes
if (today === 0){
	today = 6;

// select all the description term elements
// assign to a constant
const dts = document.querySelectorAll('dt');

// use the day number (today variable) to add
// the 'today' class to the appropriate dt
// element so it and the adjacent dd can be
// styled in CSS
dts[today].className = 'today';
// node lists begin at 0, so day 1 in our list
// (Monday) will be node 0

Notes: The JavaScript is identical to that shown on the explainer page. Once you have saved all three files and have the document open in your browser, check that everything is working as expected. If the widget is correctly styled, the CSS is working, and if today's opening times are highlighted, the JavaScript is also working. You have successfully created a document that conforms to the web standards model by ensuring that all three technology layers are kept apart but work perfectly together.