feat(curriculum): add iframe video workshop (#62053)

Co-authored-by: Sem Bauke <sem@freecodecamp.org>
Co-authored-by: Ilenia <26656284+ilenia-magoni@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jessica Wilkins <67210629+jdwilkin4@users.noreply.github.com>
This commit is contained in:
Kolade Chris
2025-09-30 09:41:45 +01:00
committed by GitHub
parent d7505e9833
commit b60dc22ea2
12 changed files with 504 additions and 0 deletions

View File

@@ -2151,6 +2151,12 @@
"In these lectures, you will learn how to work with the <code>iframe</code> element which is used to embed an external site on your web page."
]
},
"workshop-build-a-video-display-using-iframe": {
"title": "Build a Video Display Using iframe",
"intro": [
"In this workshop, you'll learn how to work with the <code>iframe</code> element by building a video display."
]
},
"lab-video-compilation-page": {
"title": "Build a Video Compilation Page",
"intro": [

View File

@@ -0,0 +1,9 @@
---
title: Introduction to the Build a Video Display Using iframe
block: workshop-build-a-video-display-using-iframe
superBlock: full-stack-developer
---
## Introduction to the Build a Video Display Using iframe
This workshop focuses on how to build a video display feature with the `iframe` element.

View File

@@ -0,0 +1,47 @@
---
id: 68b94f23f7b3ee14078c89c5
title: Step 1
challengeType: 0
dashedName: step-1
demoType: onLoad
---
# --description--
In this workshop, you will use the `iframe` element to display a video. The basic HTML boilerplate has been prepared for you.
Begin by creating an `h1` element with the text `iframe Video Display`.
# --hints--
You should have an `h1` element.
```js
assert.exists(document.querySelector('h1'))
```
Your `h1` element should have the text `iframe Video Display`.
```js
assert.equal(document.querySelector('h1')?.textContent, 'iframe Video Display')
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Display Videos in an iframe</title>
</head>
<body>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```

View File

@@ -0,0 +1,45 @@
---
id: 68ba9c4f1688914d72876093
title: Step 2
challengeType: 0
dashedName: step-2
---
# --description--
Now, create an `iframe` element. Don't put anything in it yet.
# --hints--
You should have an `iframe` element.
```js
assert.exists(document.querySelector('iframe'))
```
Your `iframe` element should be empty.
```js
assert.equal(document.querySelector('iframe')?.innerHTML.trim(), '')
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Display Videos in an iframe</title>
</head>
<body>
<h1>iframe Video Display</h1>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```

View File

@@ -0,0 +1,51 @@
---
id: 68ba9c4f1688914d72876094
title: Step 3
challengeType: 0
dashedName: step-3
---
# --description--
In the first lesson on the `iframe` element, you learned it's a replaced element just like `img`. That means it can also take the `width` and `height` properties to determine how tall and wide it should be.
Give your `iframe` element a `width` of `560` and a `height` of `315`.
# --hints--
Your `iframe` element should have a `width` attribute set to `560`.
```js
const iframeEl = document.querySelector('iframe')
assert.equal(iframeEl?.getAttribute('width'), '560')
```
Your `iframe` element should have a `height` attribute set to `315`.
```js
const iframeEl = document.querySelector('iframe')
assert.equal(iframeEl?.getAttribute('height'), '315')
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Display Videos in an iframe</title>
</head>
<body>
<h1>iframe Video Display</h1>
--fcc-editable-region--
<iframe>
</iframe>
--fcc-editable-region--
</body>
</html>
```

View File

@@ -0,0 +1,50 @@
---
id: 68ba9c4f1688914d72876095
title: Step 4
challengeType: 0
dashedName: step-4
---
# --description--
The `iframe` element also takes an `src` attribute with a value that indicates the URL or the path of the resource to display.
Add an `src` attribute of `https://www.youtube.com/embed/I0_951_MPE0` to your `iframe` element.
At this point, you should see the video displaying on the page, but there are some more attributes you need to add.
# --hints--
Your `iframe` element should have an `src` attribute set to `https://www.youtube.com/embed/I0_951_MPE0`.
```js
const iframeEl = document.querySelector('iframe')
assert.equal(iframeEl?.getAttribute('src'), 'https://www.youtube.com/embed/I0_951_MPE0')
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Display Videos in an iframe</title>
</head>
<body>
<h1>iframe Video Display</h1>
--fcc-editable-region--
<iframe
width="560"
height="315"
>
</iframe>
--fcc-editable-region--
</body>
</html>
```

View File

@@ -0,0 +1,79 @@
---
id: 68ba9c4f1688914d72876096
title: Step 5
challengeType: 0
dashedName: step-5
---
# --description--
One of the attributes is `allow`. It's like a permission list that tells the browser what features the `iframe` is allowed to use.
Here's an `iframe` element with the `allow` attribute:
```html
<iframe
allow="accelerometer autoplay clipboard-write encrypted-media gyroscope picture-in-picture web-share"
></iframe>
```
Add the `allow` attribute with the value `accelerometer`, `autoplay`, and `clipboard-write`.
`accelerometer` lets the `iframe` use motion sensors so it can detect things like device tilting and rotation. `autoplay` lets the video start playing automatically, and `clipboard-write` lets the iframe write data to the users clipboard.
# --hints--
Your `iframe` element should have an `allow` attribute set to `accelerometer`.
```js
const iframeEl = document.querySelector('iframe')
const iframeElAllowAttr = iframeEl?.getAttribute('allow')
const accelerometer = iframeElAllowAttr.trim().split(' ')[0]
assert.strictEqual(accelerometer, 'accelerometer')
```
The `allow` attribute of your `iframe` element should have `autoplay` as one of its values.
```js
const iframeEl = document.querySelector('iframe')
const iframeElAllowAttr = iframeEl?.getAttribute('allow')
const autoplay = iframeElAllowAttr.trim().split(' ')[1]
assert.strictEqual(autoplay, 'autoplay')
```
The `allow` attribute of your `iframe` element should have `clipboard-write` as one of its values.
```js
const iframeEl = document.querySelector('iframe')
const iframeElAllowAttr = iframeEl?.getAttribute('allow')
const clipboardWrite = iframeElAllowAttr.trim().split(' ')[2]
assert.strictEqual(clipboardWrite, 'clipboard-write')
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Display Videos in an iframe</title>
</head>
<body>
<h1>iframe Video Display</h1>
--fcc-editable-region--
<iframe
width="560"
height="315"
src="https://www.youtube.com/embed/I0_951_MPE0"
>
</iframe>
--fcc-editable-region--
</body>
</html>
```

View File

@@ -0,0 +1,69 @@
---
id: 68ba9c4f1688914d72876097
title: Step 6
challengeType: 0
dashedName: step-6
---
# --description--
Add `encrypted-media`, `gyroscope`, and `web-share` to the existing values in the `allow` attribute.
These three will allow the use of encrypted media extensions to protect the video, let the iframe pop out into picture-in-picture mode when needed, and allow sharing the iframe content through the device's native share dialogs.
# --hints--
The `allow` attribute of your `iframe` element should have `encrypted-media` as one of its values.
```js
const iframeEl = document.querySelector('iframe')
const iframeElAllowAttr = iframeEl?.getAttribute('allow')
const encryptedMedia = iframeElAllowAttr.trim().split(' ')[3]
assert.strictEqual(encryptedMedia, 'encrypted-media')
```
The `allow` attribute of your `iframe` element should have `gyroscope` as one of its values.
```js
const iframeEl = document.querySelector('iframe')
const iframeElAllowAttr = iframeEl?.getAttribute('allow')
const gyroscope = iframeElAllowAttr.trim().split(' ')[4]
assert.strictEqual(gyroscope, 'gyroscope')
```
The `allow` attribute of your `iframe` element should have `web-share` as one of its values.
```js
const iframeEl = document.querySelector('iframe')
const iframeElAllowAttr = iframeEl?.getAttribute('allow')
const webShare = iframeElAllowAttr.trim().split(' ')[5]
assert.strictEqual(webShare, 'web-share')
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Display Videos in an iframe</title>
</head>
<body>
<h1>iframe Video Display</h1>
--fcc-editable-region--
<iframe
width="560"
height="315"
src="https://www.youtube.com/embed/I0_951_MPE0"
allow="accelerometer autoplay clipboard-write"
>
</iframe>
--fcc-editable-region--
</body>
</html>
```

View File

@@ -0,0 +1,49 @@
---
id: 68ba9c4f1688914d72876098
title: Step 7
challengeType: 0
dashedName: step-7
---
# --description--
The next attribute you'll add is `referrerpolicy`. It is the rule that determines how much detail you share when your page connects to another page.
Add the `referrerpolicy` attribute and set it to `strict-origin-when-cross-origin`. This shares the full address on the same site, only the site name on other sites, and nothing on insecure sites.
# --hints--
Your `iframe` element should have a `referrerpolicy` attribute set to `strict-origin-when-cross-origin`.
```js
const iframeEl = document.querySelector('iframe')
assert.equal(iframeEl?.getAttribute('referrerpolicy'), 'strict-origin-when-cross-origin')
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Display Videos in an iframe</title>
</head>
<body>
<h1>iframe Video Display</h1>
--fcc-editable-region--
<iframe
width="560"
height="315"
src="https://www.youtube.com/embed/I0_951_MPE0"
allow="accelerometer autoplay clipboard-write encrypted-media gyroscope web-share"
>
</iframe>
--fcc-editable-region--
</body>
</html>
```

View File

@@ -0,0 +1,78 @@
---
id: 68ba9c4f1688914d72876099
title: Step 8
challengeType: 0
dashedName: step-8
---
# --description--
Last but not least, the attribute you will add is `allowfullscreen`. As it implies, it allows the video to be viewed in full screen mode.
With that, the workshop is completed!
# --hints--
Your `iframe` element should have a `allowfullscreen` attribute.
```js
const iframeEl = document.querySelector('iframe')
assert.exists(iframeEl?.getAttribute('allowfullscreen'))
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Display Videos in an iframe</title>
</head>
<body>
<h1>iframe Video Display</h1>
--fcc-editable-region--
<iframe
width="560"
height="315"
src="https://www.youtube.com/embed/I0_951_MPE0"
allow="accelerometer autoplay clipboard-write encrypted-media gyroscope web-share"
referrerpolicy="strict-origin-when-cross-origin"
>
</iframe>
--fcc-editable-region--
</body>
</html>
```
# --solutions--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Display Videos in an iframe</title>
</head>
<body>
<h1>iframe Video Display</h1>
<br />
<iframe
width="560"
height="315"
src="https://www.youtube.com/embed/I0_951_MPE0"
allow="accelerometer autoplay clipboard-write encrypted-media gyroscope web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen
>
</iframe>
</body>
</html>
```

View File

@@ -0,0 +1,20 @@
{
"name": "Build a Video Display Using iframe",
"isUpcomingChange": false,
"dashedName": "workshop-build-a-video-display-using-iframe",
"helpCategory": "HTML-CSS",
"blockType": "workshop",
"blockLayout": "challenge-grid",
"challengeOrder": [
{ "id": "68b94f23f7b3ee14078c89c5", "title": "Step 1" },
{ "id": "68ba9c4f1688914d72876093", "title": "Step 2" },
{ "id": "68ba9c4f1688914d72876094", "title": "Step 3" },
{ "id": "68ba9c4f1688914d72876095", "title": "Step 4" },
{ "id": "68ba9c4f1688914d72876096", "title": "Step 5" },
{ "id": "68ba9c4f1688914d72876097", "title": "Step 6" },
{ "id": "68ba9c4f1688914d72876098", "title": "Step 7" },
{ "id": "68ba9c4f1688914d72876099", "title": "Step 8" }
],
"usesMultifileEditor": true,
"hasEditableBoundaries": true
}

View File

@@ -20,6 +20,7 @@
"lecture-working-with-images-and-svgs",
"workshop-build-a-heart-icon",
"lecture-working-with-media",
"workshop-build-a-video-display-using-iframe",
"lab-video-compilation-page",
"lecture-working-with-links",
"review-basic-html",