feat(curriculum): add cat photo app workshop (#55552)

Co-authored-by: Kolade Chris <65571316+Ksound22@users.noreply.github.com>
This commit is contained in:
Jessica Wilkins
2024-08-08 10:13:46 -07:00
committed by GitHub
parent 91b4f3fe97
commit f54227d581
48 changed files with 3661 additions and 58 deletions
+6 -3
View File
@@ -1696,9 +1696,12 @@
"title": "Front End Development",
"intro": ["placeholder"],
"blocks": {
"learn-basic-html-by-building-a-recipe-page": {
"title": "Learn Basic HTML by Building a Recipe Page",
"intro": ["", ""]
"workshop-cat-photo-app": {
"title": "Build a Cat Photo App",
"intro": [
"HTML stands for HyperText Markup Language and it represents the content and structure of a web page.",
"In this workshop, you will learn how to work with basic HTML elements such as headings, paragraphs, images, links, and lists."
]
},
"lab-recipe-page": {
"title": "Recipe Page",
@@ -1,9 +0,0 @@
---
title: Introduction to the Learn Basic HTML by Building a Recipe Page
block: learn-basic-html-by-building-a-recipe-page
superBlock: front-end-development
---
## Introduction to the Learn Basic HTML by Building a Recipe Page
This is a test for the new project-based curriculum.
@@ -0,0 +1,9 @@
---
title: Introduction to Build a Cat Photo App
block: workshop-cat-photo-app
superBlock: front-end-development
---
## Introduction to Build a Cat Photo App
This is the first workshop for new frontend cert.
@@ -3,7 +3,7 @@
"isUpcomingChange": true,
"dashedName": "front-end-development-certification-exam",
"helpCategory": "HTML-CSS",
"order": 1,
"order": 387,
"superBlock": "front-end-development",
"challengeOrder": [
{
@@ -3,7 +3,7 @@
"isUpcomingChange": true,
"usesMultifileEditor": true,
"dashedName": "lab-recipe-page",
"order": 2,
"order": 3,
"superBlock": "front-end-development",
"challengeOrder": [
{
@@ -1,16 +0,0 @@
{
"name": "Learn Basic HTML by Building a Recipe Page",
"isUpcomingChange": true,
"usesMultifileEditor": true,
"hasEditableBoundaries": true,
"dashedName": "learn-basic-html-by-building-a-recipe-page",
"order": 0,
"superBlock": "front-end-development",
"challengeOrder": [
{
"id": "66731cd027ef3acb155669f5",
"title": "Step 1"
}
],
"helpCategory": "HTML-CSS"
}
@@ -0,0 +1,172 @@
{
"name": "Build a Cat Photo App",
"isUpcomingChange": true,
"usesMultifileEditor": true,
"hasEditableBoundaries": true,
"dashedName": "workshop-cat-photo-app",
"order": 2,
"superBlock": "front-end-development",
"challengeOrder": [
{
"id": "66731cd027ef3acb155669f5",
"title": "Step 1"
},
{
"id": "6690b9626a66f51257ae5a91",
"title": "Step 2"
},
{
"id": "6690b9a24f5b0f1300040c76",
"title": "Step 3"
},
{
"id": "6690ba16cf76f613b4e36197",
"title": "Step 4"
},
{
"id": "6690bb0b4062b114997f708a",
"title": "Step 5"
},
{
"id": "6690bd5ad96139157eedf697",
"title": "Step 6"
},
{
"id": "6690be42942f421648b119eb",
"title": "Step 7"
},
{
"id": "6690be902f051416f668962b",
"title": "Step 8"
},
{
"id": "6690bebfd5c918179ea4fd3a",
"title": "Step 9"
},
{
"id": "6690beec809b4f184cab6914",
"title": "Step 10"
},
{
"id": "669840900adeba35e4ebb917",
"title": "Step 11"
},
{
"id": "669840c70aea8936930dba35",
"title": "Step 12"
},
{
"id": "6698410269ace0373ec812b6",
"title": "Step 13"
},
{
"id": "6698417821794837f14ca275",
"title": "Step 14"
},
{
"id": "6698419d8f52cf3891f34853",
"title": "Step 15"
},
{
"id": "66984218720e29393b1adad2",
"title": "Step 16"
},
{
"id": "6698429ba5761b39f8aad814",
"title": "Step 17"
},
{
"id": "669842cee55b683aa13ee758",
"title": "Step 18"
},
{
"id": "669842f261665d3b4a42df81",
"title": "Step 19"
},
{
"id": "66984330a510e63bf0787898",
"title": "Step 20"
},
{
"id": "6698440c54c8823cc60af8bc",
"title": "Step 21"
},
{
"id": "6698444102ebd53d78cf66f8",
"title": "Step 22"
},
{
"id": "66984484deb84b3e21e5b3d7",
"title": "Step 23"
},
{
"id": "66984535d474083eec6bb8da",
"title": "Step 24"
},
{
"id": "6698457295f6403fa49050b8",
"title": "Step 25"
},
{
"id": "6698458e123b4f403936994d",
"title": "Step 26"
},
{
"id": "669845af34899240d9196258",
"title": "Step 27"
},
{
"id": "66984881117baa41da8bbde0",
"title": "Step 28"
},
{
"id": "669848cd668e7242872f4861",
"title": "Step 29"
},
{
"id": "66984905e95af5432faa28b1",
"title": "Step 30"
},
{
"id": "6698491eff5f2e43c20c6503",
"title": "Step 31"
},
{
"id": "6698496716e821448ba724a6",
"title": "Step 32"
},
{
"id": "66984e0cb4febb50c3794edf",
"title": "Step 33"
},
{
"id": "66984e8ab54bee517207be42",
"title": "Step 34"
},
{
"id": "66984ec64a3652522e81c678",
"title": "Step 35"
},
{
"id": "66984eef66cc1752d93b53f5",
"title": "Step 36"
},
{
"id": "66984fe8efbd8c53a78c9b62",
"title": "Step 37"
},
{
"id": "66985068aeb06e54562df39e",
"title": "Step 38"
},
{
"id": "669850ce0ccf395511ff4254",
"title": "Step 39"
},
{
"id": "6698510677b5e655ba8c1017",
"title": "Step 40"
}
],
"helpCategory": "HTML-CSS"
}
@@ -1,28 +0,0 @@
---
id: 66731cd027ef3acb155669f5
title: Step 1
challengeType: 0
dashedName: step-1
---
# --description--
step 1 instructions
# --hints--
Test 1
```js
```
# --seed--
## --seed-contents--
```html
--fcc-editable-region--
--fcc-editable-region--
```
@@ -0,0 +1,69 @@
---
id: 66731cd027ef3acb155669f5
title: Step 1
challengeType: 0
dashedName: step-1
---
# --description--
In this workshop, you will learn how to work with basic HTML elements like headings, paragraphs, and lists by building a cat photo app.
The first element you will learn about is the `h1` element. The `h1` element is a heading element and is used for the main heading of a webpage.
```html
<h1>This is a main heading</h1>
```
Add an `h1` element with the text of `CatPhotoApp` and watch
the change in the browser preview.
When you are done, press the "Check Your Code" button to see if it's correct.
# --hints--
The text `CatPhotoApp` should be present in the code. You may want to check your spelling.
```js
assert(code.match(/catphotoapp/i));
```
Your `h1` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('h1'));
```
Your `h1` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/h1\>/));
```
Your `h1` element's text should be `CatPhotoApp`. You have either omitted the text, have a typo, or it is not between the `h1` element's opening and closing tags.
```js
assert(document.querySelector('h1').innerText.toLowerCase() === 'catphotoapp');
```
You appear to be using a browser extension that is modifying the page. Be sure to turn off all browser extensions.
```js
assert.isAtMost(document.querySelectorAll('script').length, 2);
assert.equal(document.querySelectorAll('style').length, 0);
assert.equal(document.querySelectorAll('link').length, 0);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```
@@ -0,0 +1,95 @@
---
id: 6690b9626a66f51257ae5a91
title: Step 2
challengeType: 0
dashedName: step-2
---
# --description--
The `h1` through `h6` heading elements are used to signify the importance of content below them. The lower the number, the higher the importance, so `h2` elements have less importance than `h1` elements.
```html
<h1>most important heading element</h1>
<h2>second most important heading element</h2>
<h3>third most important heading element</h3>
<h4>fourth most important heading element</h4>
<h5>fifth most important heading element</h5>
<h6>least important heading element</h6>
```
Only use one `h1` element per page and place lower-importance headings below higher-importance headings.
Below the `h1` element, add an `h2` element with this text:
`Cat Photos`
# --hints--
Your `h1` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('h1'));
```
Your `h1` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/h1\>/));
```
You should only have one `h1` element. Remove the extra.
```js
assert(
document.querySelector('h1') && document.querySelectorAll('h1').length === 1
);
```
Your `h1` element's text should be 'CatPhotoApp'. You have either omitted the text or have a typo.
```js
assert(document.querySelector('h1').innerText.toLowerCase() === 'catphotoapp');
```
Your `h2` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('h2'));
```
Your `h2` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/h2\>/));
```
Your `h2` element's text should be 'Cat Photos'. Only place the text `Cat Photos` between the opening and closing `h2` tags.
```js
assert(document.querySelector('h2').innerText.toLowerCase() === 'cat photos');
```
Your `h2` element should be below the `h1` element. The `h1` element has greater importance and must be above the `h2` element.
```js
const collection = [...document.querySelectorAll('h1,h2')].map(
(node) => node.nodeName
);
assert(collection.indexOf('H1') < collection.indexOf('H2'));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
--fcc-editable-region--
<h1>CatPhotoApp</h1>
--fcc-editable-region--
</body>
</html>
```
@@ -0,0 +1,60 @@
---
id: 6690b9a24f5b0f1300040c76
title: Step 3
challengeType: 0
dashedName: step-3
---
# --description--
The `p` element is used to create a paragraph of text on websites. Create a `p` element below your `h2` element and give it the following text:
`See more cat photos in our gallery.`
# --hints--
Your `p` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelector('p'));
```
Your `p` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/p\>/));
```
Your `p` element's text should be `See more cat photos in our gallery.` You have either omitted the text or have a typo.
```js
const extraSpacesRemoved = document
.querySelector('p')
.innerText.replace(/\s+/g, ' ');
assert(extraSpacesRemoved.match(/see more cat photos in our gallery\.?$/i));
```
Your `p` element should be below the `h2` element. You have them in the wrong order.
```js
const collection = [...document.querySelectorAll('h2,p')].map(
(node) => node.nodeName
);
assert(collection.indexOf('H2') < collection.indexOf('P'));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<h1>CatPhotoApp</h1>
--fcc-editable-region--
<h2>Cat Photos</h2>
--fcc-editable-region--
</body>
</html>
```
@@ -0,0 +1,79 @@
---
id: 6690ba16cf76f613b4e36197
title: Step 4
challengeType: 0
dashedName: step-4
---
# --description--
Commenting allows you to leave messages without affecting the browser display. It also allows you to make code inactive. A comment in HTML starts with `<!--`, contains any number of lines of text, and ends with `-->`.
Here is an example of a comment with the `TODO: Remove h1`:
```html
<!-- TODO: Remove h1 -->
```
Add a comment above the `p` element with this text:
`TODO: Add link to cat photos`
# --hints--
Your comment should start with `<!--`. You are missing one or more of the characters that define the start of a comment.
```js
assert(code.match(/<!--/));
```
Your comment should end with `-->`. You are missing one or more of the characters that define the end of a comment.
```js
assert(code.match(/-->/));
```
Your code should not have extra opening/closing comment characters. You have an extra `<!--` or `-->` displaying in the browser.
```js
const noSpaces = code.replace(/\s/g, '');
assert(noSpaces.match(/<!--/g).length < 2 && noSpaces.match(/-->/g).length < 2);
```
Your comment should contain the text `TODO: Add link to cat photos`.
```js
assert(code.match(/<!--\s*todo:\s+add\s+link\s+to\s+cat\s+photos\s*-->/i));
```
Your comment should be above the `p` element. You have them in the wrong order.
```js
assert(
code
.replace(/\s/g, '')
.match(
/<!--todo:addlinktocatphotos--><p>seemorecatphotosinourgallery\.?<\/p>/i
)
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
--fcc-editable-region--
<p>See more cat photos in our gallery.</p>
--fcc-editable-region--
</body>
</html>
```
@@ -0,0 +1,81 @@
---
id: 6690bb0b4062b114997f708a
title: Step 5
challengeType: 0
dashedName: step-5
---
# --description--
HTML5 has some elements that identify different content areas. These elements make your HTML easier to read and help with Search Engine Optimization (SEO) and accessibility.
The `main` element is used to represent the main content of the body of an HTML document. Content inside the `main` element should be unique to the document and should not be repeated in other parts of the document.
```html
<main>
<h1>Most important content of the document</h1>
<p>Some more important content...</p>
</main>
```
Identify the main section of this page by adding a `<main>` opening tag before the `h1` element, and a `</main>` closing tag after the `p` element.
# --hints--
Your `main` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('main'));
```
Your `main` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/main\>/));
```
Your `main` element's opening tag should be below the `body` element's opening tag. You have them in the wrong order.
```js
const main = document.querySelector('main');
assert.equal(main?.previousElementSibling, null);
```
Your `main` element's opening tag should be above the `h1` element. You have them in the wrong order.
```js
const collection = [...document.querySelectorAll('main,h1')].map(
(node) => node.nodeName
);
assert(collection.indexOf('MAIN') < collection.indexOf('H1'));
```
Your `main` element's closing tag should be below the `p` element. You have them in the wrong order.
```js
const mainNode = document.querySelector('main');
const pNode = document.querySelector('p');
assert(
mainNode.contains(pNode) &&
pNode.textContent.toLowerCase().match(/see more cat photos in our gallery/)
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
--fcc-editable-region--
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more cat photos in our gallery.</p>
--fcc-editable-region--
</body>
</html>
```
@@ -0,0 +1,113 @@
---
id: 6690bd5ad96139157eedf697
title: Step 6
challengeType: 0
dashedName: step-6
---
# --description--
In the previous step, you put the `h1`, `h2`, comment, and `p` elements inside the `main` element. This is called *nesting*. Nested elements should be placed two spaces further to the right of the element they are nested in. This spacing is called indentation and it is used to make HTML easier to read.
Here is an example of nesting and indentation:
```html
<main>
<h1>Most important content of the document</h1>
<p>Some more important content...</p>
</main>
```
The `h1` element, `h2` element and the comment are indented two spaces more than the `main` element in the code below. Use the space bar on your keyboard to add two more spaces in front of the `p` element so that it is indented properly as well.
# --hints--
Your code should have an `h2` element with text `Cat Photos`. You may have accidentally deleted it, it is missing both opening and closing tags, or the text has changed.
```js
assert(
document.querySelector('h2') &&
code.match(/<\/h2\>/) &&
document.querySelector('h2').innerText.toLowerCase() === 'cat photos'
);
```
You should not add the `ul` or `li` elements from the example.
```js
assert(
!document.querySelector('ul') && !document.querySelector('li')
);
```
You should not change the indentation on the line with your `h2` element. Its opening tag should start 6 spaces over from the start of the line. You can restart the step to restore the original indentation.
```js
assert(code.toLowerCase().match(/<\/h1\>\s*\n\s{6}<h2>/));
```
Your code should have a comment. You removed the comment from an earlier step.
```js
assert(code.match(/<!--.*-->/));
```
The comment's text should be `TODO: Add link to cat photos`. Do not change the text or spacing of the comment.
```js
assert(code.match(/<!--\s*todo:\s+add\s+link\s+to\s+cat\s+photos\.?\s*-->/i));
```
You should not change the indentation on the line with your comment element. Its opening tag should start 6 spaces over from the start of the line. You can restart the step to restore the original indentation.
```js
assert(
code
.toLowerCase()
.match(/<\/h2>\s*\n\s{6}<!--\s*todo:\s+add\s+link\s+to\s+cat\s+photos\s*-->/)
);
```
Your code should have a `p` element. You have removed the `p` element from an earlier step.
```js
assert(document.querySelector('p'));
```
The text of the `p` element should be `See more cat photos in our gallery.` Do not change the text, spacing, or punctuation of the `p` element.
```js
assert(
document
.querySelector('p')
.innerText.toLowerCase()
.match(/see\s+more\s+cat\s+photos\s+in\s+our\s+gallery\.?$/)
);
```
The opening `p` tag should have indentation that matches your `h2` and comment elements. Its opening tag should start 6 spaces over from the start of the line.
```js
assert(code.toLowerCase().match(/-->\s*\n\s{6}<p>/));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
--fcc-editable-region--
<main>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more cat photos in our gallery.</p>
</main>
--fcc-editable-region--
</body>
</html>
```
@@ -0,0 +1,63 @@
---
id: 6690be42942f421648b119eb
title: Step 7
challengeType: 0
dashedName: step-7
---
# --description--
You can add images to your website by using the `img` element. `img` elements have an opening tag without a closing tag. An element without a closing tag is known as a <dfn>void element</dfn>.
Add an `img` element below the `p` element. At this point, no image will show up in the browser.
# --hints--
Your `img` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('img'));
```
Your `img` element should not have a closing tag `</img>`.
```js
assert(!code.match(/<\/img\>/));
```
You should only have one `img` element. Remove any extras.
```js
assert(document.querySelectorAll('img').length === 1);
```
Your `img` element should be below the `p` element. You have them in the wrong order.
```js
const collection = [...document.querySelectorAll('p,img')].map(
(node) => node.nodeName
);
assert(collection.indexOf('P') < collection.indexOf('IMG'));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
--fcc-editable-region--
<p>See more cat photos in our gallery.</p>
--fcc-editable-region--
</main>
</body>
</html>
```
@@ -0,0 +1,74 @@
---
id: 6690be902f051416f668962b
title: Step 8
challengeType: 0
dashedName: step-8
---
# --description--
HTML <dfn>attributes</dfn> are special words used inside the opening tag of an element to control the element's behavior. The `src` attribute in an `img` element specifies the image's URL (where the image is located).
Here is an example of an `img` element with a `src` attribute pointing to the freeCodeCamp logo:
```html
<img src="https://cdn.freecodecamp.org/platform/universal/fcc_secondary.svg">
```
Inside the existing `img` element, add a `src` attribute with this URL:
`https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg`
# --hints--
Your code should have an `img` element. You may have removed the `img` element or you have not surrounded the `src` attribute's value with quotes.
```js
assert(document.querySelector('img'));
```
Your `img` element should have a `src` attribute. You have either omitted the attribute or have a typo. Make sure there is a space between the element name and the attribute name.
```js
assert(document.querySelector('img').src);
```
Your `img` element's `src` attribute should be set to '`https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg`'. You have either omitted the URL or have a typo. The case of the URL is important.
```js
assert(document.querySelector('img').src === 'https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg');
```
Although you have set the `img` element's `src` to the correct URL, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<img\s+src\s*=\s*https:\/\/cdn\.freecodecamp\.org\/curriculum\/cat-photo-app\/relaxing-cat\.jpg/.test(code));
```
Your `img` element should be closed either with `>` or `/>`.
```js
assert(/<img\s+src\s*=\s*("|')https:\/\/cdn\.freecodecamp\.org\/curriculum\/cat-photo-app\/relaxing-cat\.jpg\1\s*\/?>/.test(code));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more cat photos in our gallery.</p>
--fcc-editable-region--
<img>
--fcc-editable-region--
</main>
</body>
</html>
```
@@ -0,0 +1,66 @@
---
id: 6690bebfd5c918179ea4fd3a
title: Step 9
challengeType: 0
dashedName: step-9
---
# --description--
All `img` elements should have an `alt` attribute. The `alt` attribute's text is used for screen readers to improve accessibility and is displayed if the image fails to load.
Here is an example of an `img` element with an `alt` attribute:
```html
<img src="cat.jpg" alt="A cat">
```
Inside the `img` element, add an `alt` attribute with this text:
`A cute orange cat lying on its back`
# --hints--
Your code should have an `img` element. You removed the `img` element from an earlier step.
```js
assert(document.querySelector('img'));
```
Your `img` element does not have an `alt` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert(document.querySelector('img').hasAttribute('alt'));
```
Your `img` element's `alt` attribute value is set to something other than 'A cute orange cat lying on its back'. Make sure the `alt` attribute's value is surrounded with quotation marks.
```js
const altText = document
.querySelector('img')
.alt.toLowerCase()
.replace(/\s+/g, ' ');
assert(altText.match(/A cute orange cat lying on its back\.?$/i));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more cat photos in our gallery.</p>
--fcc-editable-region--
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg">
--fcc-editable-region--
</main>
</body>
</html>
```
@@ -0,0 +1,87 @@
---
id: 6690beec809b4f184cab6914
title: Step 10
challengeType: 0
dashedName: step-10
---
# --description--
You can link to another page with the anchor (`a`) element.
Here is an example linking to `https://www.freecodecamp.org`:
```html
<a href="https://www.freecodecamp.org"></a>
```
Add an anchor element after the paragraph that links to `https://freecatphotoapp.com`. At this point, the link wont show up in the preview.
# --hints--
Your anchor (`a`) element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('a'));
```
Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/a\>/));
```
Your anchor (`a`) element should be below the `p` element. You have them in the wrong order.
```js
const collection = [...document.querySelectorAll('a, p')].map(
(node) => node.nodeName
);
assert(collection.indexOf('P') < collection.indexOf('A'));
```
Your anchor (`a`) element does not have an `href` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert(document.querySelector('a').hasAttribute('href'));
```
Your anchor (`a`) element should link to `https://freecatphotoapp.com`. You have either omitted the URL or have a typo.
```js
assert(
document.querySelector('a').getAttribute('href') ===
'https://freecatphotoapp.com'
);
```
Although you have set the anchor ('a') element's `href` attribute to the correct link, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(
!/\<a\s+href\s*=\s*https:\/\/www.freecodecamp.org\/cat-photos/.test(code)
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
--fcc-editable-region--
<p>See more cat photos in our gallery.</p>
--fcc-editable-region--
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back.">
</main>
</body>
</html>
```
@@ -0,0 +1,64 @@
---
id: 669840900adeba35e4ebb917
title: Step 11
challengeType: 0
dashedName: step-11
---
# --description--
A link's text must be placed between the opening and closing tags of an anchor (`a`) element.
Here is an example of a link with the text `click here to go to freeCodeCamp.org`:
```html
<a href="https://www.freecodecamp.org">click here to go to freeCodeCamp.org</a>
```
Add the anchor text `link to cat pictures` to the anchor element. This will become the link's text.
# --hints--
Your anchor (`a`) element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('a'));
```
Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/a\>/));
```
Your anchor (`a`) element's text should be `link to cat pictures`. Make sure to put the link text between the anchor (`a`) element's opening tag and closing tag.
```js
assert(
document.querySelector('a').innerText.toLowerCase().replace(/\s+/g, ' ') ===
'link to cat pictures'
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more cat photos in our gallery.</p>
--fcc-editable-region--
<a href="https://freecatphotoapp.com"></a>
--fcc-editable-region--
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back.">
</main>
</body>
</html>
```
@@ -0,0 +1,79 @@
---
id: 669840c70aea8936930dba35
title: Step 12
challengeType: 0
dashedName: step-12
---
# --description--
You can turn any text into a link, such as the text inside of a `p` element.
``` html
<p>I think <a href="https://www.freecodecamp.org">freeCodeCamp</a> is great.</p>
```
In the text of your `p` element, turn the words `cat photos` into a link by adding opening and closing anchor (`a`) tags around these words. Then set the `href` attribute to `https://freecatphotoapp.com`
# --hints--
You should nest a new anchor (`a`) element within the `p` element.
```js
const nestedAnchor = document.querySelector(`p > a`);
assert.isNotNull(nestedAnchor)
```
The link's `href` value should be `https://freecatphotoapp.com`. You have either omitted the `href` value or have a typo.
```js
assert(
document.querySelector('p > a').href === 'https://freecatphotoapp.com/'
);
```
The link's text should be `cat photos`. You have either omitted the text or have a typo.
```js
const nestedAnchor = document.querySelector('p > a');
const innerContent = nestedAnchor.innerHTML;
assert.isTrue(innerContent.trim() === 'cat photos');
```
The text inside your anchor element has extra leading or trailing whitespace. The only space in the anchor text should be between the word `cat` and the word `photos`.
```js
const nestedAnchor = document.querySelector('p > a');
const innerContent = nestedAnchor.innerHTML;
assert.isNotTrue(/^\s+|\s+$/.test(innerContent));
```
After nesting the anchor (`a`) element, the only `p` element content visible in the browser should be `See more cat photos in our gallery.` Double check the text, spacing, or punctuation of both the `p` and nested anchor element.
```js
assert.match(code, /<p>see more <a[^>]*>cat photos<\/a> in our gallery\.?<\/p>/i)
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
--fcc-editable-region--
<p>See more cat photos in our gallery.</p>
--fcc-editable-region--
<a href="https://freecatphotoapp.com">link to cat pictures</a>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back.">
</main>
</body>
</html>
```
@@ -0,0 +1,63 @@
---
id: 6698410269ace0373ec812b6
title: Step 13
challengeType: 0
dashedName: step-13
---
# --description--
Now that you turned the text `cat photos` inside the `p` element into a link, you don't need the second link below the `p` element. Delete the entire anchor element below the `p` element.
# --hints--
Your code should only have one paragraph (`p`) element.
```js
assert.isTrue(document.querySelectorAll('p').length === 1);
```
Your code should only have one anchor (`a`) element.
```js
assert.isTrue(document.querySelectorAll('a').length === 1);
```
Do not make any changes to the elements you created in the previous step.
```js
assert.strictEqual(document.querySelector('p').innerHTML, 'See more <a href="https://freecatphotoapp.com">cat photos</a> in our gallery.')
```
There should not be `cat photos` text below the `p` element.
```js
const pNextSibling = document.querySelector('p').nextSibling;
assert(
pNextSibling.nodeName === '#text' && !/cat\s*photos/.test(pNextSibling.nodeValue) ||
pNextSibling.nodeName === 'IMG'
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
--fcc-editable-region--
<p>See more <a href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com">link to cat pictures</a>
--fcc-editable-region--
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back.">
</main>
</body>
</html>
```
@@ -0,0 +1,66 @@
---
id: 6698417821794837f14ca275
title: Step 14
challengeType: 0
dashedName: step-14
---
# --description--
To open links in a new tab, you can use the `target` attribute on the anchor (`a`) element.
The `target` attribute specifies where to open the linked document. `target="_blank"` opens the linked document in a new tab or window.
Here is the basic syntax for an `a` element with a `target` attribute:
```html
<a href="https://www.freecodecamp.org" target="_blank">freeCodeCamp</a>
```
Add a `target` attribute with the value `_blank` to the anchor (`a`) element's opening tag, so that the link opens in a new tab.
# --hints--
Your `p` element should have a nested anchor (`a`) element with the text `cat photos`. You may have deleted it or have a typo.
```js
const anchor = $('p > a');
assert(
anchor.length &&
anchor[0].innerText.toLowerCase().replace(/\s+/g, ' ') === 'cat photos'
);
```
Your anchor (`a`) element does not have a `target` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert(document.querySelector('a').hasAttribute('target'));
```
The value of the `target` attribute should be `_blank`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
assert(document.querySelector('a').getAttribute('target') === '_blank');
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
--fcc-editable-region--
<p>See more <a href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
--fcc-editable-region--
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back.">
</main>
</body>
</html>
```
@@ -0,0 +1,99 @@
---
id: 6698419d8f52cf3891f34853
title: Step 15
challengeType: 0
dashedName: step-15
---
# --description--
In previous steps, you used an anchor element to turn text into a link. Other types of content can also be turned into a link by wrapping it in anchor tags.
Here is an example of turning an image into a link:
```html
<a href="example-link">
<img src="image-link.jpg" alt="A photo of a cat.">
</a>
```
Turn the image into a link by surrounding it with necessary element tags. Use `https://freecatphotoapp.com` as the anchor's `href` attribute value.
# --hints--
You should have an `img` element with a `src` value of `https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg`. You may have accidentally deleted it.
```js
assert(
document.querySelector('img') &&
document.querySelector('img').getAttribute('src') ===
'https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg'
);
```
Your anchor (`a`) element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('a').length >= 2);
```
You are missing a closing (`a`) tag after the image.
```js
assert(document.querySelectorAll('a').length === 2);
```
Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/a>/g).length >= 2);
```
You should only add one closing anchor (`a`) tag. Please remove any extras.
```js
assert(code.match(/<\/a>/g).length === 2);
```
Your anchor (`a`) element does not have an `href` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert(document.querySelector('a').hasAttribute('href'));
```
Your anchor (`a`) element should link to `https://freecatphotoapp.com`. You have either omitted the URL or have a typo.
```js
assert(
document.querySelectorAll('a')[1].getAttribute('href') ===
'https://freecatphotoapp.com'
);
```
Your `img` element should be nested within the anchor (`a`) element. The entire `img` element should be inside the opening and closing tags of the anchor (`a`) element.
```js
assert(document.querySelector('img').parentNode.nodeName === 'A');
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
--fcc-editable-region--
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back.">
--fcc-editable-region--
</main>
</body>
</html>
```
@@ -0,0 +1,83 @@
---
id: 66984218720e29393b1adad2
title: Step 16
challengeType: 0
dashedName: step-16
---
# --description--
Before adding any new content, you should make use of a `section` element to separate the cat photos content from the future content.
The `section` element is used to define sections in a document, such as chapters, headers, footers, or any other sections of the document. It is a semantic element that helps with SEO and accessibility.
```html
<section>
<h2>Section Title</h2>
<p>Section content...</p>
</section>
```
Take your `h2`, comment, `p`, and anchor (`a`) elements and nest them in a `section` element.
# --hints--
Your `section` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelector('section'));
```
Your `section` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/section\s*>/i));
```
The entire `section` element should be between the opening and closing tags of the `main` element.
```js
assert(document.querySelector('section').parentNode.nodeName === 'MAIN');
```
The existing `h2`, comment, `p` element, and anchor (`a`) element should be between the opening and closing tags of the `section` element.
```js
const childrenOfSection = [...document.querySelector('section').childNodes];
const foundElements = childrenOfSection.filter((child) => {
return ['H2', 'A', 'P'].includes(child.nodeName);
});
assert(foundElements.length === 3);
```
The `h1` element should not be nested in the `section` element.
```js
const childrenOfSection = [...document.querySelector('section').childNodes];
const includesH1 = childrenOfSection.some((child) => child.nodeName === 'H1');
assert.isFalse(includesH1);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
--fcc-editable-region--
<main>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</main>
--fcc-editable-region--
</body>
</html>
```
@@ -0,0 +1,83 @@
---
id: 6698429ba5761b39f8aad814
title: Step 17
challengeType: 0
dashedName: step-17
---
# --description--
It is time to add a new section. Add a second `section` element below the existing `section` element.
# --hints--
Your `section` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('section').length >= 2);
```
You should only add one opening `section` tag. Please remove any extras.
```js
assert(document.querySelectorAll('section').length === 2);
```
Your `section` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/section>/g).length >= 2);
```
You should only add one closing `section` tag. Please remove any extras.
```js
assert(code.match(/<\/section>/g).length === 2);
```
The second `section` element should not be nested in the first `section` element.
```js
const childrenOf1stSection = [
...document.querySelector('main > section').children
];
const foundElems = childrenOf1stSection.filter((child) => {
return child.nodeName === 'SECTION';
});
assert(foundElems.length === 0);
```
Both `section` elements should be between the opening and closing tags of the `main` element.
```js
const childrenOfMain = [...document.querySelector('main').children];
const foundElems = childrenOfMain.filter((child) => {
return child.nodeName === 'SECTION';
});
assert(foundElems.length === 2);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
--fcc-editable-region--
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
--fcc-editable-region--
</main>
</body>
</html>
```
@@ -0,0 +1,77 @@
---
id: 669842cee55b683aa13ee758
title: Step 18
challengeType: 0
dashedName: step-18
---
# --description--
Within the second `section` element, add a new `h2` element with the text `Cat Lists`.
# --hints--
Your `section` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(
document.querySelectorAll('section').length === 2 &&
code.match(/<\/section>/g).length === 2
);
```
Your `h2` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('h2').length === 2);
```
Your `h2` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/h2\>/g).length === 2);
```
Your second `h2` element should be right above the second `section` element's closing tag. It is not in the correct position.
```js
const secondSection = document.querySelectorAll('section')[1];
assert(secondSection.lastElementChild.nodeName === 'H2');
```
The second `h2` element should have the text `Cat Lists`. You have either omitted the text or have a typo.
```js
assert(
document
.querySelectorAll('main > section')[1]
.lastElementChild.innerText.toLowerCase() === 'cat lists'
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
--fcc-editable-region--
<section>
</section>
--fcc-editable-region--
</main>
</body>
</html>
```
@@ -0,0 +1,86 @@
---
id: 669842f261665d3b4a42df81
title: Step 19
challengeType: 0
dashedName: step-19
---
# --description--
When you add a lower-rank heading element to the page, it's implied that you're starting a new subsection.
After the last `h2` element of the second `section` element, add an `h3` element with this text:
`Things cats love:`
# --hints--
The second `section` element appears to be missing or does not have both an opening and closing tag.
```js
assert(
document.querySelectorAll('main > section')[1] &&
code.match(/\<\/section>/g).length == 2
);
```
There should be an `h3` element right above the second `section` element's closing tag.
```js
assert(
document.querySelectorAll('main > section')[1].lastElementChild.nodeName ===
'H3'
);
```
The `h3` element right above the second `section` element's closing tag should have the text `Things cats love:`. Make sure to include the colon at the end of the text.
```js
assert(
document
.querySelectorAll('main > section')[1]
.lastElementChild.innerText.toLowerCase()
.replace(/\s+/g, ' ') === 'things cats love:'
);
```
There should be an `h2` element with the text `Cat Lists` above the last `h3` element that is nested in the last `section` element'. You may have accidentally deleted the `h2` element.
```js
const secondSectionLastElemNode = document.querySelectorAll('main > section')[1]
.lastElementChild;
assert(
secondSectionLastElemNode.nodeName === 'H3' &&
secondSectionLastElemNode.previousElementSibling.innerText
.toLowerCase()
.replace(/\s+/g, ' ') === 'cat lists'
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
--fcc-editable-region--
<section>
<h2>Cat Lists</h2>
</section>
--fcc-editable-region--
</main>
</body>
</html>
```
@@ -0,0 +1,62 @@
---
id: 66984330a510e63bf0787898
title: Step 20
challengeType: 0
dashedName: step-20
---
# --description--
To create an unordered list of items, you can use the `ul` element.
After the `h3` element with the `Things cats love:` text, add an unordered list (`ul`) element. Note that nothing will be displayed at this point.
# --hints--
Your `ul` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('ul'));
```
Your `ul` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/ul>/));
```
The `ul` element should be above the second `section` element's closing tag.
```js
const secondSectionLastElemNode = $('main > section')[1].lastElementChild;
assert(secondSectionLastElemNode.nodeName === 'UL');
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
--fcc-editable-region--
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,85 @@
---
id: 6698440c54c8823cc60af8bc
title: Step 21
challengeType: 0
dashedName: step-21
---
# --description--
The `li` element is used to create a list item in an ordered or unordered list.
Here is an example of list items in an unordered list:
```html
<ul>
<li>milk</li>
<li>cheese</li>
</ul>
```
Within the `ul` element nest three list items to display three things cats love:
`cat nip`
`laser pointers`
`lasagna`
# --hints--
You should have three `li` elements. Each `li` element should have its own opening and closing tag.
```js
assert($('li').length === 3 && code.match(/<\/li\>/g).length === 3);
```
You should have three `li` elements with the text `cat nip`, `laser pointers` and `lasagna` in any order. You have either omitted some text or have a typo.
```js
assert.deepStrictEqual(
[...document.querySelectorAll('li')]
.map((item) => item.innerText.toLowerCase())
.sort((a, b) => a.localeCompare(b)),
['cat nip', 'lasagna', 'laser pointers']
);
```
The three `li` elements should be located between the `ul` element's opening and closing tags.
```js
assert(
[...document.querySelectorAll('li')].filter(
(item) => item.parentNode.nodeName === 'UL'
).length === 3
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
--fcc-editable-region--
<ul>
</ul>
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,96 @@
---
id: 6698444102ebd53d78cf66f8
title: Step 22
challengeType: 0
dashedName: step-22
---
# --description--
After the unordered list, add a new image with a `src` attribute value set to:
`https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg`
And its `alt` attribute value to:
`A slice of lasagna on a plate.`
# --hints--
There should be an `img` element right after the closing `</ul>` tag.
```js
assert($('section')[1].lastElementChild.nodeName === 'IMG');
```
The new image does not have an `alt` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert($('section')[1].lastElementChild.hasAttribute('alt'));
```
The new image should have an `alt` value of `A slice of lasagna on a plate.` Make sure the `alt` attribute's value is surrounded with quotation marks.
```js
assert(
$('section')[1]
.lastElementChild.getAttribute('alt')
.replace(/\s+/g, ' ')
.match(/^A slice of lasagna on a plate\.?$/i)
);
```
The new image does not have a `src` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert($('section')[1].lastElementChild.hasAttribute('src'));
```
The new image should have a `src` value of `https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg`. Make sure the `src` attribute's value is surrounded with quotation marks.
```js
assert(
$('section')[1].lastElementChild.getAttribute('src') ===
'https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg'
);
```
Although you have set the new image's `src` to the correct URL, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<img\s+.+\s+src\s*=\s*https:\/\/cdn\.freecodecamp\.org\/curriculum\/cat-photo-app\/lasagna\.jpg/.test(code));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
--fcc-editable-region--
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,79 @@
---
id: 66984484deb84b3e21e5b3d7
title: Step 23
challengeType: 0
dashedName: step-23
---
# --description--
The `figure` element represents self-contained content and will allow you to associate an image with a caption.
Nest the image you just added within a `figure` element.
# --hints--
Your `figure` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelector('figure'));
```
Your `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/figure\>/));
```
There should be an `figure` element right above the second `section` element's closing tag.
```js
assert($('section')[1].lastElementChild.nodeName === 'FIGURE');
```
The lasagna `img` element should be nested in the `figure` element.
```js
assert(
document.querySelector('figure > img') &&
document.querySelector('figure > img').getAttribute('src').toLowerCase() ===
'https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg'
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
--fcc-editable-region--
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,109 @@
---
id: 66984535d474083eec6bb8da
title: Step 24
challengeType: 0
dashedName: step-24
---
# --description--
A figure caption (`figcaption`) element is used to add a caption to describe the image contained within the `figure` element.
Here is an example of a `figcaption` element with the caption of `A cute cat`:
```html
<figure>
<img src="image.jpg" alt="A description of the image">
<figcaption>A cute cat</figcaption>
</figure>
```
After the image nested in the `figure` element, add a `figcaption` element with text set to:
`Cats love lasagna.`
# --hints--
Your `figcaption` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelector('figcaption'));
```
Your `figcaption` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/figcaption\>/));
```
The `figcaption` element should be nested in the `figure` element.
```js
assert(
document.querySelector('figure > figcaption') &&
document.querySelector('figure > figcaption')
);
```
The lasagna `img` element should be nested in the `figure` element.
```js
assert(
document.querySelector('figure > img') &&
document.querySelector('figure > img').getAttribute('src').toLowerCase() ===
'https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg'
);
```
The `figcaption` element nested in the `figure` element should be below the `img` element. You have them in the wrong order.
```js
assert(
document.querySelector('figcaption').previousElementSibling.nodeName === 'IMG'
);
```
Your `figcaption` element's text should be `Cats love lasagna.` You have either omitted the text or have a typo.
```js
assert(
document.querySelector('figcaption').innerText.match(/Cats love lasagna.?$/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
--fcc-editable-region--
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
</figure>
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,88 @@
---
id: 6698457295f6403fa49050b8
title: Step 25
challengeType: 0
dashedName: step-25
---
# --description--
To place emphasis on a specific word or phrase, you can use the `em` element.
Emphasize the word `love` in the `figcaption` element by wrapping it in an emphasis `em` element.
# --hints--
Your emphasis `em` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('em'));
```
Your emphasis `em` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/em\>/));
```
You have either deleted the `figcaption` element or it is missing an opening or closing tag.
```js
assert(document.querySelector('figcaption') && code.match(/<\/figcaption\>/));
```
Your emphasis `em` element should surround the text `love`. You have either omitted the text or have a typo.
```js
assert(
document.querySelector('figcaption > em').innerText.toLowerCase() === 'love'
);
```
The `figcaption`'s text should be `Cats love lasagna`. Check for typos and that the necessary spaces are present around the `em` element's opening and closing tags.
```js
assert(
document
.querySelector('figcaption')
.innerText.replace(/\s+/gi, ' ')
.match(/cats love lasagna\.?/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
--fcc-editable-region--
<figcaption>Cats love lasagna.</figcaption>
--fcc-editable-region--
</figure>
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,83 @@
---
id: 6698458e123b4f403936994d
title: Step 26
challengeType: 0
dashedName: step-26
---
# --description--
After the `figure` element, add another `h3` element with the text:
`Top 3 things cats hate:`
# --hints--
There should be an `h3` element right above the second `section` element's closing tag. Make sure it has an opening and closing tag.
```js
assert(
document.querySelectorAll('main > section')[1].lastElementChild.nodeName ===
'H3' && code.match(/<\/h3\>/g).length === 2
);
```
The new `h3` element should have the text `Top 3 things cats hate:`. Make sure to include the colon at the end of the text.
```js
assert(
document
.querySelectorAll('main > section')[1]
.lastElementChild.innerText.toLowerCase()
.replace(/\s+/g, ' ') === 'top 3 things cats hate:'
);
```
There should be a `figure` above the new `h3` element. You may have accidentally deleted the `figure` element.
```js
const secondSectionLastElemNode = document.querySelectorAll('main > section')[1]
.lastElementChild;
assert(
secondSectionLastElemNode.nodeName === 'H3' &&
secondSectionLastElemNode.previousElementSibling.nodeName === 'FIGURE'
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
--fcc-editable-region--
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,104 @@
---
id: 669845af34899240d9196258
title: Step 27
challengeType: 0
dashedName: step-27
---
# --description--
The code for an ordered list (`ol`) is similar to an unordered list, but list items in an ordered list are numbered when displayed.
After the second `section` element's last `h3` element, add an ordered list with these three list items:
`flea treatment`
`thunder`
`other cats`
# --hints--
Your `ol` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('ol'));
```
Your `ol` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/ol>/));
```
The `ol` element should be above the second `section` element's closing tag. You have them in the wrong order.
```js
assert($('main > section')[1].lastElementChild.nodeName === 'OL');
```
The three `li` elements should be nested inside the `ol` element.
```js
assert(
[...document.querySelectorAll('li')].filter(
(item) => item.parentNode.nodeName === 'OL'
).length === 3
);
```
You should have three `li` elements with the text `flea treatment`, `thunder` and `other cats` in any order.
```js
assert.deepStrictEqual(
[...document.querySelectorAll('li')]
.filter((item) => item.parentNode.nodeName === 'OL')
.map((item) => item.innerText.toLowerCase())
.sort((a, b) => a.localeCompare(b)),
['flea treatment', 'other cats', 'thunder']
);
```
You should only have one `ol` element.
```js
assert([...document.querySelectorAll('ol')].length == 1);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
--fcc-editable-region--
<h3>Top 3 things cats hate:</h3>
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,74 @@
---
id: 66984881117baa41da8bbde0
title: Step 28
challengeType: 0
dashedName: step-28
---
# --description--
After the ordered list, add another `figure` element.
# --hints--
Your `figure` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('figure').length === 2);
```
Your `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/figure>/g).length === 2);
```
There should be a `figure` element right above the second `section` element's closing tag.
```js
assert($('main > section')[1].lastElementChild.nodeName === 'FIGURE');
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
--fcc-editable-region--
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,101 @@
---
id: 669848cd668e7242872f4861
title: Step 29
challengeType: 0
dashedName: step-29
---
# --description--
Inside the `figure` element you just added, nest an `img` element with a `src` attribute set to `https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg`.
# --hints--
Your second `figure` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('figure').length >= 2);
```
Your second `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/figure>/g).length >= 2);
```
There should be a second `figure` element right above the second `section` element's closing tag. You have them in the wrong order.
```js
assert($('main > section')[1].lastElementChild.nodeName === 'FIGURE');
```
You should have a third `img` element nested in the `figure` element.
```js
const catsImg = document.querySelectorAll('figure > img')[1];
assert(
catsImg
);
```
The third image should have a `src` attribute set to `https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg`.
```js
const catsImg = document.querySelectorAll('figure > img')[1];
assert(
catsImg &&
catsImg.getAttribute('src').toLowerCase() === 'https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg'
);
```
Although you have set the new image's `src` to the correct URL, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<img\s+.+\s+src\s*=\s*https:\/\/cdn\.freecodecamp\.org\/curriculum\/cat-photo-app\/cats\.jpg/.test(code));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
--fcc-editable-region--
<figure>
</figure>
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,100 @@
---
id: 66984905e95af5432faa28b1
title: Step 30
challengeType: 0
dashedName: step-30
---
# --description--
To improve the accessibility of the image you added, add an `alt` attribute with the text:
`Five cats looking around a field.`
# --hints--
Your `figure` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('figure').length === 2);
```
Your `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/figure>/g).length === 2);
```
There should be a `figure` element right above the last `section` element's closing tag.
```js
assert($('main > section')[1].lastElementChild.nodeName === 'FIGURE');
```
The Cats `img` element should be nested in the `figure` element.
```js
const catsImg = document.querySelectorAll('figure > img')[1];
assert(
catsImg &&
catsImg.getAttribute('src').toLowerCase() === 'https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg'
);
```
The Cats `img` element should have an `alt` attribute with the value `Five cats looking around a field.`
```js
const catsImg = document.querySelectorAll('figure > img')[1];
assert(
catsImg
.getAttribute('alt')
.replace(/\s+/g, ' ')
.match(/^Five cats looking around a field\.?$/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
<figure>
--fcc-editable-region--
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg">
--fcc-editable-region--
</figure>
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,125 @@
---
id: 6698491eff5f2e43c20c6503
title: Step 31
challengeType: 0
dashedName: step-31
---
# --description--
After the last `img` element, add a `figcaption` element with the text `Cats hate other cats.`
# --hints--
Your `figcaption` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelectorAll('figcaption').length === 2);
```
Your `figcaption` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/figcaption\>/g).length === 2);
```
There should be a `figure` element right above the second `section` element's closing tag.
```js
assert($('main > section')[1].lastElementChild.nodeName === 'FIGURE');
```
The last `img` element should be nested in the `figure` element.
```js
const catsImg = document.querySelectorAll('figure > img')[1];
assert(
catsImg &&
catsImg.getAttribute('src').toLowerCase() === 'https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg'
);
```
Your `figure` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelectorAll('figure').length === 2);
```
Your `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/figure\>/g).length === 2);
```
The `figcaption` element should be nested in the `figure` element.
```js
assert(document.querySelectorAll('figure > figcaption').length === 2);
```
The `figcaption` element nested in the `figure` element should be below the `img` element. You have the `img` element and the `figcaption` element in the wrong order.
```js
assert(
document.querySelectorAll('figcaption')[1].previousElementSibling.nodeName ===
'IMG'
);
```
The `figcaption` element should have the text `Cats hate other cats.` You have omitted a word or have a typo.
```js
assert(
document
.querySelectorAll('figcaption')[1]
.innerText.toLowerCase()
.match(/Cats hate other cats\.?$/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
--fcc-editable-region--
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field.">
</figure>
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,99 @@
---
id: 6698496716e821448ba724a6
title: Step 32
challengeType: 0
dashedName: step-32
---
# --description--
The `strong` element is used to indicate that some text is of strong importance or urgent.
In the `figcaption` you just added, indicate that `hate` is of strong importance by wrapping it in a `strong` element.
# --hints--
Your `strong` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('strong'));
```
Your `strong` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/strong\>/));
```
Your `strong` element should surround the word `hate` in the text `Cats hate other cats.` You have either omitted the text or have a typo.
```js
assert(
document
.querySelectorAll('figcaption')[1]
.querySelector('strong')
.innerText.toLowerCase() === 'hate'
);
```
The `figcaption`'s text should be `Cats hate other cats.` Check for typos and that the necessary spaces are present around the `strong` element's opening and closing tags.
```js
const secondFigCaption = document.querySelectorAll('figcaption')[1];
assert(
secondFigCaption &&
secondFigCaption.innerText
.replace(/\s+/gi, ' ')
.trim()
.match(/cats hate other cats\.?/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field.">
--fcc-editable-region--
<figcaption>Cats hate other cats.</figcaption>
--fcc-editable-region--
</figure>
</section>
</main>
</body>
</html>
```
@@ -0,0 +1,86 @@
---
id: 66984e0cb4febb50c3794edf
title: Step 33
challengeType: 0
dashedName: step-33
---
# --description--
The `footer` element is used to define a footer for a document or section. A footer typically contains information about the author of the document, copyright data, links to terms of use, contact information, and more.
After the `main` element, add a `footer` element.
# --hints--
You have either deleted the `main` element or it is missing an opening tag or closing tag.
```js
assert(document.querySelector('main') && code.match(/<\/main>/));
```
Your `footer` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelector('footer'));
```
Your `footer` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/footer\>/));
```
Your `footer` element should be below the closing `main` element tag. You have put it somewhere else.
```js
assert(document.querySelector('main').nextElementSibling.nodeName === 'FOOTER');
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field.">
<figcaption>Cats <strong>hate</strong> other cats.</figcaption>
</figure>
</section>
--fcc-editable-region--
</main>
</body>
--fcc-editable-region--
</html>
```
@@ -0,0 +1,88 @@
---
id: 66984e8ab54bee517207be42
title: Step 34
challengeType: 0
dashedName: step-34
---
# --description--
Nest a `p` element with the text `No Copyright - freeCodeCamp.org` within the `footer` element.
# --hints--
You have either deleted the `footer` element or it is missing an opening tag or closing tag.
```js
assert(document.querySelector('footer') && code.match(/<\/footer>/));
```
Your `footer` element should have a `p` element. Make sure to add an opening tag and closing tag for the `p` element.
```js
assert(document.querySelector('footer > p'));
```
Your `footer` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
const pElemClosingTags = code.match(/<\/p\>/g);
assert(pElemClosingTags && pElemClosingTags.length === 2);
```
Your `p` element's text should be `No Copyright - freeCodeCamp.org`. You have either omitted the text, have a typo, or it is not between the `p` element's opening and closing tags.
```js
const extraSpacesRemoved = $('footer > p')[0].innerText.replace(/\s+/g, ' ');
assert(extraSpacesRemoved.match(/No Copyright - freeCodeCamp\.org$/i));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field.">
<figcaption>Cats <strong>hate</strong> other cats.</figcaption>
</figure>
</section>
</main>
--fcc-editable-region--
<footer>
</footer>
--fcc-editable-region--
</body>
</html>
```
@@ -0,0 +1,99 @@
---
id: 66984ec64a3652522e81c678
title: Step 35
challengeType: 0
dashedName: step-35
---
# --description--
Turn the existing `freeCodeCamp.org` text into a link by enclosing it in an anchor (`a`) element. The `href` attribute should be set to `https://www.freecodecamp.org`.
# --hints--
Your anchor (`a`) element should be nested within the `p` element inside the `footer`. Make sure to add an opening tag and closing tag for the anchor (`a`) element.
```js
assert($('footer > p > a').length);
```
Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
const aElemClosingTags = code.match(/<\/a\>/g);
assert(aElemClosingTags && aElemClosingTags.length === 3);
```
Your anchor (`a`) element should have an `href` attribute with the value `https://www.freecodecamp.org`. You may have omitted the attribute/value, or have a typo.
```js
const nestedAnchor = $('footer > p > a')[0];
assert(nestedAnchor.getAttribute('href').toLowerCase() === 'https://www.freecodecamp.org');
```
The link's text should be `freeCodeCamp.org`. You have either omitted the text or have a typo.
```js
const nestedAnchor = $('footer > p > a')[0];
assert(
nestedAnchor.innerText.toLowerCase().replace(/\s+/g, ' ') ===
'freecodecamp.org'
);
```
After nesting the anchor (`a`) element, the only `p` element content visible in the browser should be `No Copyright - freeCodeCamp.org`. Double check the text, spacing, or punctuation of both the `p` and nested anchor element.
```js
const pText = $('footer > p')[0].innerText.toLowerCase().replace(/\s+/g, ' ');
assert(pText.match(/^no copyright - freecodecamp.org$/));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field.">
<figcaption>Cats <strong>hate</strong> other cats.</figcaption>
</figure>
</section>
</main>
<footer>
--fcc-editable-region--
<p>No Copyright - freeCodeCamp.org</p>
--fcc-editable-region--
</footer>
</body>
</html>
```
@@ -0,0 +1,94 @@
---
id: 66984eef66cc1752d93b53f5
title: Step 36
challengeType: 0
dashedName: step-36
---
# --description--
Notice that everything you've added to the page so far is inside the `body` element. All page content elements that should be rendered to the page go inside the `body` element. However, other important information goes inside the `head` element.
The `head` element is used to contain metadata about the document, such as its title, links to stylesheets, and scripts. Metadata is information about the page that isn't displayed directly on the page.
Add a `head` element above the `body` element.
# --hints--
You have either deleted the `body` element or it is missing an opening tag or closing tag.
```js
assert(document.querySelector('body') && code.match(/<\/body>/));
```
Your `head` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(code.match(/\<head\>/));
```
Your `head` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/\<\/head\>/));
```
Your `head` element should be above the opening `body` element tag. You have put it somewhere else.
```js
const noSpaces = code.replace(/\s/g, '');
assert(noSpaces.match(/\<\/head\>\<body\>/));
```
# --seed--
## --seed-contents--
```html
--fcc-editable-region--
<html>
<body>
--fcc-editable-region--
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field.">
<figcaption>Cats <strong>hate</strong> other cats.</figcaption>
</figure>
</section>
</main>
<footer>
<p>
No Copyright - <a href="https://www.freecodecamp.org">freeCodeCamp.org</a>
</p>
</footer>
</body>
</html>
```
@@ -0,0 +1,96 @@
---
id: 66984fe8efbd8c53a78c9b62
title: Step 37
challengeType: 0
dashedName: step-37
---
# --description--
The `title` element determines what browsers show in the title bar or tab for the page.
Add a `title` element within the `head` element using the text below:
`CatPhotoApp`
# --hints--
You have either deleted the `head` element or it is missing an opening tag or closing tag.
```js
assert(code.match(/\<head\>/) && code.match(/\<\/head\>/));
```
Your `title` element should be nested in the `head` element. Make sure to add an opening tag and closing tag for the `title` element.
```js
const noSpaces = code.replace(/\s/g, '');
assert(noSpaces.match(/\<head\>\<title\>.*\<\/title\>\<\/head\>/));
```
Your `title` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/\<\/title\>/));
```
Your `title` element's text should be `CatPhotoApp`. You have either omitted the text or have a typo.
```js
assert(document.title && document.title.toLowerCase() === 'catphotoapp');
```
# --seed--
## --seed-contents--
```html
<html>
--fcc-editable-region--
<head>
</head>
--fcc-editable-region--
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field.">
<figcaption>Cats <strong>hate</strong> other cats.</figcaption>
</figure>
</section>
</main>
<footer>
<p>
No Copyright - <a href="https://www.freecodecamp.org">freeCodeCamp.org</a>
</p>
</footer>
</body>
</html>
```
@@ -0,0 +1,84 @@
---
id: 66985068aeb06e54562df39e
title: Step 38
challengeType: 0
dashedName: step-38
---
# --description--
Notice that the entire contents of the page are nested within an `html` element. The `html` element is the root element of an HTML page and wraps all content on the page.
You can also specify the language of your page by adding the `lang` attribute to the `html` element.
Add the `lang` attribute with the value `en` to the opening `html` tag to specify that the language of the page is English.
# --hints--
You have either deleted the `html` element or it is missing an opening tag or closing tag.
```js
assert(code.match(/\<html.*?\>/) && code.match(/\<\/html\>/));
```
Your `html` element should have a `lang` attribute with the value `en`. You may have omitted the attribute/value, or have a typo.
```js
const extraSpacesRemoved = code.replace(/\s+/g, " ");
assert(extraSpacesRemoved.match(/\<html\s+lang\s*\=\s*("?|'?)en\1\s*\>/));
```
# --seed--
## --seed-contents--
```html
--fcc-editable-region--
<html>
--fcc-editable-region--
<head>
<title>CatPhotoApp</title>
</head>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field.">
<figcaption>Cats <strong>hate</strong> other cats.</figcaption>
</figure>
</section>
</main>
<footer>
<p>
No Copyright - <a href="https://www.freecodecamp.org">freeCodeCamp.org</a>
</p>
</footer>
</body>
</html>
```
@@ -0,0 +1,85 @@
---
id: 669850ce0ccf395511ff4254
title: Step 39
challengeType: 0
dashedName: step-39
---
# --description--
All pages should begin with `<!DOCTYPE html>`. This special string is known as a <dfn>declaration</dfn> and ensures the browser tries to meet industry-wide specifications.
`<!DOCTYPE html>` tells browsers that the document is an HTML5 document which is the latest version of HTML.
Add this declaration as the first line of the code.
# --hints--
Your code should begin with the declaration `<!DOCTYPE html>`. You may have omitted the declaration, have a typo, or it is not the first line of code.
```js
assert(code.match(/\<\s*!DOCTYPE\s+html\s*\>/));
```
Your `<!DOCTYPE html>` must be located at the top of the document.
```js
const noSpaces = code.replace(/\s/g, '');
assert(noSpaces.match(/^\<\!DOCTYPEhtml\>\<html/));
```
# --seed--
## --seed-contents--
```html
--fcc-editable-region--
<html lang="en">
--fcc-editable-region--
<head>
<title>CatPhotoApp</title>
</head>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field.">
<figcaption>Cats <strong>hate</strong> other cats.</figcaption>
</figure>
</section>
</main>
<footer>
<p>
No Copyright - <a href="https://www.freecodecamp.org">freeCodeCamp.org</a>
</p>
</footer>
</body>
</html>
```
@@ -0,0 +1,148 @@
---
id: 6698510677b5e655ba8c1017
title: Step 40
challengeType: 0
dashedName: step-40
---
# --description--
You can set browser behavior by adding `meta` elements in the `head`. Here's an example:
```html
<meta attribute="value">
```
Inside the `head` element, nest a `meta` element with a `charset` attribute set to the value of `utf-8`. This tells the browser how to encode characters for the page.
Note that the `meta` element is a void element.
With that last change, you have completed the Cat Photo App workshop. Congratulations!
# --hints--
You should create a `meta` element within the `head` element.
```js
assert.exists(document.querySelector('head > meta'));
```
You should give the `meta` element a `charset` of `UTF-8`.
```js
assert.equal(document.querySelector('head > meta')?.getAttribute('charset')?.toLowerCase(), 'utf-8');
```
Your `meta` element should be a void element, you don't need to add `</meta>`.
```js
assert.notMatch(code, /<\/meta\s*>?/i);
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
--fcc-editable-region--
<head>
<title>CatPhotoApp</title>
</head>
--fcc-editable-region--
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field.">
<figcaption>Cats <strong>hate</strong> other cats.</figcaption>
</figure>
</section>
</main>
<footer>
<p>
No Copyright - <a href="https://www.freecodecamp.org">freeCodeCamp.org</a>
</p>
</footer>
</body>
</html>
```
# --solutions--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CatPhotoApp</title>
</head>
<body>
<main>
<h1>CatPhotoApp</h1>
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>See more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a> in our gallery.</p>
<a href="https://freecatphotoapp.com"><img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg" alt="A cute orange cat lying on its back."></a>
</section>
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/lasagna.jpg" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
<figure>
<img src="https://cdn.freecodecamp.org/curriculum/cat-photo-app/cats.jpg" alt="Five cats looking around a field.">
<figcaption>Cats <strong>hate</strong> other cats.</figcaption>
</figure>
</section>
</main>
<footer>
<p>
No Copyright - <a href="https://www.freecodecamp.org">freeCodeCamp.org</a>
</p>
</footer>
</body>
</html>
```