--- id: 587d78af367417b2b2512b04 title: Costruire la Landing Page per un prodotto challengeType: 14 forumTopicId: 301144 dashedName: build-a-product-landing-page --- # --description-- **Obbiettivo:** Crea un'app funzionalmente simile a https://product-landing-page.freecodecamp.rocks **User story:** 1. La pagina di destinazione del prodotto dovrebbe avere un elemento `header` con un corrispondente `id="header"` 1. Puoi vedere un immagine dentro l'elemento `header` con un attributo corrispondente `id="header-img"` (un logo sarebbe una buona immagine qui) 1. Dentro l'elemento `#header`, puoi vedere un elemento `nav` con un corrispondente attributo `id="nav-bar"` 1. Puoi vedere almeno tre elementi cliccabili dentro l'elemento `nav`, ognuno con una classe di `nav-link` 1. Quando clicchi su un pulsante `.nav-link` dentro l'elemento `nav`, vieni portato alla sezione corrispondente nella pagina 1. Puoi vedere un video sul prodotto incorporato nella pagina con `id="video"` 1. La tua pagina ha un elemento `form` con un corrispondente attributo `id="form"` 1. Dentro il modulo, c'è un campo `input` con un `id="email"` dove puoi inserire un indirizzo email 1. Il campo input `#email` dovrebbe avere testo segnaposto per far sapere agli utenti per che cosa è il campo 1. Il campo input `#email` usa la validazione HTML5 per confermare che il testo inserito è un indirizzo email 1. Dentro il modulo, c'è un `input` per inviare con un corrispondente `id="submit"` 1. Quando clicchi l'elemento `#submit`, l'email è inviata a una pagina statica (usa l'URL non funzionante: `https://www.freecodecamp.com/email-submit`) 1. La barra di navigazione dovrebbe essere sempre in cima alla porta di visualizzazione 1. La tua pagina del prodotto dovrebbe avere almeno un media query 1. La tua pagina del prodotto dovrebbe utilizzare CSS flexbox almeno una volta Soddisfa le storie utente e passa tutti i test qua sotto per completare il progetto. Usa il tuo stile personale. Buon divertimento! **Nota:** Assicurati di aggiungere `` nel tuo HTML per linkare il tuo foglio di stile e applicare il tuo CSS # --hints-- Dovresti avere un elemento `header` con un `id` di `header` ```js const el = document.getElementById('header') assert(!!el && el.tagName === 'HEADER') ``` Dovresti avere un elemento `img` con un attributo `id` di `header-img` ```js const el = document.getElementById('header-img') assert(!!el && el.tagName === 'IMG') ``` L'elemento `#header-img` dovrebbe essere un discendente di `#header` ```js const els = document.querySelectorAll('#header #header-img') assert(els.length > 0) ``` L'elemento `#header-img` dovrebbe avere un attributo `src` ```js const el = document.getElementById('header-img') assert(!!el && !!el.src) ``` L'attributo `src` dell'elemento `#header-img` dovrebbe essere un URL valido (inizia con `http`) ```js const el = document.getElementById('header-img') assert(!!el && /^http/.test(el.src)) ``` Dovresti avere un elemento `nav` con un `id` di `nav-bar` ```js const el = document.getElementById('nav-bar') assert(!!el && el.tagName === 'NAV') ``` Il tuo elemento `#nav-bar` dovrebbe essere un discendente dell'elemento `#header` ```js const els = document.querySelectorAll('#header #nav-bar') assert(els.length > 0) ``` Dovresti avere almeno 3 elementi `.nav-link` dentro `#nav-bar` ```js const els = document.querySelectorAll('#nav-bar .nav-link') assert(els.length >= 3) ``` Ogni elemento `.nav-link` dovrebbe avere un attributo `href` ```js const els = document.querySelectorAll('.nav-link') els.forEach(el => { if (!el.href) assert(false) }) assert(els.length > 0) ``` Ogni elemento `.nav-link` dovrebbe essere un collegamento ad un elemento corrispondente nella pagina (cioè ha un attributo `href` con il valore dell'id di un altro elemento, ad esempio `#footer`) ```js const els = document.querySelectorAll('.nav-link') els.forEach(el => { const linkDestination = el.getAttribute('href').slice(1) if (!document.getElementById(linkDestination)) assert(false) }) assert(els.length > 0) ``` Dovresti avere un elemento `video` o `iframe` con un `id` di `video` ```js const el = document.getElementById('video') assert(!!el && (el.tagName === 'VIDEO' || el.tagName === 'IFRAME')) ``` L'elemento `#video` dovrebbe avere un attributo `src` ```js let el = document.getElementById('video') const sourceNode = el.children; let sourceElement = null; if (sourceNode.length) { sourceElement = [...video.children].filter(el => el.localName === 'source')[0]; } if (sourceElement) { el = sourceElement; } assert(el.hasAttribute('src')); ``` Dovresti avere un elemento `form` con un attributo `id` di `form` ```js const el = document.getElementById('form') assert(!!el && el.tagName === 'FORM') ``` Dovresti avere un elemento `input` con un `id` di `email` ```js const el = document.getElementById('email') assert(!!el && el.tagName === 'INPUT') ``` L'elemento `#email` dovrebbe essere un discendente di `#form` ```js const els = document.querySelectorAll('#form #email') assert(els.length > 0) ``` L'elemento `#email`dovrebbe avere un attributo `placeholder` con del testo segnaposto ```js const el = document.getElementById('email') assert(!!el && !!el.placeholder && el.placeholder.length > 0) ``` L'elemento `#email` dovrebbe usare la validazione HTML5 impostando l'attributo `type` a `email` ```js const el = document.getElementById('email') assert(!!el && el.type === 'email') ``` Dovresti avere un elemento `input` con un `id` di `submit` ```js const el = document.getElementById('submit') assert(!!el && el.tagName === 'INPUT') ``` L'elemento `#submit` dovrebbe essere un discendente di `#form` ```js const els = document.querySelectorAll('#form #submit') assert(els.length > 0) ``` L'elemento `#submit` dovrebbe avere un attributo `type` con valore di `submit` ```js const el = document.getElementById('submit') assert(!!el && el.type === 'submit') ``` L'elemento `#form` dovrebbe avere un attributo `action` con valore di `https://www.freecodecamp.com/email-submit` ```js const el = document.getElementById('form') assert(!!el && el.action === 'https://www.freecodecamp.com/email-submit') ``` L'elemento `#email` dovrebbe avere un attributo `name` con valore di `email` ```js const el = document.getElementById('email') assert(!!el && el.name === 'email') ``` L'elemento `#nav-bar` dovrebbe sempre essere in cima al viewport ```js (async () => { const timeout = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)); const header = document.getElementById('header'); const headerChildren = header.children; const navbarCandidates = [header, ...headerChildren]; // Return smallest top position of all navbar candidates const getNavbarPosition = (candidates = []) => { return candidates.reduce( (min, candidate) => Math.min(min, Math.abs(candidate?.getBoundingClientRect().top)), Infinity ); }; assert.approximately( getNavbarPosition(navbarCandidates), 0, 15, '#header or one of its children should be at the top of the viewport ' ); window.scroll(0, 500); await timeout(1); assert.approximately( getNavbarPosition(navbarCandidates), 0, 15, '#header or one of its children should be at the top of the ' + 'viewport even after scrolling ' ); window.scroll(0, 0); })(); ``` La pagina dovrebbe avere almeno un media query ```js const htmlSourceAttr = Array.from(document.querySelectorAll('source')).map(el => el.getAttribute('media')) const cssCheck = new __helpers.CSSHelp(document).getCSSRules('media') assert(cssCheck.length > 0 || htmlSourceAttr.length > 0); ``` La tua pagina dovrebbe usare CSS Flexbox almeno una volta ```js const stylesheet = new __helpers.CSSHelp(document).getStyleSheet() const cssRules = new __helpers.CSSHelp(document).styleSheetToCssRulesArray(stylesheet) const usesFlex = cssRules.find(rule => { return rule.style?.display === 'flex' || rule.style?.display === 'inline-flex' }) assert(usesFlex) ``` # --seed-- ## --seed-contents-- ```html ``` ```css ``` ## --solutions-- ```html Product Landing Page

