diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index 8c08fbe6d4d..75a4bfd3f63 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -1857,7 +1857,12 @@ "ioby": { "title": "87", "intro": [] }, "dyvj": { "title": "88", "intro": [] }, "rjsv": { "title": "89", "intro": [] }, - "txmt": { "title": "90", "intro": [] }, + "lab-tribute-page": { + "title": "Build a Tribute Page", + "intro": [ + "For this lab, you will build a tribute page for a subject of your choosing, fictional or real." + ] + }, "fnde": { "title": "91", "intro": [] }, "gxjm": { "title": "92", "intro": [] }, "swpl": { "title": "93", "intro": [] }, diff --git a/client/src/pages/learn/front-end-development/lab-tribute-page/index.md b/client/src/pages/learn/front-end-development/lab-tribute-page/index.md new file mode 100644 index 00000000000..39334474f5b --- /dev/null +++ b/client/src/pages/learn/front-end-development/lab-tribute-page/index.md @@ -0,0 +1,9 @@ +--- +title: Introduction to the Tribute Page +block: lab-tribute-page +superBlock: front-end-development +--- + +## Introduction to the Tribute Page + +For this lab, you will build a tribute page for a subject of your choosing, fictional or real. diff --git a/curriculum/challenges/_meta/lab-tribute-page/meta.json b/curriculum/challenges/_meta/lab-tribute-page/meta.json new file mode 100644 index 00000000000..5ed51820dd4 --- /dev/null +++ b/curriculum/challenges/_meta/lab-tribute-page/meta.json @@ -0,0 +1,16 @@ +{ + "name": "Build a Tribute Page", + "blockType": "lab", + "isUpcomingChange": true, + "usesMultifileEditor": true, + "dashedName": "lab-tribute-page", + "order": 90, + "superBlock": "front-end-development", + "challengeOrder": [ + { + "id": "bd7158d8c442eddfaeb5bd18", + "title": "Build a Tribute Page" + } + ], + "helpCategory": "HTML-CSS" +} diff --git a/curriculum/challenges/english/25-front-end-development/lab-tribute-page/bd7158d8c442eddfaeb5bd18.md b/curriculum/challenges/english/25-front-end-development/lab-tribute-page/bd7158d8c442eddfaeb5bd18.md new file mode 100644 index 00000000000..35aa65db792 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/lab-tribute-page/bd7158d8c442eddfaeb5bd18.md @@ -0,0 +1,435 @@ +--- +id: bd7158d8c442eddfaeb5bd18 +title: Build a Tribute Page +challengeType: 14 +demoType: onClick +dashedName: build-a-tribute-page +--- + +# --description-- + +**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab. + +**User Stories:** + +1. Your tribute page should have a `main` element with a corresponding `id` of `main`, which contains all other elements. +1. You should see an element with an `id` of `title`, which contains a string (i.e. text), that describes the subject of the tribute page (e.g. "Dr. Norman Borlaug"). +1. You should see either a `figure` or a `div` element with an `id` of `img-div`. +1. Within the `#img-div` element, you should see an `img` element with a corresponding `id="image"`. +1. Within the `#img-div` element, you should see an element with a corresponding `id="img-caption"` that contains textual content describing the image shown in `#img-div`. +1. You should see an element with a corresponding `id="tribute-info"`, which contains textual content describing the subject of the tribute page. +1. You should see an `a` element with a corresponding `id="tribute-link"`, which links to an outside site, that contains additional information about the subject of the tribute page. HINT: You must give your element an attribute of `target` and set it to `_blank` in order for your link to open in a new tab. +1. Your `#image` should use `max-width` and `height` properties to resize responsively, relative to the width of its parent element, without exceeding its original size. +1. Your `img` element should be centered within its parent element. + +**Note:** Be sure to link your stylesheet in your HTML and apply your CSS. + +# --hints-- + +You should have a `main` element with an `id` of `main`. + +```js +const el = document.getElementById('main') +assert(!!el && el.tagName === 'MAIN') +``` + +Your `#img-div`, `#image`, `#img-caption`, `#tribute-info`, and `#tribute-link` should all be descendants of `#main`. + +```js +const el1 = document.querySelector('#main #img-div') +const el2 = document.querySelector('#main #image') +const el3 = document.querySelector('#main #img-caption') +const el4 = document.querySelector('#main #tribute-info') +const el5 = document.querySelector('#main #tribute-link') +assert(!!el1 & !!el2 && !!el3 && !!el4 && !!el5) +``` + +You should have an element with an `id` of `title`. + +```js +const el = document.getElementById('title') +assert(!!el) +``` + +Your `#title` should not be empty. + +```js +const el = document.getElementById('title') +assert(!!el && el.innerText.length > 0) + +``` + +You should have a `figure` or `div` element with an `id` of `img-div`. + +```js +const el = document.getElementById('img-div') +assert(!!el && (el.tagName === 'DIV' || el.tagName === 'FIGURE')) +``` + +You should have an `img` element with an `id` of `image`. + +```js +const el = document.getElementById('image') +assert(!!el && el.tagName === 'IMG') +``` + +Your `#image` should be a descendant of `#img-div`. + +```js +const el = document.querySelector('#img-div #image') +assert(!!el) +``` + +You should have a `figcaption` or `div` element with an `id` of `img-caption`. + +```js +const el = document.getElementById('img-caption') +assert(!!el && (el.tagName === 'DIV' || el.tagName === 'FIGCAPTION')) +``` + +Your `#img-caption` should be a descendant of `#img-div`. + +```js +const el = document.querySelector('#img-div #img-caption') +assert(!!el) +``` + +Your `#img-caption` should not be empty. + +```js +const el = document.getElementById('img-caption') +assert(!!el && el.innerText.length > 0) +``` + +You should have an element with an `id` of `tribute-info`. + +```js +const el = document.getElementById('tribute-info') +assert(!!el) +``` + +Your `#tribute-info` should not be empty. + +```js +const el = document.getElementById('tribute-info') +assert(!!el && el.innerText.length > 0) +``` + +You should have an `a` element with an `id` of `tribute-link`. + +```js +const el = document.getElementById('tribute-link') +assert(!!el && el.tagName === 'A') +``` + +Your `#tribute-link` should have an `href` attribute and value. + +```js +const el = document.getElementById('tribute-link') +assert(!!el && !!el.href && el.href.length > 0) +``` + +Your `#tribute-link` should have a `target` attribute set to `_blank`. + +```js +const el = document.getElementById('tribute-link') +assert(!!el && el.target === '_blank') +``` + +Your `img` element should have a `display` of `block`. + +```js +const img = document.getElementById('image'); +const imgStyle = window.getComputedStyle(img); +const style = imgStyle?.getPropertyValue('display') +assert(style === 'block') +``` + +Your `#image` should have a `max-width` of `100%`. + +```js +const img = document.getElementById('image'); +const imgStyle = window.getComputedStyle(img); +const style = imgStyle?.getPropertyValue('max-width') +assert(style === '100%') +``` + +Your `#image` should have a `height` of `auto`. + +```js +// taken from the testable-projects repo +const img = document.getElementById('image'); +const imgStyle = window.getComputedStyle(img); +const oldDisplayValue = imgStyle.getPropertyValue('display'); +const oldDisplayPriority = imgStyle.getPropertyPriority('display'); +img?.style.setProperty('display', 'none', 'important'); +const heightValue = imgStyle?.getPropertyValue('height') +img?.style.setProperty('display', oldDisplayValue, oldDisplayPriority); +assert(heightValue === 'auto') +``` + +Your `#image` should be centered within its parent. + +```js +// taken from the testable-projects repo +const img = document.getElementById('image'), + imgParent = img?.parentElement, + imgLeft = img?.getBoundingClientRect().left, + imgRight = img?.getBoundingClientRect().right, + parentLeft = imgParent?.getBoundingClientRect().left, + parentRight = imgParent?.getBoundingClientRect().right, + leftMargin = imgLeft - parentLeft, + rightMargin = parentRight - imgRight; +assert(leftMargin - rightMargin < 6 && rightMargin - leftMargin < 6) +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + + Tribute Page + + + + + + + +``` + +```css + +``` + +# --solutions-- + +```html + + + + + + +
+

