This example implements a responsive website design using CSS, HTML, and JavaScript. The layout has two variations, suitable for both desktop browsers and mobile devices.
Basic setup
Begin with index.css and index.html from the Grid CSS holy grail layout.
Basic setup
Layout design
Content outline
Subcontent outline
Layout diagram
HTML elements
Flexbox
Implementation
CSS
JavaScript
HTML
Appearance
Landscape/desktop view
Portrait view
Content outline
Subcontent outline
Layout diagram
CSS
JavaScript
HTML
Landscape/desktop view
Portrait view
Place index.css and index.html in the same folder. Open index.html in a web browser.
Layout design
Our example shows one way to create the home page for a fictional business/service. The home page is the first thing the user sees when visiting the site.
Content outline
The primary information to appear on the home page is listed below.
- Name/logo — The identity of the business/service, located in the header, left justified.
- Announcements — The first section of the main body. The user sees this information above the fold, before seeing items for sale. This space may contain important updates, limited-time deals, or recommended items.
- Items for sale — The name, description, price, and current inventory of various items for sale.
- Upcoming events — Information about future business-related events where the user may want to participate.
- Message of the day — Rotating “flavor” content, such as a quiz or an inspirational quote.
- Footer — Authorship and/or Copyright information.
Subcontent outline
The following links and supplemental information are accessible on the home page, encouraging the user to explore. This subcontent may appear differently in the layout, depending on the user’s viewing device.
- On a desktop browser or a mobile device in landscape mode, all subcontent is displayed.
- On a mobile device in portrait mode or a desktop browser window resized narrow, the side panels disappear. Subcontent is repositioned or available in a menu.
The following subcontent is accessible on the home page.
- About — A link to a separate identity statement page. In desktop/landscape mode, it appears in the header, justified right. In portrait mode, it is a menu item.
- Contact — A link to a separate page with contact information of the business/service, such as a postal address, e-mail address, phone number, etc. In desktop/landscape mode, this link appears in the header, justified right. In portrait mode, it is a menu item.
- Sections — Links to other sections of the website. In portrait mode, each section link is a menu item.
- Partners — Links to partner businesses/services. In desktop/landscape mode, partners are displayed in the right panel. In portrait mode, they are displayed at the bottom of the main body.
Layout diagram
This design has two layout variations.
- One layout for devices in landscape mode.
- One layout for devices in portrait mode.
Desktop browsers are compatible with both, but primarily view the landscape layout.
The layouts are diagrammed as follows.
HTML elements
In this design, the following HTML elements are each assigned a specific layout purpose.
Flexbox
CSS Flexible Boxes (abbreviated as Flexbox) is a set of special CSS attributes. It creates elements that expand or contract (“flex”) automatically, depending on their content and layout context.
An element with attribute display: flexbox is a flexbox container. If the container shape changes (e.g., if the user resizes the browser window, or rotates their mobile device), its child elements change their relative position and/or shape. The elements flex in one dimension, either horizontally (in a row) or vertically (in a column).
The holy grail layout has five major areas that flex.
- The header and footer flex horizontally (flex-direction: row), left-to-right.
- The left panel, main body, and right panel flex vertically (flex-direction: column), top-to-bottom.
In portrait mode, the panels are hidden. The menu is implemented as a flex column.
Implementation: CSS, JavaScript, and HTML
CSS: index.css
/* element styles */
- { margin: 0; /* by default, all elements (selector *) have no margin / } html { width: 100%; / 100% width of parent (root) element / height: 100vh; / 100% height of viewport / background: rgb(0, 0, 0, 0.1); / 10% black / font-size: 1.0em; / our root font size / font-family: Arial, Helvetica, sans-serif; / default font / } body { min-height: 100%; } section { padding: 0.5rem; flex-grow: 1; / in a flexbox, sections expand along flex axis / } h1 { / Website name in header / font-size: 2.0rem; font-weight: normal; } h2 { / About, Contact / font-size: 1.25rem; } h3 { / Section headings / font-size: 1.2rem; padding: 0.5rem; } h4 { / Section item title / font-weight: normal; padding: 0.5rem; } p { / Paragraph styling / padding: 0.5rem; } a:link, a:visited { / anchor links, and visited anchor links / color: black; text-decoration: none; / disable underline / } a:hover { / when anchor link is hovered / color: rgb(25, 25, 25); } a:active { / when anchor link is clicked / color: rgb(96, 96, 96); } / component styles / #container { display: grid; height: 100%; grid-template-columns: [left] 10rem auto 10rem [right]; grid-template-rows: [top] 5rem auto 5rem [bottom]; grid-template-areas: “head head head” “panleft mainbody panright” “foot foot foot”; } #header { grid-area: head; / corresponds to grid-template-area / background: rgb(0, 0, 0, 0.2); / 20% black / display: flex; flex-direction: row; justify-content: space-between; align-items: baseline; / site name and nav item text aligns baseline / padding: 1.0rem; } #panel { / if element id=“panel” / display: flex; / this element is a flexbox parent / flex-direction: column; / its child elements flex vertically / padding: 0.5rem; background: rgb(0, 0, 0, 0.1); / 10% black / } #panel.left { / if element id=“panel” and class=“left” / grid-area: panleft; / this element fills a grid area / } #panel.right { / if element id=“panel” and class=“right” / grid-area: panright; / this element fills a grid area / } #footer { / if element id=“footer” / grid-area: foot; / this element fills a grid area / display: flex; / this element is a flexbox parent / flex-direction: column; / its child elements flex vertically / justify-content: center; / horizontal center footer content / align-items: center; / vertical center footer content / padding: 0.5rem; background: rgb(0, 0, 0, 0.2); } #mainbody { / if element id=“mainbody” / display: flex; / this element is a flexbox parent / flex-direction: column; / its child elements flex vertically / grid-area: mainbody; justify-self: center; / fixed-width mainbody always centered / width: 100%; min-width: 22.5rem; / mainbody width can’t go < 22.5rem / } div#panel, div#mainbody { / extra space under header / padding-top: 0.5rem; } #partners, #sections { / if element id=“partners” or id=“sections” / display: flex; / this element is a flexbox parent / flex-direction: row; / its child elements flex horizontally / flex-wrap: wrap; / its child elements can wrap to next line / align-content: flex-start; / child elements start in upper left / } #partners.wide { / if element id=“partners” and class=“wide” / display: none; / by default, do not display this element / } #menu { position: absolute; / menu position unaffected by other elements / right: 0; / zero pixels from the right boundary / background: rgb(239, 239, 239); border: 0.15rem solid rgb(0, 0, 0, 0.4); visibility: hidden; / visibility property supports transitions / opacity: 0; / opacity + visibility transition = menu fade effect / z-index: 1; / ensure menu appears over all other content / } #menuitems { / menu is implemented as a flexbox container / display: flex; flex-direction: column; padding: 1rem; } #menuitems h3 { border-top: 0.15rem solid rgb(0, 0, 0, 0.1); / light horizontal rule / } #menuitems .menusec { border-color: rgb(0, 0, 0, 0.25); / darker horizontal rule / } #menuitems h3:hover { background-color: rgb(0, 0, 0, 0.1); / gray of rollover menuitems / } .menubutton { text-align: right; cursor: pointer; / indicates it can be clicked like a link / user-select: none; / user cannot select the button as text / } #menuitems .alignright { text-align: right; / right-aligned menu item text (unused) / } #header h1.menubutton { display: none; / in default view (landscape), hide menu button / border: 0.15rem solid rgb(0, 0, 0, 0); / (invisible) alignment shim / } #header .placeholder { / this invisible button is rendered when menu / color: rgb(0, 0, 0, 0); / button is hidden, so header height matches. / user-select: none; / user can’t select text of invisible button / } .sectionlink, .partnerlink { border-radius: 0.25rem; / give this element a slight rounded edge / font-weight: normal; font-size: 1.1rem; padding: 0.5rem; width: 7rem; / fixed width for these items / margin-bottom: 1rem; / slight margin for readability / background: rgb(0, 0, 0, 0.1); } .sectionlink:hover, .partnerlink:hover { background-color: rgb(0, 0, 0, 0.065); / brighten bg on mouse hover / } .partnerlink { height: 7rem; / partner elements are additionally fixed height / } .partnerlink.wide { margin: 0.5rem 1rem 0.5rem 0; / margins for spacing if they wrap / } .clickable-area { / use whenever a clickable area excludes margins / height: 100%; / clickable area spans height of parent / } .eventitem, .announceitem, .motditem { margin-bottom: 0.5rem; / slight margin for readability / } .title { / e.g., “Open for business” / font-style: italic; font-weight: normal; font-size: 1.1rem; } .date { / e.g., January 1, 2021 / font-style: italic; font-size: 0.9rem; padding: 0 0 0 0.5rem; color: rgb(0, 0, 0, 0.5); } .navitem { / About, Contact / font-weight: normal; padding: 0 0.5rem 0 1rem; } .headspace, .panspace, .footspace, .bodyspace { flex-grow: 1; / these elements expand on flex axis to fill space / } / table styles (“items for sale”) / table { border-collapse: collapse; / pixel-adjacent table cells / width: 100%; margin-bottom: 1rem; } th { text-align: left; } tr { margin: 4rem 0 0 0; border-bottom: 0.15rem solid rgb(0, 0, 0, 0.2); / horizontal rule / } td, th { padding: 0.5rem; vertical-align: top; } td.price { white-space: nowrap; / white space in price does not wrap line / } td.qty, th.qty { text-align: center; } span.perunit { opacity: 0.5; } / responsive styles applied in portrait mode / @media screen and (max-width: 45rem) { / if viewport width < 45rem / #panel.left { grid-column-end: left; / panel grid area shrinks to nothing / } #panel.right { grid-column-start: right; / panel grid area shrinks to nothing / } #partners.tall { display: none; / hide partners in panel (overwrites display: flex) / } #partners.wide { display: flex; / show partners in body (overwrites display: none) / } #panel, / these disappear from layout / #header .placeholder, .navitem { display: none; } #mainbody { grid-column-start: left; / mainbody now starts at left edge / grid-column-end: right; / mainbody now ends at right edge / } #header h1.menubutton { / display the header menu button / display: inline; / overwrites display: none */ } }
JavaScript: index.js
This JavaScript implements the menu show/hide toggle, which triggers when the menu button is pressed.
function menuToggle(state) { var ele = document.getElementById(‘menu’); switch(state) { case ‘show’: ele.style.opacity=1; ele.style.color=‘rgb(96, 96, 96)’; ele.style.visibility=‘visible’; ele.style.transition=‘visibility 0s, opacity 0.3s’; break; case ‘hide’: ele.style.opacity=0; ele.style.color=‘black’; ele.style.visibility=‘hidden’; ele.style.transition=‘visibility 0.3s, opacity 0.3s’; break; } }
HTML: index.html
Announcements
Open for business
Jan. 15
Renovations of our new storefront are complete, and we're open for business.
Items for sale
Item | Description | Price | Qty |
---|---|---|---|
Milk | Good source of calcium. | $2 / half gal. | 3 |
Eggs | Great for breakfast and baking. | $4 / doz. | 6 |
Whole chicken | Perfect for roasting. | $5 / lb. | 4 |
Upcoming events
Cider Fest
October 20, 2pm–6pm
Celebrate the season with fresh-pressed cider from our orchards.
Bread baking workshop
December 13, 9am–noon
Learn how to create and cultivate a sourdough starter.
Message of the day
Eat better food. Support your local farm stand.
Our friends
Appearance
In landscape view, the panels are displayed.
Landscape/desktop view
Portrait view
In portrait view, the panels are hidden, and the menu is active. Partners are displayed as the final section of the main body.
Related information
- How to start in HTML and web design.
- How to create a holy grail website layout using CSS Grid.
- How to create a website using Node.js and Express.
- How to connect a Node.js web app to an SQLite database.
- Complete information and help with HTML.
- HTML and web design help and support.