Pokemon Daycare Service

What we offer

Guaranteed friendly and loving staff!
Comfortable environment for Pokemon to explore and play!
Multiple membership plans to fit your lifestyle!

Check us out!

A sneak peek into our facility:

Membership Plans

Basic Membership
  • One Pokemon
  • Food and berries provided
$9.99/month
Silver Membership
  • Up to Three Pokemon
  • Food and berries provided
  • Grooming and accessories included
$19.99/month
Gold Membership
  • Up to six Pokemon!
  • Food and berries provided
  • Grooming and accessories included
  • Personal training for each Pokemon
  • Breeding and egg hatching
$29.99/month

Sign up for our newsletter!

``` ```css body { background-color: #3a3240; color: white; } main { max-width: 750px; margin: 50px auto; } input { background-color: #92869c; } a:not(.nav-link) { color: white; } #header-img { max-height: 25px; } #nav-bar { position: fixed; width: 100%; text-align: center; top: 0%; background-color: #92869c; } h1 { text-align: center; } body { text-align: center; } footer { text-align: center; } #bullet { max-height: 25px; } .flex-here { display: flex; justify-content: center; } .flex-left { height: 25px; } .flex-mem { display: flex; justify-content: center; } .flex-mem-box { background-color: #92869c; border-color: black; border-width: 5px; border-style: solid; margin: 10px; padding: 10px; color: black; } @media (max-width: 350px) { #video { width: 300; height: 200; } } ```