Dr. Norman Borlaug

+

The man who saved a billion lives

+
+ Dr. Norman Borlaug seen standing in Mexican wheat field with a group of biologists +
+ Dr. Norman Borlaug, third from the left, trains biologists in Mexico + on how to increase wheat yields - part of his life-long war on hunger. +
+
+
+

Here's a time line of Dr. Borlaug's life:

+ +
+

+ "Borlaug's life and achievement are testimony to the far-reaching + contribution that one man's towering intellect, persistence and + scientific vision can make to human peace and progress." +

+ -- Indian Prime Minister Manmohan Singh +
+

+ If you have time, you should read more about this incredible human + being on his + Wikipedia entry. +

+
+
+ + +``` + +```css +html { + /* Setting a base font size of 10px give us easier rem calculations + Info: 1rem === 10px, 1.5rem === 15px, 2rem === 20px and so forth + */ + font-size: 10px; +} + +body { + /* Native font stack https://getbootstrap.com/docs/4.2/content/reboot/#native-font-stack */ + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', + 'Helvetica Neue', Arial, sans-serif; + font-size: 1.6rem; + line-height: 1.5; + text-align: center; + color: #333; + margin: 0; +} + +h1 { + font-size: 4rem; + margin-bottom: 0; +} + +@media (max-width: 460px) { + h1 { + font-size: 3.5rem; + line-height: 1.2; + } +} + +h2 { + font-size: 3.25rem; +} + +a { + color: #477ca7; +} + +a:visited { + color: #74638f; +} + +#main { + margin: 30px 8px; + padding: 15px; + border-radius: 5px; + background: #eee; +} + +@media (max-width: 460px) { + #main { + margin: 0; + } +} + +img { + max-width: 100%; + display: block; + height: auto; + margin: 0 auto; +} + +#img-div { + background: white; + padding: 10px; + margin: 0; +} + +#img-caption { + margin: 15px 0 5px 0; +} + +@media (max-width: 460px) { + #img-caption { + font-size: 1.4rem; + } +} + +#headline { + margin: 50px 0; + text-align: center; +} + +ul { + max-width: 550px; + margin: 0 auto 50px auto; + text-align: left; + line-height: 1.6; +} + +li { + margin: 16px 0; +} + +blockquote { + font-style: italic; + max-width: 545px; + margin: 0 auto 50px auto; + text-align: left; +} +```