mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(curriculum): add Build a Bookstore Page Workshop to FSD cert (#62723)
Co-authored-by: Jessica Wilkins <67210629+jdwilkin4@users.noreply.github.com> Co-authored-by: Dario <105294544+Dario-DC@users.noreply.github.com>
This commit is contained in:
@@ -2087,6 +2087,12 @@
|
||||
"In these lessons, you will learn about HTML fundamentals like the <code>div</code> element, the <code>id</code> and <code>class</code> attributes, the HTML boilerplate, HTML entities, and more."
|
||||
]
|
||||
},
|
||||
"workshop-bookstore-page": {
|
||||
"title": "Build a Bookstore Page",
|
||||
"intro": [
|
||||
"In this workshop, you will practice working with classes, ids and the <code>div</code> element by building a bookstore page."
|
||||
]
|
||||
},
|
||||
"lecture-understanding-how-html-affects-seo": {
|
||||
"title": "Understanding How HTML Affects SEO",
|
||||
"intro": [
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Introduction to the Build a Bookstore Page
|
||||
block: workshop-bookstore-page
|
||||
superBlock: full-stack-developer
|
||||
---
|
||||
|
||||
## Introduction to the Build a Bookstore Page
|
||||
|
||||
In this workshop, you will practice working with classes, ids and the <code>div</code> element by building a bookstore page.
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
---
|
||||
id: 68e97fe79367ad7b5dd6c9cd
|
||||
title: Step 1
|
||||
challengeType: 0
|
||||
dashedName: step-1
|
||||
demoType: onLoad
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In this workshop, you will build a bookstore page by creating book cards that display information about different books. You'll practice organizing content using `div` elements, classes, and IDs.
|
||||
|
||||
Start by adding an `h1` element with the text `XYZ Bookstore`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have an `h1` element.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('h1'));
|
||||
```
|
||||
|
||||
Your `h1` element's text should be `XYZ Bookstore`. Double check for spelling or capitalization errors.
|
||||
|
||||
```js
|
||||
assert.equal(document.querySelector('h1')?.innerText.trim(), 'XYZ Bookstore');
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
---
|
||||
id: 68ebdbacdd3fa474132cc975
|
||||
title: Step 2
|
||||
challengeType: 0
|
||||
dashedName: step-2
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Below the `h1` element, add a `p` element with this text: `Browse our collection of amazing books!`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `p` element.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('p'));
|
||||
```
|
||||
|
||||
Your `p` element's text should be: `Browse our collection of amazing books!`.
|
||||
|
||||
```js
|
||||
assert.equal(document.querySelector('p')?.innerText.trim(), 'Browse our collection of amazing books!');
|
||||
```
|
||||
|
||||
Your `p` element should be below your `h1` element.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('h1 + p'));
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
--fcc-editable-region--
|
||||
<h1>XYZ Bookstore</h1>
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
---
|
||||
id: 68ec6cd5b7e8f5a8f7319e32
|
||||
title: Step 3
|
||||
challengeType: 0
|
||||
dashedName: step-3
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The `div` element is used as a container to group other HTML elements. You will mainly use the `div` element when you want to group HTML elements that will share a set of CSS styles.
|
||||
|
||||
Below the `p` element, add a `div` element. This `div` will be a container for your book cards.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `div` element.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('div'));
|
||||
```
|
||||
|
||||
Your `div` element should be below your `p` element.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('p + div'));
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
--fcc-editable-region--
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
---
|
||||
id: 68ec6d9a315221aa31e54816
|
||||
title: Step 4
|
||||
challengeType: 0
|
||||
dashedName: step-4
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The `class` attribute is used to identify one or more elements for styling. Unlike the `id` attribute, class names do not need to be unique: multiple elements can share the same class.
|
||||
|
||||
Here is an example:
|
||||
|
||||
```html
|
||||
<p class="example">example paragraph</p>
|
||||
```
|
||||
|
||||
Add a `class` attribute to your `div` element and set its value to `card-container`.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your `div` element should have a `class` attribute.
|
||||
|
||||
```js
|
||||
assert.isTrue(document.querySelector('div')?.hasAttribute('class'));
|
||||
```
|
||||
|
||||
Your `div` element should have a `class` attribute with the value of `card-container`.
|
||||
|
||||
```js
|
||||
assert.equal(document.querySelector('div')?.className, 'card-container');
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
--fcc-editable-region--
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
---
|
||||
id: 68ec6e8d0caee3afaaf142ef
|
||||
title: Step 5
|
||||
challengeType: 0
|
||||
dashedName: step-5
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the element having a `class` of `card-container`, create another `div` element. This `div` will represent the first book card.
|
||||
|
||||
Add a `class` attribute to this new `div` element and set the value of the `class` attribute to `card`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `div` element nested inside the element with a class of `card-container`.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('.card-container div'));
|
||||
```
|
||||
|
||||
Your new `div` element should have a `class` attribute.
|
||||
|
||||
```js
|
||||
assert.isTrue(document.querySelector('.card-container div')?.hasAttribute('class'));
|
||||
```
|
||||
|
||||
Your new `div` element should have a `class` having the value of `card`.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('.card-container div.card'));
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
--fcc-editable-region--
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
---
|
||||
id: 68ec9332a9b5b2b32487bd00
|
||||
title: Step 6
|
||||
challengeType: 0
|
||||
dashedName: step-6
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The `id` attribute adds a unique identifier to an HTML element. Each `id` should be unique within a page and should only be used once.
|
||||
|
||||
`id` values cannot contain spaces and should only contain letters, digits, underscores, and dashes.
|
||||
|
||||
Here is an example:
|
||||
|
||||
```html
|
||||
<p id="para">example paragraph</p>
|
||||
```
|
||||
|
||||
Add an `id` attribute to your element having a class of `card` and set its value to `sally-adventure-book`.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your element with a class of `card` should have an `id` attribute.
|
||||
|
||||
```js
|
||||
assert.isTrue(document.querySelector('.card')?.hasAttribute('id'));
|
||||
```
|
||||
|
||||
Your element having a class of `card` should have an `id` having the value of `sally-adventure-book`.
|
||||
|
||||
```js
|
||||
assert.equal(document.querySelector('.card')?.id, 'sally-adventure-book');
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
--fcc-editable-region--
|
||||
<div class="card">
|
||||
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
</div>
|
||||
```
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
---
|
||||
id: 68ec98b38d83a3c28dd30efe
|
||||
title: Step 7
|
||||
challengeType: 0
|
||||
dashedName: step-7
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the first element having a class of `card`, add an `h2` element with the text `Sally's SciFi Adventure`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have an `h2` element nested inside the element having a class of `card`.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('.card h2'));
|
||||
```
|
||||
|
||||
Your `h2` element's text should be `Sally's SciFi Adventure`.
|
||||
|
||||
```js
|
||||
assert.equal(document.querySelector('.card h2')?.innerText.trim(), "Sally's SciFi Adventure");
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
--fcc-editable-region--
|
||||
<div class="card" id="sally-adventure-book">
|
||||
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
</div>
|
||||
```
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
---
|
||||
id: 68ec99e478211dc578699944
|
||||
title: Step 8
|
||||
challengeType: 0
|
||||
dashedName: step-8
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Below the `h2` element in the first element having a class of `card`, add a `p` element with the following text:
|
||||
|
||||
```md
|
||||
This is an epic story of Sally and her dog Rex as they navigate through other worlds.
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `p` element nested inside the element having a class of `card`.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('.card p'));
|
||||
```
|
||||
|
||||
Your `p` element's text should be `This is an epic story of Sally and her dog Rex as they navigate through other worlds.`.
|
||||
|
||||
```js
|
||||
assert.equal(document.querySelector('.card p')?.innerText.trim(), "This is an epic story of Sally and her dog Rex as they navigate through other worlds.");
|
||||
```
|
||||
|
||||
Your `p` element should be below your `h2` element.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('.card h2 + p'));
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
--fcc-editable-region--
|
||||
<div class="card" id="sally-adventure-book">
|
||||
<h2>Sally's SciFi Adventure</h2>
|
||||
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
</div>
|
||||
```
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
---
|
||||
id: 68eca11e99e3c5c894ca9d69
|
||||
title: Step 9
|
||||
challengeType: 0
|
||||
dashedName: step-9
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The `button` element is used to create clickable buttons on a webpage. Buttons are interactive elements that users can click to perform actions.
|
||||
|
||||
You can add multiple elements inside a `div` element to group related content. Add a `button` element inside the element that has a `class` of `card`, give the button a `class` attribute set to `btn`, and the text `Buy Now`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `button` element nested inside the element that has a class of `card`.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('.card button'));
|
||||
```
|
||||
|
||||
Your `button` element should have a `class` attribute.
|
||||
|
||||
```js
|
||||
assert.isTrue(document.querySelector('.card button')?.hasAttribute('class'));
|
||||
```
|
||||
|
||||
Your `button` element should have a `class` that has a value of `btn`.
|
||||
|
||||
```js
|
||||
assert.equal(document.querySelector('.card button')?.className, 'btn');
|
||||
```
|
||||
|
||||
Your `button` element's text should be `Buy Now`.
|
||||
|
||||
```js
|
||||
assert.equal(document.querySelector('.card button')?.innerText.trim(), 'Buy Now');
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
--fcc-editable-region--
|
||||
<div class="card" id="sally-adventure-book">
|
||||
<h2>Sally's SciFi Adventure</h2>
|
||||
<p>This is an epic story of Sally and her dog Rex as they navigate through other worlds.</p>
|
||||
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
</div>
|
||||
```
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
---
|
||||
id: 68eca2a795b333ca5fee30a8
|
||||
title: Step 10
|
||||
challengeType: 0
|
||||
dashedName: step-10
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now create a second book card. Add another `div` element with the `class` attribute set to `card`. Notice how you can reuse the same class name for multiple elements to apply consistent styling.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have two `div` elements with a `class` attribute having a value of `card`.
|
||||
|
||||
```js
|
||||
assert.lengthOf(document.querySelectorAll('.card'), 2);
|
||||
```
|
||||
|
||||
The second element with a class of `card` should be inside the element having a class of `card-container`.
|
||||
|
||||
```js
|
||||
assert.lengthOf(document.querySelectorAll('.card-container .card'), 2);
|
||||
```
|
||||
|
||||
The two elements with a class of `card` should be siblings.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('.card + .card'));
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
--fcc-editable-region--
|
||||
<div class="card" id="sally-adventure-book">
|
||||
<h2>Sally's SciFi Adventure</h2>
|
||||
<p>This is an epic story of Sally and her dog Rex as they navigate through other worlds.</p>
|
||||
<button class="btn">Buy Now</button>
|
||||
</div>
|
||||
|
||||
--fcc-editable-region--
|
||||
</div>
|
||||
```
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
---
|
||||
id: 68eca3cfeebef2cd8cc5f814
|
||||
title: Step 11
|
||||
challengeType: 0
|
||||
dashedName: step-11
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Add an `id` attribute to your second element having a class of `card` and set its value to `dave-cooking-book`. Remember that each `id` must be unique.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your second element having a class of `card` should have an `id` attribute.
|
||||
|
||||
```js
|
||||
const cards = document.querySelectorAll('.card');
|
||||
assert.isTrue(cards[1]?.hasAttribute('id'));
|
||||
```
|
||||
|
||||
Your second element having a class of`card` should have an `id` with value of `dave-cooking-book`.
|
||||
|
||||
```js
|
||||
const cards = document.querySelectorAll('.card');
|
||||
assert.equal(cards[1]?.id, 'dave-cooking-book');
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
<div class="card" id="sally-adventure-book">
|
||||
<h2>Sally's SciFi Adventure</h2>
|
||||
<p>This is an epic story of Sally and her dog Rex as they navigate through other worlds.</p>
|
||||
<button class="btn">Buy Now</button>
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
<div class="card">
|
||||
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
</div>
|
||||
```
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
---
|
||||
id: 68eca4c4b0f952cf09fabe09
|
||||
title: Step 12
|
||||
challengeType: 0
|
||||
dashedName: step-12
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the second element having a class of `card`, add an `h2` element with the text `Dave's Cooking Adventure`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have an `h2` element nested inside the second element that has a class of `card`.
|
||||
|
||||
```js
|
||||
const cards = document.querySelectorAll('.card');
|
||||
assert.exists(cards[1]?.querySelector('h2'));
|
||||
```
|
||||
|
||||
The `h2` element inside the second element having a class of `card` should have a text of `Dave's Cooking Adventure`.
|
||||
|
||||
```js
|
||||
const cards = document.querySelectorAll('.card');
|
||||
assert.equal(cards[1]?.querySelector('h2')?.innerText.trim(), "Dave's Cooking Adventure");
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
<div class="card" id="sally-adventure-book">
|
||||
<h2>Sally's SciFi Adventure</h2>
|
||||
<p>This is an epic story of Sally and her dog Rex as they navigate through other worlds.</p>
|
||||
<button class="btn">Buy Now</button>
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
<div class="card" id="dave-cooking-book">
|
||||
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
</div>
|
||||
```
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
---
|
||||
id: 68eca5412b5dd9d06b3d6404
|
||||
title: Step 13
|
||||
challengeType: 0
|
||||
dashedName: step-13
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Below the `h2` element in the second card, add a `p` element with this text:
|
||||
|
||||
```md
|
||||
This is the story of Dave as he learns to cook everything from pancakes to pasta, one recipe at a time.
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `p` element nested inside the second element that has a class of `card`.
|
||||
|
||||
```js
|
||||
const cards = document.querySelectorAll('.card');
|
||||
assert.exists(cards[1]?.querySelector('p'));
|
||||
```
|
||||
|
||||
Your second card's `p` element's text should be `This is the story of Dave as he learns to cook everything from pancakes to pasta, one recipe at a time.`.
|
||||
|
||||
```js
|
||||
const cards = document.querySelectorAll('.card');
|
||||
assert.equal(cards[1]?.querySelector('p')?.innerText.trim(), "This is the story of Dave as he learns to cook everything from pancakes to pasta, one recipe at a time.");
|
||||
```
|
||||
|
||||
Your second card's `p` element should be below your `h2` element.
|
||||
|
||||
```js
|
||||
const cards = document.querySelectorAll('.card');
|
||||
assert.exists(cards[1]?.querySelector('h2 + p'));
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
<div class="card" id="sally-adventure-book">
|
||||
<h2>Sally's SciFi Adventure</h2>
|
||||
<p>This is an epic story of Sally and her dog Rex as they navigate through other worlds.</p>
|
||||
<button class="btn">Buy Now</button>
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
<div class="card" id="dave-cooking-book">
|
||||
<h2>Dave's Cooking Adventure</h2>
|
||||
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
</div>
|
||||
```
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
---
|
||||
id: 68eca5c0065c82d256d29ca3
|
||||
title: Step 14
|
||||
challengeType: 0
|
||||
dashedName: step-14
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the second card, add a `button` element with the `class` attribute set to `btn` and the text `Buy Now`.
|
||||
|
||||
Both `button` elements now share the same `class`, which means they can be styled consistently together.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `button` element nested inside the second element that has a class of `card`.
|
||||
|
||||
```js
|
||||
const cards = document.querySelectorAll('.card');
|
||||
assert.exists(cards[1]?.querySelector('button'));
|
||||
```
|
||||
|
||||
Your second card's `button` element should have a `class` attribute.
|
||||
|
||||
```js
|
||||
const cards = document.querySelectorAll('.card');
|
||||
assert.isTrue(cards[1]?.querySelector('button')?.hasAttribute('class'));
|
||||
```
|
||||
|
||||
Your second card's `button` element should have a `class` with the value of `btn`.
|
||||
|
||||
```js
|
||||
const cards = document.querySelectorAll('.card');
|
||||
assert.equal(cards[1]?.querySelector('button')?.className, 'btn');
|
||||
```
|
||||
|
||||
Your second card's `button` element's text should be `Buy Now`.
|
||||
|
||||
```js
|
||||
const cards = document.querySelectorAll('.card');
|
||||
assert.equal(cards[1]?.querySelector('button')?.innerText.trim(), 'Buy Now');
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
<div class="card" id="sally-adventure-book">
|
||||
<h2>Sally's SciFi Adventure</h2>
|
||||
<p>This is an epic story of Sally and her dog Rex as they navigate through other worlds.</p>
|
||||
<button class="btn">Buy Now</button>
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
<div class="card" id="dave-cooking-book">
|
||||
<h2>Dave's Cooking Adventure</h2>
|
||||
<p>This is the story of Dave as he learns to cook everything from pancakes to pasta, one recipe at a time.</p>
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
</div>
|
||||
```
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
---
|
||||
id: 68eca6364c5616d393389a30
|
||||
title: Step 15
|
||||
challengeType: 0
|
||||
dashedName: step-15
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Below the element with the class `card-container`, add a new `p` element with this text:
|
||||
|
||||
```md
|
||||
Review your selections and continue to checkout.
|
||||
```
|
||||
|
||||
Below the `p` element, create a `div` element with the `class` attribute set to `btn-container`. This container will group your navigation button elements.
|
||||
|
||||
# --hints--
|
||||
|
||||
The newly added `p` element should be below the element with a class of `card-container`.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('.card-container + p'));
|
||||
```
|
||||
|
||||
Your new `p` element's text should be `Review your selections and continue to checkout.`.
|
||||
|
||||
```js
|
||||
const cardContainer = document.querySelector('.card-container');
|
||||
assert.equal(cardContainer?.nextElementSibling?.innerText.trim(), 'Review your selections and continue to checkout.');
|
||||
```
|
||||
|
||||
You should have a `div` element with a `class` of `btn-container`.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('div.btn-container'));
|
||||
```
|
||||
|
||||
Your `div` element having a `class` of `btn-container` should come after the newly added `p` element.
|
||||
|
||||
```js
|
||||
assert.exists(document.querySelector('p + .btn-container'));
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
--fcc-editable-region--
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
<div class="card" id="sally-adventure-book">
|
||||
<h2>Sally's SciFi Adventure</h2>
|
||||
<p>This is an epic story of Sally and her dog Rex as they navigate through other worlds.</p>
|
||||
<button class="btn">Buy Now</button>
|
||||
</div>
|
||||
<div class="card" id="dave-cooking-book">
|
||||
<h2>Dave's Cooking Adventure</h2>
|
||||
<p>This is the story of Dave as he learns to cook everything from pancakes to pasta, one recipe at a time.</p>
|
||||
<button class="btn">Buy Now</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
---
|
||||
id: 68eca6e5a6759ed4ea0034dc
|
||||
title: Step 16
|
||||
challengeType: 0
|
||||
dashedName: step-16
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the element with a class of `btn-container`, add two `button` elements:
|
||||
|
||||
First button:
|
||||
|
||||
- Id: `view-cart-btn`
|
||||
- Class: `btn`
|
||||
- Text: `View Cart`
|
||||
|
||||
Second button:
|
||||
|
||||
- Id: `checkout-btn`
|
||||
- Class: `btn`
|
||||
- Text: `Checkout`
|
||||
|
||||
|
||||
Congratulations! You have successfully built the structure of a bookstore page using divs, classes, and ids to organize your content. You used classes to group elements that share styling (the card divs and buttons), and you used unique ids to identify specific elements (individual book cards and action buttons).
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have two `button` elements nested inside the `.btn-container` element.
|
||||
|
||||
```js
|
||||
assert.lengthOf(document.querySelectorAll('.btn-container button'), 2);
|
||||
```
|
||||
|
||||
Your first button inside element with the class of `btn-container` should have an `id` attribute with the value of `view-cart-btn`.
|
||||
|
||||
```js
|
||||
const buttons = document.querySelectorAll('.btn-container button');
|
||||
assert.equal(buttons[0]?.id, 'view-cart-btn');
|
||||
```
|
||||
|
||||
Your first button inside the element having a class of `btn-container` should have a `class` attribute with the value of `btn`.
|
||||
|
||||
```js
|
||||
const buttons = document.querySelectorAll('.btn-container button');
|
||||
assert.equal(buttons[0]?.className, 'btn');
|
||||
```
|
||||
|
||||
Your first button's text should be `View Cart`.
|
||||
|
||||
```js
|
||||
const buttons = document.querySelectorAll('.btn-container button');
|
||||
assert.equal(buttons[0]?.innerText.trim(), 'View Cart');
|
||||
```
|
||||
|
||||
Your second button inside the element with a class of `btn-container` should have an `id` attribute with the value of `checkout-btn`.
|
||||
|
||||
```js
|
||||
const buttons = document.querySelectorAll('.btn-container button');
|
||||
assert.equal(buttons[1]?.id, 'checkout-btn');
|
||||
```
|
||||
|
||||
Your second button inside the element with `class="btn-container"` should have a `class` attribute with the value of `btn`.
|
||||
|
||||
```js
|
||||
const buttons = document.querySelectorAll('.btn-container button');
|
||||
assert.equal(buttons[1]?.className, 'btn');
|
||||
```
|
||||
|
||||
Your second button's text should be `Checkout`.
|
||||
|
||||
```js
|
||||
const buttons = document.querySelectorAll('.btn-container button');
|
||||
assert.equal(buttons[1]?.innerText.trim(), 'Checkout');
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
<div class="card-container">
|
||||
<div class="card" id="sally-adventure-book">
|
||||
<h2>Sally's SciFi Adventure</h2>
|
||||
<p>This is an epic story of Sally and her dog Rex as they navigate through other worlds.</p>
|
||||
<button class="btn">Buy Now</button>
|
||||
</div>
|
||||
<div class="card" id="dave-cooking-book">
|
||||
<h2>Dave's Cooking Adventure</h2>
|
||||
<p>This is the story of Dave as he learns to cook everything from pancakes to pasta, one recipe at a time.</p>
|
||||
<button class="btn">Buy Now</button>
|
||||
</div>
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
<p>Review your selections and continue to checkout.</p>
|
||||
<div class="btn-container">
|
||||
|
||||
</div>
|
||||
--fcc-editable-region--
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```html
|
||||
<h1>XYZ Bookstore</h1>
|
||||
<p>Browse our collection of amazing books!</p>
|
||||
|
||||
<div class="card-container">
|
||||
<div class="card" id="sally-adventure-book">
|
||||
<h2>Sally's SciFi Adventure</h2>
|
||||
<p>
|
||||
This is an epic story of Sally and her dog Rex as they navigate
|
||||
through other worlds.
|
||||
</p>
|
||||
<button class="btn">Buy Now</button>
|
||||
</div>
|
||||
|
||||
<div class="card" id="dave-cooking-book">
|
||||
<h2>Dave's Cooking Adventure</h2>
|
||||
<p>
|
||||
This is the story of Dave as he learns to cook everything from
|
||||
pancakes to pasta, one recipe at a time.
|
||||
</p>
|
||||
<button class="btn">Buy Now</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Review your selections and continue to checkout.</p>
|
||||
|
||||
<div class="btn-container">
|
||||
<button id="view-cart-btn" class="btn">View Cart</button>
|
||||
<button id="checkout-btn" class="btn">Checkout</button>
|
||||
</div>
|
||||
```
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "Build a Bookstore Page",
|
||||
"isUpcomingChange": false,
|
||||
"dashedName": "workshop-bookstore-page",
|
||||
"helpCategory": "HTML-CSS",
|
||||
"blockLayout": "challenge-grid",
|
||||
"challengeOrder": [
|
||||
{ "id": "68e97fe79367ad7b5dd6c9cd", "title": "Step 1" },
|
||||
{ "id": "68ebdbacdd3fa474132cc975", "title": "Step 2" },
|
||||
{ "id": "68ec6cd5b7e8f5a8f7319e32", "title": "Step 3" },
|
||||
{ "id": "68ec6d9a315221aa31e54816", "title": "Step 4" },
|
||||
{ "id": "68ec6e8d0caee3afaaf142ef", "title": "Step 5" },
|
||||
{ "id": "68ec9332a9b5b2b32487bd00", "title": "Step 6" },
|
||||
{ "id": "68ec98b38d83a3c28dd30efe", "title": "Step 7" },
|
||||
{ "id": "68ec99e478211dc578699944", "title": "Step 8" },
|
||||
{ "id": "68eca11e99e3c5c894ca9d69", "title": "Step 9" },
|
||||
{ "id": "68eca2a795b333ca5fee30a8", "title": "Step 10" },
|
||||
{ "id": "68eca3cfeebef2cd8cc5f814", "title": "Step 11" },
|
||||
{ "id": "68eca4c4b0f952cf09fabe09", "title": "Step 12" },
|
||||
{ "id": "68eca5412b5dd9d06b3d6404", "title": "Step 13" },
|
||||
{ "id": "68eca5c0065c82d256d29ca3", "title": "Step 14" },
|
||||
{ "id": "68eca6364c5616d393389a30", "title": "Step 15" },
|
||||
{ "id": "68eca6e5a6759ed4ea0034dc", "title": "Step 16" }
|
||||
],
|
||||
"blockLabel": "workshop",
|
||||
"usesMultifileEditor": true,
|
||||
"hasEditableBoundaries": true
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
"workshop-cat-photo-app",
|
||||
"lab-recipe-page",
|
||||
"lecture-html-fundamentals",
|
||||
"workshop-bookstore-page",
|
||||
"lecture-understanding-how-html-affects-seo",
|
||||
"lab-travel-agency-page",
|
||||
"lecture-working-with-audio-and-video-elements",
|
||||
|
||||
Reference in New Issue
Block a user