<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ 作品集 - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ freeCodeCamp 是一个免费学习编程的开发者社区，涵盖 Python、HTML、CSS、React、Vue、BootStrap、JSON 教程等，还有活跃的技术论坛和丰富的社区活动，在你学习编程和找工作时为你提供建议和帮助。 ]]>
        </description>
        <link>https://www.freecodecamp.org/chinese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ 作品集 - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/chinese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 11 Jun 2026 20:33:10 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/chinese/news/tag/portfolio/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ 如何使用 HTML、CSS、JavaScript 和 Bootstrap5 创建作品集网站 ]]>
                </title>
                <description>
                    <![CDATA[ 原文：How to Create a Portfolio Website Using HTML, CSS, JavaScript, and Bootstrap 5 [https://www.freecodecamp.org/news/how-to-create-a-portfolio-website-using-html-css-javascript-and-bootstrap/] ，作者：Sampurna Chapagain [https://www.freecodecamp.org/news/author/sampurna/] 如果你是 Web 开发人员或 Web 设计师，那么拥有一个作品集网站对你来说至关重要。你可以在上面展示自己的信息，并且运用你的相关技能和经验展示你的最佳作品。 在这篇文章中，我们将讨论创建作品集网站的一些好处。然后，我将向你展示如何使用 HTML、CSS、JavaScript 和 Bootstrap5 为自己创建一个漂亮的响应式作品集网站。 目录  * 拥有作品集网站的好处  * Bootstrap 是什么  * 文件夹结构  * 如何给你的作品集添加 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/how-to-create-a-portfolio-website-using-html-css-javascript-and-bootstrap/</link>
                <guid isPermaLink="false">62a811f3150818084d6d4303</guid>
                
                    <category>
                        <![CDATA[ 作品集 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chengjun.L ]]>
                </dc:creator>
                <pubDate>Thu, 16 Jun 2022 08:00:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/06/Untitled-design-6-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>原文：<a href="https://www.freecodecamp.org/news/how-to-create-a-portfolio-website-using-html-css-javascript-and-bootstrap/">How to Create a Portfolio Website Using HTML, CSS, JavaScript, and Bootstrap 5</a>，作者：<a href="https://www.freecodecamp.org/news/author/sampurna/">Sampurna Chapagain</a></p><p>如果你是 Web 开发人员或 Web 设计师，那么拥有一个作品集网站对你来说至关重要。你可以在上面展示自己的信息，并且运用你的相关技能和经验展示你的最佳作品。</p><p>在这篇文章中，我们将讨论创建作品集网站的一些好处。然后，我将向你展示如何使用 HTML、CSS、JavaScript 和 Bootstrap5 为自己创建一个漂亮的响应式作品集网站。</p><h2 id="-"><strong>目录</strong></h2><ul><li>拥有作品集网站的好处</li><li>Bootstrap 是什么</li><li>文件夹结构</li><li>如何给你的作品集添加导航菜单</li><li>如何给作品集添加主视觉</li><li>如何创建关于部分</li><li>如何创建服务部分</li><li>如何在页面滚动上向导航栏添加深色背景颜色</li><li>如何创建作品集部分</li><li>如何创建联系部分</li><li>如何创建页脚部分</li><li>最后润色</li><li>总结</li></ul><h2 id="--1">拥有作品集网站的好处</h2><p>拥有一个作品集网站有几个好处，包括：</p><ul><li>它提供了一个平台来展示你的相关技能和经验</li><li>它显示了你的个性</li><li>它让招聘经理找到你，而不是你联系他们</li><li>人们可以在 Google 等搜索引擎中搜索到你</li></ul><h2 id="bootstrap-"><strong>Bootstrap 是什么</strong></h2><p>Bootstrap 是一个流行的前端 CSS 框架，用于开发响应式和移动端友好的网站。 Bootstrap 的最新版本是第 5 版。你可以在<a href="https://getbootstrap.com/docs/5.0/getting-started/introduction/">此处</a>找到 Bootstrap5 的官方文档。</p><h2 id="--2"><strong>文件夹结构</strong></h2><p>我们现在将开始创建作品集网站。</p><p>首先，让我们创建文件夹结构。你可以在 <a href="https://github.com/SampurnaC/portfolio_website_fcc/tree/portfolio-starter-files">GitHub</a> 上获取项目启动文件。此外，你可以访问<a href="https://brad-portfolio.netlify.app/">此处</a>查看该项目的 demo。</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-from-2022-01-22-19-10-25.png" class="kg-image" alt="Screenshot-from-2022-01-22-19-10-25" width="600" height="400" loading="lazy"><figcaption>项目文件夹结构</figcaption></figure><p>文件夹结构由 index.html、style.css 和 script.js 文件和一个 images 文件夹组成。我们将在 style.css 文件中编写所有 CSS，在 script.js 文件中编写 JavaScript。</p><p>在 index.html 文件中，你可以看到带有 Bootstrap CDN 的 HTML 样板代码、<a href="https://fontawesome.com/">font awesome 套件</a>以及指向外部样式表和 JavaScript 的链接。</p><p>这里，script.js 文件是在加载完所有 HTML 代码后加载的。</p><h2 id="--3">如何给你的作品集添加导航菜单</h2><p>现在，在我们的项目中添加一个导航菜单。它将帮助访问者找到他们正在寻找的相关信息。</p><p>我们将在 nav 元素中使用 Bootstrap 的 <code>fixed-top</code> 类来将导航栏保持在页面顶部。 navbar 也有一个 <code>navbar-brand</code> 类，我们将人名作为品牌保存。</p><pre><code class="language-html">&lt;nav class="navbar navbar-expand-lg fixed-top navbarScroll"&gt;
        &lt;div class="container"&gt;
            &lt;a class="navbar-brand" href="#"&gt;Brad&lt;/a&gt;
            &lt;button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"&gt;
                &lt;span class="navbar-toggler-icon"&gt;&lt;/span&gt;
            &lt;/button&gt;
            &lt;div class="collapse navbar-collapse" id="navbarSupportedContent"&gt;
                &lt;ul class="navbar-nav ms-auto"&gt;
                    &lt;li class="nav-item active"&gt;
                        &lt;a class="nav-link" href="#home"&gt;Home&lt;/a&gt;
                    &lt;/li&gt;
                    &lt;li class="nav-item"&gt;
                        &lt;a class="nav-link" href="#about"&gt;About&lt;/a&gt;
                    &lt;/li&gt;
                    &lt;li class="nav-item"&gt;
                        &lt;a class="nav-link" href="#services"&gt;Services&lt;/a&gt;
                    &lt;/li&gt;
                    &lt;li class="nav-item"&gt;
                        &lt;a class="nav-link" href="#portfolio"&gt;Portfolio&lt;/a&gt;
                    &lt;/li&gt;
                    &lt;li class="nav-item"&gt;
                        &lt;a class="nav-link" href="#contact"&gt;Contact&lt;/a&gt;
                    &lt;/li&gt;
                &lt;/ul&gt;
                
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/nav&gt;</code></pre><p>导航栏具有以下功能：</p><ul><li>它有六个链接：home（主页）、about（关于）、services（服务）、portfolio（作品集）、contact（联系）和 footer（页脚）</li><li>它有一个透明的背景，稍后我们将在页面滚动时添加深色背景</li><li>它可以在较小的设备上滚动</li></ul><p>你可以在<a href="https://getbootstrap.com/docs/5.0/components/navbar/">此处</a>找到有关 Bootstrap5 导航栏功能的更多详细信息。</p><p>但是，导航栏在滚动时出现问题。它在整个页面中完全透明，这会导致可读性问题。我们将在完成 services 部分后解决此问题，以便你正确地理解该问题。</p><h2 id="-hero-header-">如何给作品集添加主视觉（Hero Header）</h2><p>现在，我们将在中心添加一个带有一些文本的主视觉。主视觉是一个网页设计术语，指的是显示公司或个人主要目标的高质量全幅图像、具有代表性的图像或其他引人注目的元素。它有助于吸引用户访问你的网站。</p><pre><code class="language-html"> &lt;!-- main banner --&gt;
    &lt;section class="bgimage" id="home"&gt;
        &lt;div class="container-fluid"&gt;
            &lt;div class="row"&gt;
            &lt;div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 hero-text"&gt;
                &lt;h2 class="hero_title"&gt;Hi, it's me Brad&lt;/h2&gt;
                &lt;p class="hero_desc"&gt;I am a professional freelancer in New York City&lt;/p&gt;
            &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/section&gt;</code></pre><p>另外，让我们在 style.css 文件中添加上述代码的 CSS：</p><pre><code class="language-css">/* hero background image */
.bgimage {
    height:100vh;
    background: url('images/heroImage.jpeg');
    background-size:cover;
    position:relative;
}
/* text css above hero image*/
.hero_title {
    font-size: 4.5rem;
}
.hero_desc {
    font-size: 2rem;
}
.hero-text {
    text-align: center;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: white;
}</code></pre><p>在这里我们可以看到该部分有一个名为 <code>bgimage</code> 的 id，它负责以全宽显示主视觉图像。它还借助上述 CSS 在图像上方的中心显示一些文本。</p><p>这是该网站到目前为止的导航栏和主视觉部分的外观：</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-from-2022-01-25-10-13-25.png" class="kg-image" alt="Screenshot-from-2022-01-25-10-13-25" width="600" height="400" loading="lazy"><figcaption>带有导航栏的主视觉图像</figcaption></figure><h2 id="--4"><strong>如何创建关于部分</strong></h2><p>关于页面包含有关你和你的背景的重要信息。你的作品集网站的访问者可以通过你在此页面中提供的信息了解你。</p><p>我们将在行的左侧添加一个图像，在右侧我们将在本节中添加快速介绍。让我们使用下面的代码来演示它：</p><pre><code class="language-html">&lt;!-- about section--&gt;
    &lt;section id="about"&gt;
        &lt;div class="container mt-4 pt-4"&gt;
            &lt;h1 class="text-center"&gt;About Me&lt;/h1&gt;
            &lt;div class="row mt-4"&gt;
                &lt;div class="col-lg-4"&gt;
                    &lt;img src="images/about.jpeg" class= "imageAboutPage" alt=""&gt;
                &lt;/div&gt;

                &lt;div class="col-lg-8"&gt;
                    &lt;p&gt; Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged
                        
                    &lt;/p&gt;
                    &lt;div class="row mt-3"&gt;
                        &lt;div class="col-md-6"&gt;
                            &lt;ul&gt;
                                &lt;li&gt;Name: David Parker&lt;/li&gt;
                                &lt;li&gt;Age: 28&lt;/li&gt;
                                &lt;li&gt;Occupation: Web Developer&lt;/li&gt;

                            &lt;/ul&gt;
                        &lt;/div&gt;
                        &lt;div class="col-md-6"&gt;
                            &lt;ul&gt;
                                &lt;li&gt;Name: David Parker&lt;/li&gt;
                                &lt;li&gt;Age: 28&lt;/li&gt;
                                &lt;li&gt;Occupation: Web Developer&lt;/li&gt;

                            &lt;/ul&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class="row mt-3"&gt;
                        &lt;p&gt; Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                            Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                        &lt;/p&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
    &lt;/section&gt;
</code></pre><p>让我们为左侧图像添加一些 CSS：</p><pre><code class="language-css">/* about section image css */
.imageAboutPage {
    width: 100%;
}</code></pre><p>这将创建一个关于部分。你可以根据你的用例修改内容。我们添加了名为 <code>mt-4</code> 和 <code>pt-4</code> 的类以及容器类，它将顶部 margin 和顶部 padding 设置为 1.5 rem。</p><p>该行有两列。一个有 <code>col-lg-4</code> 类用于显示图像，它将占据左列，有 4 部分网格用于大屏幕。</p><p>下一列有一个 <code>col-lg-8</code> 类，它将占据右列，并带有 8 部分网格，用于更大的屏幕。</p><p>对于中小屏幕，它们会相互重叠，我们可以在下面的 GIF 文件中看到：</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/01/about.gif" class="kg-image" alt="about" width="600" height="400" loading="lazy"><figcaption>关于部分</figcaption></figure><h2 id="--5"><strong>如何创建服务部分</strong></h2><p>本部分有助于将网站访问者转化为潜在客户。你在这里展示自己可提供哪些特定的细分的服务。</p><p>让我们为此部分添加代码，并在下面进行描述：</p><pre><code class="language-html">&lt;!-- services section--&gt;
    &lt;section id="services"&gt;
        &lt;div class="container"&gt;
            &lt;h1 class="text-center"&gt;Services&lt;/h1&gt;
            &lt;div class="row"&gt;
                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card servicesText"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;i class="fas servicesIcon fa-clock"&gt;&lt;/i&gt;
                            &lt;h4 class="card-title mt-3"&gt;Website Development&lt;/h4&gt;
                            &lt;p class="card-text mt-3"&gt;Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            &lt;/p&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;  
                &lt;/div&gt;
                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card servicesText"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;i class='fas servicesIcon fa-layer-group'&gt;&lt;/i&gt;
                            &lt;h4 class="card-title mt-3"&gt;Website Design&lt;/h4&gt;
                            &lt;p class="card-text mt-3"&gt;Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            &lt;/p&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;  
                &lt;/div&gt;

                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card servicesText"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;i class='far servicesIcon fa-check-circle'&gt;&lt;/i&gt;
                            &lt;h4 class="card-title mt-3"&gt;Website Deployment&lt;/h4&gt;
                            &lt;p class="card-text mt-3"&gt;Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            &lt;/p&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;  
                &lt;/div&gt;
            &lt;/div&gt;

            &lt;div class="row"&gt;
                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card servicesText"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;i class='fas servicesIcon fa-search'&gt;&lt;/i&gt;
                            &lt;h4 class="card-title mt-3"&gt;SEO&lt;/h4&gt;
                            &lt;p class="card-text mt-3"&gt;Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            &lt;/p&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;  
                &lt;/div&gt;

                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card servicesText"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;i class='fas servicesIcon fa-shield-alt'&gt;&lt;/i&gt;
                            &lt;h4 class="card-title mt-3"&gt;DevOps&lt;/h4&gt;
                            &lt;p class="card-text mt-3"&gt;Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            &lt;/p&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;  
                &lt;/div&gt;

                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card servicesText"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;i class='fas servicesIcon fa-wrench'&gt;&lt;/i&gt;
                            &lt;h4 class="card-title mt-3"&gt;QA&lt;/h4&gt;
                            &lt;p class="card-text mt-3"&gt;Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            &lt;/p&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;  
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/section&gt;</code></pre><p>由于该网站面向 Web 开发人员和设计人员，因此我列出了 Web 开发人员或设计人员可能提供的一些服务。</p><p>我们使用 Bootstrap 卡片来显示服务。我们的服务部分有 2 行和 3 列。对于宽度大于等于 992px 的大屏，三张卡片连续显示。对于宽度小于 992px 的屏幕，一行中只会显示一张卡片。</p><p>你可以在<a href="https://getbootstrap.com/docs/5.0/layout/breakpoints/">此处</a>找到有关 Bootstrap 断点的更多信息。</p><p>此外，每张卡片中都添加了字体以使它们看起来更好。</p><p>如果没有 CSS，服务部分将如下所示：</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-from-2022-01-23-14-01-00.png" class="kg-image" alt="Screenshot-from-2022-01-23-14-01-00" width="600" height="400" loading="lazy"></figure><p>所以，让我们添加一些 CSS 来增加字体图标的字体大小和卡片高度，并在用户将鼠标悬停在卡片上时添加一些额外的颜色。</p><pre><code class="language-css">/* services section css */
.servicesText.card {
    height: 280px;
    cursor: pointer;
  }
.servicesIcon {
    font-size: 36px;
    text-align: center;
    width: 100%;
}
.card-title {
    text-align: center;
}
.card:hover .servicesIcon {
    color: #008000;
}
.servicesText:hover {
    border: 1px solid #008000;
}</code></pre><p>这就是我们的服务部分现在的样子：</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/01/services.gif" class="kg-image" alt="services" width="600" height="400" loading="lazy"><figcaption>Services&nbsp;</figcaption></figure><h2 id="--6">如何在页面滚动上向导航栏添加深色背景颜色</h2><p>如果你查看上面的 GIF，你会发现导航栏在整个页面中都是透明的，这会导致可读性问题。所以让我们努力解决这个问题。</p><p>我们将编写一些 JavaScript 和 CSS 来解决这个问题。我们将添加一个 <code>navbarDark</code> 类，以便在页面滚动时为导航栏显示深色背景色。</p><p>为此，我们需要转到 script.js 文件并添加以下代码：</p><pre><code class="language-javascript">// add class navbarDark on navbar scroll
const header = document.querySelector('.navbar');

window.onscroll = function() {
    var top = window.scrollY;
    if(top &gt;=100) {
        header.classList.add('navbarDark');
    }
    else {
        header.classList.remove('navbarDark');
    }
}</code></pre><p>现在，让我们分解上面的代码：</p><ul><li>header 保存 nav 元素的值，querySelector 方法返回与 CSS 选择器匹配的第一个元素（在本例中为 <code>.navbar</code>）。</li><li><code>window.onscroll</code> 在滚动事件发生时触发。</li><li><code>window.scrollY</code> 返回文档垂直滚动的像素数，并将其值分配给名为 <code>top</code> 的变量。</li><li>如果 <code>top</code> 的值大于等于100，则在 header 中添加一个 <code>navbarDark</code> 类。</li></ul><p>让我们快速为 <code>navbarDark</code> 类添加 CSS。为此，请转到你的 style.css 文件并添加以下代码：</p><pre><code class="language-css">/* display background color black on navbar scroll */
.navbarScroll.navbarDark {
    background-color: black;
}</code></pre><p>这是导航栏现在的样子：</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/01/navbar.gif" class="kg-image" alt="navbar" width="600" height="400" loading="lazy"><figcaption>页面滚动时导航栏上的深色背景</figcaption></figure><h2 id="--7">如何创建作品集部分</h2><p>这个部分包括你的最佳作品。人们可以看到你的能力，并且展示过去的出色工作肯定会吸引更多的潜在客户或招聘人员。因此，请仅在这个部分中添加你的最佳作品。</p><p>我们将使用 Bootstrap 卡片来展示作品集项目，将有 2 行，每行将有 3 列卡片。</p><p>这将是作品集部分的代码：</p><pre><code class="language-html">&lt;!-- portfolio section--&gt;
    &lt;section id="portfolio"&gt;
        &lt;div class="container mt-3"&gt;
            &lt;h1 class="text-center"&gt;Portfolio&lt;/h1&gt;
            &lt;div class="row"&gt;
                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card"&gt;
                        &lt;img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;h4 class="card-title"&gt;YouTube Clone&lt;/h4&gt;
                            &lt;p class="card-text"&gt;Lorem Ipsum is simply dummy text of the printing and typesetting industry.&lt;/p&gt;
                            &lt;div class="text-center"&gt;
                                &lt;a href="#" class="btn btn-success"&gt;Link&lt;/a&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;

                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card portfolioContent"&gt;
                        &lt;img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;h4 class="card-title"&gt;Quiz App&lt;/h4&gt;
                            &lt;p class="card-text"&gt;Lorem Ipsum is simply dummy text of the printing and typesetting industry.&lt;/p&gt;
                            &lt;div class="text-center"&gt;
                                &lt;a href="#" class="btn btn-success"&gt;Link&lt;/a&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;

                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card portfolioContent"&gt;
                        &lt;img class="card-img-top" src="images/portfolioImage3.jpg" alt="Card image" style="width:100%"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;h4 class="card-title"&gt;Product Landing Page&lt;/h4&gt;
                            &lt;p class="card-text"&gt;Lorem Ipsum is simply dummy text of the printing and typesetting industry.&lt;/p&gt;
                            &lt;div class="text-center"&gt;
                                &lt;a href="#" class="btn btn-success"&gt;Link&lt;/a&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;br&gt;
            &lt;div class="row"&gt;
                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card portfolioContent"&gt;
                        &lt;img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;h4 class="card-title"&gt;Messaging Service&lt;/h4&gt;
                            &lt;p class="card-text"&gt;Lorem Ipsum is simply dummy text of the printing and typesetting industry.&lt;/p&gt;
                            &lt;div class="text-center"&gt;
                                &lt;a href="#" class="btn btn-success"&gt;Link&lt;/a&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;

                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card portfolioContent"&gt;
                        &lt;img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;h4 class="card-title"&gt;Twitter Clone&lt;/h4&gt;
                            &lt;p class="card-text"&gt;Lorem Ipsum is simply dummy text of the printing and typesetting industry.&lt;/p&gt;
                            &lt;div class="text-center"&gt;
                                &lt;a href="#" class="btn btn-success"&gt;Link&lt;/a&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;

                &lt;div class="col-lg-4 mt-4"&gt;
                    &lt;div class="card portfolioContent"&gt;
                        &lt;img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%"&gt;
                        &lt;div class="card-body"&gt;
                            &lt;h4 class="card-title"&gt;Blog App&lt;/h4&gt;
                            &lt;p class="card-text"&gt;Lorem Ipsum is simply dummy text of the printing and typesetting industry.&lt;/p&gt;
                            &lt;div class="text-center"&gt;
                                &lt;a href="#" class="btn btn-success"&gt;Link&lt;/a&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
    &lt;/section&gt;</code></pre><p>每张卡片都有图片、标题、描述和项目链接。对于断点宽度大于等于 992px 的大屏幕，连续显示三张卡片，但对于宽度小于 992px 的屏幕，仅连续显示一张卡片。</p><p>下面的 GIF 显示了作品集部分现在的样子：</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/01/portfolio.gif" class="kg-image" alt="portfolio" width="600" height="400" loading="lazy"><figcaption>作品集</figcaption></figure><h2 id="--8">如何创建联系部分</h2><p>你应该在此部分中包含你的联系信息，以便访问者在他们想雇用你时可以与你联系。</p><p>我们的联系部分将在单行中包含 2 列：用于位置的谷歌地图和联系表格。</p><p>要嵌入 Google 地图，你需要执行以下步骤：</p><ul><li>访问 <a href="https://www.embed-map.com">https://www.embed-map.com</a></li><li>输入你的位置</li><li>单击<strong>生成 HTML 代码</strong>按钮，该按钮将提供你的 Google 地图 HTML 代码</li></ul><p>我们的代码将如下所示，其中包含联系表格：</p><pre><code class="language-html">&lt;!-- contact section--&gt;
    &lt;section id="contact"&gt;
        &lt;div class="container mt-3 contactContent"&gt;
            &lt;h1 class="text-center"&gt;Contact Me&lt;/h1&gt;

            &lt;div class="row mt-4"&gt;
                &lt;div class="col-lg-6"&gt;
                    &lt;!-- to edit google map goto https://www.embed-map.com type your location, generate html code and copy the html  --&gt;
                    &lt;div style="max-width:100%;overflow:hidden;color:red;width:500px;height:500px;"&gt;
                        &lt;div id="embedmap-canvas" style="height:100%; width:100%;max-width:100%;"&gt;
                            &lt;iframe style="height:100%;width:100%;border:0;" frameborder="0" src="https://www.google.com/maps/embed/v1/place?q=new+york&amp;key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8"&gt;
                            &lt;/iframe&gt;
                        &lt;/div&gt;
                        &lt;a class="googlemaps-html" href="https://www.embed-map.com" id="get-data-forembedmap"&gt;https://www.embed-map.com&lt;/a&gt;
                        &lt;style&gt;#embedmap-canvas img{max-width:none!important;background:none!important;font-size: inherit;font-weight:inherit;}
                        &lt;/style&gt;
                    &lt;/div&gt;
                &lt;/div&gt;

                &lt;div class="col-lg-6"&gt;
                    &lt;!-- form fields --&gt;
                    &lt;form&gt;
                        &lt;input type="text" class="form-control form-control-lg" placeholder="Name"&gt;
                        &lt;input type="email" class="form-control mt-3" placeholder="Email"&gt;
                        &lt;input type="text" class="form-control mt-3" placeholder="Subject"&gt;
                        &lt;div class="mb-3 mt-3"&gt;
                            &lt;textarea class="form-control" rows="5" id="comment" name="text" placeholder="Project Details"&gt;&lt;/textarea&gt;
                        &lt;/div&gt;
                    &lt;/form&gt;
                    &lt;button type="button" class="btn btn-success mt-3"&gt;Contact Me&lt;/button&gt;
                    
                &lt;/div&gt;

            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/section&gt;</code></pre><p>第一列将显示谷歌地图，下一列将显示联系表。</p><p>该表单有四个不同的字段：姓名、电子邮件、主题和项目详细信息。表单本身不提交请求。你需要将其与任何后端语言连接起来。或者，你可以简单地使用 <a href="https://www.netlify.com/products/forms/">Netlify 表单</a>或 <a href="https://formspree.io/">Formspree 表单</a>。</p><p>这是联系人部分的样子：</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-from-2022-01-25-11-31-56.png" class="kg-image" alt="Screenshot-from-2022-01-25-11-31-56" width="600" height="400" loading="lazy"><figcaption>Contact Section</figcaption></figure><h2 id="--9"><strong>如何创建页脚部分</strong></h2><p>现在我们来到了这篇文章的最后一部分，即页脚部分。我们已经在 index.html 文件中添加了指向字体 awesome CDN 的链接。</p><p>在页脚中，我们将通过 font awesome 图标添加指向社交媒体的链接。</p><pre><code class="language-html"> &lt;!-- footer section--&gt;
    &lt;footer id="footer"&gt;
        &lt;div class="container-fluid"&gt;
            &lt;!-- social media icons --&gt;
            &lt;div class="social-icons mt-4"&gt;
                &lt;a href="https://www.facebook.com/" target="_blank"&gt;&lt;i class="fab fa-facebook"&gt;&lt;/i&gt;&lt;/a&gt;
                &lt;a href="https://www.instagram.com/" target="_blank"&gt;&lt;i class="fab fa-instagram"&gt;&lt;/i&gt;&lt;/a&gt;
                &lt;a href="https://www.twitter.com/" target="_blank"&gt;&lt;i class="fab fa-twitter"&gt;&lt;/i&gt;&lt;/a&gt;
                &lt;a href="https://www.linkedin.com/" target="_blank"&gt;&lt;i class="fab fa-linkedin"&gt;&lt;/i&gt;&lt;/a&gt;
                &lt;a href="https://www.twitch.tv/" target="_blank"&gt;&lt;i class="fab fa-twitch"&gt;&lt;/i&gt;&lt;/a&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/footer&gt;</code></pre><p>如果没有 CSS，我们的页脚将如下所示：</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screenshot-from-2022-01-23-17-56-37.png" class="kg-image" alt="Screenshot-from-2022-01-23-17-56-37" width="600" height="400" loading="lazy"><figcaption>页脚没有添加样式</figcaption></figure><p>因此，让我们使用以下代码为页脚添加一些样式：</p><pre><code class="language-css">/* social media icons styling */
.social-icons {
    font-size: 36px;
    cursor: pointer;
}
.fa-facebook:hover,.fa-instagram:hover,.fa-twitter:hover,.fa-linkedin:hover, .fa-twitch:hover {
    color: #008000;
}
.fab {
    color: #000000;
}
/* footer styling */
#footer {
    background-color: #808080;
    text-align: center;
}</code></pre><p>图标现在显示在中心，带有悬停效果，我们可以在下面的 GIF 文件中看到。</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/01/footer.gif" class="kg-image" alt="footer" width="600" height="400" loading="lazy"><figcaption>页脚</figcaption></figure><h2 id="--10"><strong>最后润色</strong></h2><p>为了在所有部分之间添加一些间距，让我们添加更多样式：</p><pre><code class="language-css">/* spacing on all sections */
#about, #services, #portfolio, #contact {
    margin-top: 4rem;
    padding-top: 4rem;
}
#contact {
    padding-bottom: 4rem;
}</code></pre><p>现在我们已经完成了完整的作品集网站的制作。</p><p>你可以在<a href="https://github.com/SampurnaC/portfolio_website_fcc/tree/master">这里</a>找到这个项目的完整源代码。</p><h2 id="--11"><strong>总结</strong></h2><p>这就是如何使用 HTML、CSS、JavaScript 和 Bootstrap5 创建一个完整的响应式作品集网站。</p><p>在这篇文章中，我们看到了 Web 开发者和设计师创建一个作品集网站的一些好处。我们把整个网站分为不同的部分，并在创建过程中单独讨论了每一个部分。</p><p>你可以根据自己的使用情况来定制这个网站。</p><p>希望这篇文章对你有帮助，祝你编程愉快！</p><p>你可以在 <a href="https://twitter.com/saam_codes">Twitter</a> 上关注我，了解有关 Web 开发的更多内容。</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 如何使用 React 创建一个作品集网站 ]]>
                </title>
                <description>
                    <![CDATA[ 原文：How to Build a Portfolio Website with React [https://www.freecodecamp.org/news/build-portfolio-website-react/]，作者：Reed Barger [https://www.freecodecamp.org/news/author/reed/] 今天，你将为自己创建一个最重要的应用程序——你的作品集。 每个 React 开发者或者 Web 开发者通常需要向潜在的客户或者雇主展示自己能做什么。 在这篇文章里，我们将使用 React、Tailwind CSS、Netlify 等等行业标准工具创建一个作品集网站。 开始吧！ 作品集是怎样的 这是你将要建立的最终版本。 它的作用是展示你自己、你做过什么项目、你在做这些项目时用了什么技能，还有一个联系表单，以便客户或者雇主联系上你。 我们将使用什么工具  * 我们将用 React 来创建应用程序的用户界面。它将允许我们通过可重复使用的组件来组成登录页面的每一部分，以及添加我们想要的功能，例如博客。  * 为了设计我们的应 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/build-portfolio-website-react/</link>
                <guid isPermaLink="false">61de69586161280665ed7ff0</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 作品集 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 网站开发 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ luojiyin ]]>
                </dc:creator>
                <pubDate>Fri, 04 Feb 2022 05:00:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2022/01/react-portfolio-2021.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>原文：<a href="https://www.freecodecamp.org/news/build-portfolio-website-react/">How to Build a Portfolio Website with React</a>，作者：<a href="https://www.freecodecamp.org/news/author/reed/">Reed Barger</a></p><!--kg-card-begin: markdown--><p>今天，你将为自己创建一个最重要的应用程序——你的作品集。</p>
<p>每个 React 开发者或者 Web 开发者通常需要向潜在的客户或者雇主展示自己能做什么。</p>
<p>在这篇文章里，我们将使用 React、Tailwind CSS、Netlify 等等行业标准工具创建一个作品集网站。</p>
<p>开始吧！</p>
<h2 id="">作品集是怎样的</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/portfolio-1-min.gif" alt="portfolio-1-min" width="600" height="400" loading="lazy"></p>
<p>这是你将要建立的最终版本。</p>
<p>它的作用是展示你自己、你做过什么项目、你在做这些项目时用了什么技能，还有一个联系表单，以便客户或者雇主联系上你。</p>
<h2 id="">我们将使用什么工具</h2>
<ul>
<li>我们将用 React 来创建应用程序的用户界面。它将允许我们通过可重复使用的组件来组成登录页面的每一部分，以及添加我们想要的功能，例如博客。</li>
<li>为了设计我们的应用程序，我们将使用 Tailwind CSS。Tailwind 允许我们通过组合类名（classnames）将多种样式轻松应用到 React 项目上，给应用程序一个专业的外观。</li>
<li>为了把我们的应用程序部署到网络上，我们将使用免费的 Netlify。通过 CDN 的帮助下，用户可以通过我们自己的的域名快速访问到我们的项目。</li>
</ul>
<h2 id="">如何开始</h2>
<p><strong><a href="https://reedbarger.com/resources/react-portfolio-2021">你可以在这里下载我们项目的启动文件</a></strong>。</p>
<p>当你获取到代码，你要做的是把（解压好的）项目文件夹拖到代码编辑器中，然后在终端运行命令。</p>
<pre><code class="language-bash">npm install
</code></pre>
<p>然后可以开始了！</p>
<h2 id="">我需要使用什么工具来构建作品集</h2>
<p>从创建到部署应用程序，需要：</p>
<p>1、你的电脑安装 Node.js，你可以在 nodejs.org 下载安装程序。<br>
2、在你的电脑安装 Git，你可以在 git-scm.com 下载。<br>
3、我建议使用 VS Code 作为你的代码编辑器。你可以在 code.visualstudio.com 下载它。<br>
4、一个在 Netlify.com 上的免费的 Netlify 账户。<br>
5、一个免费的 GitHub 账号。</p>
<h2 id="">如何建立作品集的结构</h2>
<p>使用 React 的好处是，我们可以将我们的应用程序扩展到任意多的页面，并添加大量的内容，这是非常容易的。</p>
<p>但是，由于我们只处理一个页面，所以可以在应用程序组件中非常快速地找到需要的不同组件。我们将在顶部放一个导航栏，通过上面的链接可以跳转到作品集的不同部分。</p>
<p>然后，我们将有一个“关于”部分，这里包含我们的项目介绍、客户推荐以及联系表单。</p>
<p>这种快速的规划使我们能够弄清楚组件怎样命名，以什么顺序命名。下一步，把它们全部添加到我们的 App.js 文件夹中（在 src 文件夹）：</p>
<pre><code class="language-js">// src/App.js

import React from "react";

export default function App() {
  return (
    &lt;main&gt;
      &lt;Navbar /&gt;
      &lt;About /&gt;
      &lt;Projects /&gt;
      &lt;Skills /&gt;
      &lt;Testimonials /&gt;
      &lt;Contact /&gt;
    &lt;/main&gt;
  );
}
</code></pre>
<h2 id="">如何创建组件</h2>
<p>现在我们已经列出了所有这些组件，我们需要继续创建它们。</p>
<p>在源代码（src）文件夹中，我们将创建一个 <code>components</code> 文件夹，里面有我们需要的所有文件。</p>
<pre><code>my-portfolio
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
└── src
    ├── App.js
    ├── data.js
    ├── index.css
    ├── index.js
    └── components
        ├── About.js
        ├── Contact.js
        ├── Navbar.js
        ├── Projects.js
        ├── Skills.js
        └── Testimonials.js
</code></pre>
<p>然后我们将创建每个 React 组件的基本结构，并使用 <code>export default</code> 从该文件导出：</p>
<pre><code class="language-js">// src/components/About.js

export default function About() {}

// repeat the same basic structure for all 6 components（在所有的 6 个组件中重复相同的结构）
</code></pre>
<p>最后在 App.js 中导入它：</p>
<pre><code class="language-js">// src/App.js

import React from "react";
import About from "./components/About";
import Contact from "./components/Contact";
import Navbar from "./components/Navbar";
import Projects from "./components/Projects";
import Skills from "./components/Skills";
import Testimonials from "./components/Testimonials";

export default function App() {
  return (
    &lt;main&gt;
      &lt;Navbar /&gt;
      &lt;About /&gt;
      &lt;Projects /&gt;
      &lt;Skills /&gt;
      &lt;Testimonials /&gt;
      &lt;Contact /&gt;
    &lt;/main&gt;
  );
}
</code></pre>
<p><em>请注意，总共应该有 6 个组件</em></p>
<h2 id="tailwindcss">Tailwind CSS 介绍</h2>
<p>做完上面的，我们可以开始使用 Tailwind CSS 给我们的应用程序一个基本的外观。</p>
<p>使用 Tailwind CSS 的好处是，我们不必在 CSS 中手动编写任何样式，而是组合多个类（class）来创建我们想要的外观。</p>
<pre><code class="language-js">// src/App.js

import React from "react";
import About from "./components/About";
import Contact from "./components/Contact";
import Navbar from "./components/Navbar";
import Projects from "./components/Projects";
import Skills from "./components/Skills";
import Testimonials from "./components/Testimonials";

export default function App() {
  return (
    &lt;main className="text-gray-400 bg-gray-900 body-font"&gt;
      &lt;Navbar /&gt;
      &lt;About /&gt;
      &lt;Projects /&gt;
      &lt;Skills /&gt;
      &lt;Testimonials /&gt;
      &lt;Contact /&gt;
    &lt;/main&gt;
  );
}
</code></pre>
<h2 id="about">如何构建 <code>About</code> 组件</h2>
<p>现在开始第一部分，即 <code>about</code> 部分，介绍我们的基本情况和擅长的技能。</p>
<p>它还将包含联系表单的链接，以及我们过去的项目。由于这些链接将指向同一页面的不同部分，我们能使用 "/#projects" 和 "/#contact"。</p>
<p>为了使这些链接能跳转到每个部分，我们把项目部分 <code>id</code> 的属性设置为 <code>projects</code>，把联系部分的 <code>id</code> 属性设置为 <code>contact</code>。</p>
<pre><code class="language-js">// src/components/About.js

import React from "react";

export default function About() {
  return (
    &lt;section id="about"&gt;
      &lt;div className="container mx-auto flex px-10 py-20 md:flex-row flex-col items-center"&gt;
        &lt;div className="lg:flex-grow md:w-1/2 lg:pr-24 md:pr-16 flex flex-col md:items-start md:text-left mb-16 md:mb-0 items-center text-center"&gt;
          &lt;h1 className="title-font sm:text-4xl text-3xl mb-4 font-medium text-white"&gt;
            Hi, I'm Reed.
            &lt;br className="hidden lg:inline-block" /&gt;I love to build amazing
            apps.
          &lt;/h1&gt;
          &lt;p className="mb-8 leading-relaxed"&gt;
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui
            laborum quasi, incidunt dolore iste nostrum cupiditate voluptas?
            Laborum, voluptas natus?
          &lt;/p&gt;
          &lt;div className="flex justify-center"&gt;
            &lt;a
              href="#contact"
              className="inline-flex text-white bg-green-500 border-0 py-2 px-6 focus:outline-none hover:bg-green-600 rounded text-lg"&gt;
              Work With Me
            &lt;/a&gt;
            &lt;a
              href="#projects"
              className="ml-4 inline-flex text-gray-400 bg-gray-800 border-0 py-2 px-6 focus:outline-none hover:bg-gray-700 hover:text-white rounded text-lg"&gt;
              See My Past Work
            &lt;/a&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div className="lg:max-w-lg lg:w-full md:w-1/2 w-5/6"&gt;
          &lt;img
            className="object-cover object-center rounded"
            alt="hero"
            src="./coding.svg"
          /&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/section&gt;
  );
}
</code></pre>
<p>对于本部分右侧的图片，我使用的 <code>public</code> 文件夹中的一个 svg 文件（coding.svg）。</p>
<p>这个图片只是作为一个临时的占位符，我强烈建议你使用你自己的图片。</p>
<h2 id="projects">如何构建 <code>projects</code> 组件</h2>
<p>我们的项目部分是由一个 <code>section</code> 元素组成，id为 <code>prpjects</code>。这将是包含所有项目的图片集。</p>
<pre><code class="language-js">// src/components/Projects.js

import { CodeIcon } from "@heroicons/react/solid";
import React from "react";
import { projects } from "../data";

export default function Projects() {
  return (
    &lt;section id="projects" className="text-gray-400 bg-gray-900 body-font"&gt;
      &lt;div className="container px-5 py-10 mx-auto text-center lg:px-40"&gt;
        &lt;div className="flex flex-col w-full mb-20"&gt;
          &lt;CodeIcon className="mx-auto inline-block w-10 mb-4" /&gt;
          &lt;h1 className="sm:text-4xl text-3xl font-medium title-font mb-4 text-white"&gt;
            Apps I've Built
          &lt;/h1&gt;
          &lt;p className="lg:w-2/3 mx-auto leading-relaxed text-base"&gt;
            Lorem ipsum, dolor sit amet consectetur adipisicing elit. Explicabo
            facilis repellat ab cupiditate alias vero aliquid obcaecati quisquam
            fuga dolore.
          &lt;/p&gt;
        &lt;/div&gt;
        &lt;div className="flex flex-wrap -m-4"&gt;
          {projects.map((project) =&gt; (
            &lt;a
              href={project.link}
              key={project.image}
              className="sm:w-1/2 w-100 p-4"&gt;
              &lt;div className="flex relative"&gt;
                &lt;img
                  alt="gallery"
                  className="absolute inset-0 w-full h-full object-cover object-center"
                  src={project.image}
                /&gt;
                &lt;div className="px-8 py-10 relative z-10 w-full border-4 border-gray-800 bg-gray-900 opacity-0 hover:opacity-100"&gt;
                  &lt;h2 className="tracking-widest text-sm title-font font-medium text-green-400 mb-1"&gt;
                    {project.subtitle}
                  &lt;/h2&gt;
                  &lt;h1 className="title-font text-lg font-medium text-white mb-3"&gt;
                    {project.title}
                  &lt;/h1&gt;
                  &lt;p className="leading-relaxed"&gt;{project.description}&lt;/p&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/a&gt;
          ))}
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/section&gt;
  );
}
</code></pre>
<p>注意，我们还将使用库 <code>@heroicons/react</code>，以便将 SVG 图标写成 React 组件。</p>
<p>我们从同一个文件夹中的 <code>data.js</code> 文件导入一个项目数组。在那里，我们导出一个对象数组，每个对象包含项目的数据。</p>
<pre><code class="language-js">// src/data.js

export const projects = [
  {
    title: "React Reserve",
    subtitle: "MERN Stack",
    description:
      "Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium dolore rerum laborum iure enim sint nemo omnis voluptate exercitationem eius?",
    image: "./project-1.gif",
    link: "https://reactbootcamp.com",
  },
  {
    title: "React Tracks",
    subtitle: "React and Python",
    description:
      "Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium dolore rerum laborum iure enim sint nemo omnis voluptate exercitationem eius?",
    image: "./project-2.gif",
    link: "https://reedbarger.com",
  },
  {
    title: "DevChat",
    subtitle: "React and Firebase",
    description:
      "Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium dolore rerum laborum iure enim sint nemo omnis voluptate exercitationem eius?",
    image: "./project-3.gif",
    link: "https://jsbootcamp.com",
  },
  {
    title: "Epic Todo App",
    subtitle: "React Hooks",
    description:
      "Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium dolore rerum laborum iure enim sint nemo omnis voluptate exercitationem eius?",
    image: "./project-4.gif",
    link: "https://pythonbootcamp.com",
  },
];
</code></pre>
<h2 id="skills">如何构建 <code>Skills</code> 组件</h2>
<p>我们在这部分填写自己会的技能和技术。</p>
<p>这将包含一个简单的清单，列出在我们熟悉的主要工具，可用于雇主或客户的项目中。</p>
<p>再一次，我们将从 <code>data</code> 文件夹导入一个数组。但是这个数组是由字符串组成，是我们所知道的技能，如 JavaScript、React 和 Node。</p>
<pre><code class="language-js">// src/components/Skills.js

import { BadgeCheckIcon, ChipIcon } from "@heroicons/react/solid";
import React from "react";
import { skills } from "../data";

export default function Skills() {
  return (
    &lt;section id="skills"&gt;
      &lt;div className="container px-5 py-10 mx-auto"&gt;
        &lt;div className="text-center mb-20"&gt;
          &lt;ChipIcon className="w-10 inline-block mb-4" /&gt;
          &lt;h1 className="sm:text-4xl text-3xl font-medium title-font text-white mb-4"&gt;
            Skills &amp;amp; Technologies
          &lt;/h1&gt;
          &lt;p className="text-base leading-relaxed xl:w-2/4 lg:w-3/4 mx-auto"&gt;
            Lorem ipsum dolor sit amet consectetur, adipisicing elit. Nisi sit
            ipsa delectus eum quo voluptas aspernatur accusantium distinctio
            possimus est.
          &lt;/p&gt;
        &lt;/div&gt;
        &lt;div className="flex flex-wrap lg:w-4/5 sm:mx-auto sm:mb-2 -mx-2"&gt;
          {skills.map((skill) =&gt; (
            &lt;div key={skill} className="p-2 sm:w-1/2 w-full"&gt;
              &lt;div className="bg-gray-800 rounded flex p-4 h-full items-center"&gt;
                &lt;BadgeCheckIcon className="text-green-400 w-6 h-6 flex-shrink-0 mr-4" /&gt;
                &lt;span className="title-font font-medium text-white"&gt;
                  {skill}
                &lt;/span&gt;
              &lt;/div&gt;
            &lt;/div&gt;
          ))}
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/section&gt;
  );
}
</code></pre>
<h2 id="testimonials">如何构建 <code>Testimonials</code> 组件</h2>
<p>在 <code>Testimonials</code> 组件中，我们将列出一些过去的比较熟悉的客户的推荐信。</p>
<p>这些将由几个卡片组成，里面有推荐人和推荐人所在的公司。</p>
<p>我们将导入一个包含推荐信息的数组，里面的对象包含了评价、图片和公司。</p>
<pre><code class="language-js">// src/components/Testimonials

import React from "react";
import { TerminalIcon, UsersIcon } from "@heroicons/react/solid";
import { testimonials } from "../data";

export default function Testimonials() {
  return (
    &lt;section id="testimonials"&gt;
      &lt;div className="container px-5 py-10 mx-auto text-center"&gt;
        &lt;UsersIcon className="w-10 inline-block mb-4" /&gt;
        &lt;h1 className="sm:text-4xl text-3xl font-medium title-font text-white mb-12"&gt;
          Client Testimonials
        &lt;/h1&gt;
        &lt;div className="flex flex-wrap m-4"&gt;
          {testimonials.map((testimonial) =&gt; (
            &lt;div className="p-4 md:w-1/2 w-full"&gt;
              &lt;div className="h-full bg-gray-800 bg-opacity-40 p-8 rounded"&gt;
                &lt;TerminalIcon className="block w-8 text-gray-500 mb-4" /&gt;
                &lt;p className="leading-relaxed mb-6"&gt;{testimonial.quote}&lt;/p&gt;
                &lt;div className="inline-flex items-center"&gt;
                  &lt;img
                    alt="testimonial"
                    src={testimonial.image}
                    className="w-12 rounded-full flex-shrink-0 object-cover object-center"
                  /&gt;
                  &lt;span className="flex-grow flex flex-col pl-4"&gt;
                    &lt;span className="title-font font-medium text-white"&gt;
                      {testimonial.name}
                    &lt;/span&gt;
                    &lt;span className="text-gray-500 text-sm uppercase"&gt;
                      {testimonial.company}
                    &lt;/span&gt;
                  &lt;/span&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;
          ))}
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/section&gt;
  );
}
</code></pre>
<h2 id="contact">如何构建<code>Contact</code>组件</h2>
<p>在登录页的尾部，我们将加入联系表单，以便潜在的雇主能联系到我们。</p>
<p>这个表格包含 3 个输入：姓名、电子邮件和输入信息。</p>
<p>为了接收这些表格所提交的信息，我们将使用 Netlify 表格工具以轻松保存这些信息。</p>
<pre><code class="language-js">// src/components/Contact.js

import React from "react";

export default function Contact() {
  return (
    &lt;section id="contact" className="relative"&gt;
      &lt;div className="container px-5 py-10 mx-auto flex sm:flex-nowrap flex-wrap"&gt;
        &lt;div className="lg:w-2/3 md:w-1/2 bg-gray-900 rounded-lg overflow-hidden sm:mr-10 p-10 flex items-end justify-start relative"&gt;
          &lt;iframe
            width="100%"
            height="100%"
            title="map"
            className="absolute inset-0"
            frameBorder={0}
            marginHeight={0}
            marginWidth={0}
            style={{ filter: "opacity(0.7)" }}
            src="https://www.google.com/maps/embed/v1/place?q=97+warren+st+new+york+city&amp;key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8"
          /&gt;
          &lt;div className="bg-gray-900 relative flex flex-wrap py-6 rounded shadow-md"&gt;
            &lt;div className="lg:w-1/2 px-6"&gt;
              &lt;h2 className="title-font font-semibold text-white tracking-widest text-xs"&gt;
                ADDRESS
              &lt;/h2&gt;
              &lt;p className="mt-1"&gt;
                97 Warren St. &lt;br /&gt;
                New York, NY 10007
              &lt;/p&gt;
            &lt;/div&gt;
            &lt;div className="lg:w-1/2 px-6 mt-4 lg:mt-0"&gt;
              &lt;h2 className="title-font font-semibold text-white tracking-widest text-xs"&gt;
                EMAIL
              &lt;/h2&gt;
              &lt;a className="text-indigo-400 leading-relaxed"&gt;
                reedbarger@email.com
              &lt;/a&gt;
              &lt;h2 className="title-font font-semibold text-white tracking-widest text-xs mt-4"&gt;
                PHONE
              &lt;/h2&gt;
              &lt;p className="leading-relaxed"&gt;123-456-7890&lt;/p&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;form
          netlify
          name="contact"
          className="lg:w-1/3 md:w-1/2 flex flex-col md:ml-auto w-full md:py-8 mt-8 md:mt-0"&gt;
          &lt;h2 className="text-white sm:text-4xl text-3xl mb-1 font-medium title-font"&gt;
            Hire Me
          &lt;/h2&gt;
          &lt;p className="leading-relaxed mb-5"&gt;
            Lorem ipsum dolor sit amet consectetur, adipisicing elit. Illum
            suscipit officia aspernatur veritatis. Asperiores, aliquid?
          &lt;/p&gt;
          &lt;div className="relative mb-4"&gt;
            &lt;label htmlFor="name" className="leading-7 text-sm text-gray-400"&gt;
              Name
            &lt;/label&gt;
            &lt;input
              type="text"
              id="name"
              name="name"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 text-base outline-none text-gray-100 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"
            /&gt;
          &lt;/div&gt;
          &lt;div className="relative mb-4"&gt;
            &lt;label htmlFor="email" className="leading-7 text-sm text-gray-400"&gt;
              Email
            &lt;/label&gt;
            &lt;input
              type="email"
              id="email"
              name="email"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 text-base outline-none text-gray-100 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"
            /&gt;
          &lt;/div&gt;
          &lt;div className="relative mb-4"&gt;
            &lt;label
              htmlFor="message"
              className="leading-7 text-sm text-gray-400"&gt;
              Message
            &lt;/label&gt;
            &lt;textarea
              id="message"
              name="message"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 h-32 text-base outline-none text-gray-100 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out"
            /&gt;
          &lt;/div&gt;
          &lt;button
            type="submit"
            className="text-white bg-indigo-500 border-0 py-2 px-6 focus:outline-none hover:bg-indigo-600 rounded text-lg"&gt;
            Submit
          &lt;/button&gt;
        &lt;/form&gt;
      &lt;/div&gt;
    &lt;/section&gt;
  );
}
</code></pre>
<h2 id="googlemaps">如何嵌入 <code>Google Maps</code> 位置</h2>
<p>在表格的左边，我们将一个 <code>Google Maps</code> 嵌入，显示我们的所在位置。</p>
<p>我们可以在一个在线工具（embed-map.com）的帮助下这样做。你所要做的事只是输入你的位置并点击<code>Generate HTML code</code>。</p>
<p>在给我们生成的代码中，不要复制所有的代码，只要复制 ifame 中的 <code>src</code> 属性，然后替换掉 <code>src</code> 的默认值。<br>
<img src="https://www.freecodecamp.org/news/content/images/2021/06/portfolio-2.png" alt="portfolio-2" width="600" height="400" loading="lazy"></p>
<p>向 Netlify 发送任何提交的表单数据，Netlify Forms 需要将从静态 HTML 中识别表单。因为我们的 React 应用是由 JavaScript 控制的，而不是普通的 HTML 组成，所以我们需要在 <code>public</code> 文件夹下的 index.html 文件中添加一个隐藏的表单。</p>
<pre><code class="language-html">&lt;!-- public/index.html --&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
  &lt;head&gt;
    &lt;!-- head content skipped --&gt;
  &lt;/head&gt;
  &lt;body&gt;

  &lt;form name="contact" netlify netlify-honeypot="bot-field" hidden&gt;
    &lt;input type="text" name="name" /&gt;
    &lt;input type="email" name="email" /&gt;
    &lt;textarea name="message"&gt;&lt;/textarea&gt;
  &lt;/form&gt;
  
    &lt;noscript&gt;You need to enable JavaScript to run this app.&lt;/noscript&gt;
    &lt;div id="root"&gt;&lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>我们需要隐藏这个表单，因为它不需要被用户看到，它只需要被Netlify看到。</p>
<h2 id="">如何从联系表单提交</h2>
<p>完成上面这些，我们将回到 Contact.js。我们将使用 JavaScript 提交这个表单。</p>
<pre><code class="language-js">const [name, setName] = React.useState("");
const [email, setEmail] = React.useState("");
const [message, setMessage] = React.useState("");
</code></pre>
<p>我们将在 <code>onChange</code> 处理程序的帮助下，将用户在每个输入项的信息存储在 <code>state</code>。</p>
<pre><code class="language-js">// src/components/Contact.js

import React from "react";

export default function Contact() {
  const [name, setName] = React.useState("");
  const [email, setEmail] = React.useState("");
  const [message, setMessage] = React.useState("");

  function encode(data) {
    return Object.keys(data)
      .map(
        (key) =&gt; encodeURIComponent(key) + "=" + encodeURIComponent(data[key])
      )
      .join("&amp;");
  }

  function handleSubmit(e) {
    e.preventDefault();
    fetch("/", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: encode({ "form-name": "contact", name, email, message }),
    })
      .then(() =&gt; alert("Message sent!"))
      .catch((error) =&gt; alert(error));
  }

  return (
    &lt;section id="contact" className="relative"&gt;
      &lt;div className="container px-5 py-10 mx-auto flex sm:flex-nowrap flex-wrap"&gt;
        &lt;div className="lg:w-2/3 md:w-1/2 bg-gray-900 rounded-lg overflow-hidden sm:mr-10 p-10 flex items-end justify-start relative"&gt;
          &lt;iframe
            width="100%"
            height="100%"
            title="map"
            className="absolute inset-0"
            frameBorder={0}
            marginHeight={0}
            marginWidth={0}
            style={{ filter: "opacity(0.7)" }}
            src="https://www.google.com/maps/embed/v1/place?q=97+warren+st+new+york+city&amp;key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8"
          /&gt;
          &lt;div className="bg-gray-900 relative flex flex-wrap py-6 rounded shadow-md"&gt;
            &lt;div className="lg:w-1/2 px-6"&gt;
              &lt;h2 className="title-font font-semibold text-white tracking-widest text-xs"&gt;
                ADDRESS
              &lt;/h2&gt;
              &lt;p className="mt-1"&gt;
                97 Warren St. &lt;br /&gt;
                New York, NY 10007
              &lt;/p&gt;
            &lt;/div&gt;
            &lt;div className="lg:w-1/2 px-6 mt-4 lg:mt-0"&gt;
              &lt;h2 className="title-font font-semibold text-white tracking-widest text-xs"&gt;
                EMAIL
              &lt;/h2&gt;
              &lt;a className="text-indigo-400 leading-relaxed"&gt;
                reedbarger@email.com
              &lt;/a&gt;
              &lt;h2 className="title-font font-semibold text-white tracking-widest text-xs mt-4"&gt;
                PHONE
              &lt;/h2&gt;
              &lt;p className="leading-relaxed"&gt;123-456-7890&lt;/p&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;form
          netlify
          name="contact"
          onSubmit={handleSubmit}
          className="lg:w-1/3 md:w-1/2 flex flex-col md:ml-auto w-full md:py-8 mt-8 md:mt-0"&gt;
          &lt;h2 className="text-white sm:text-4xl text-3xl mb-1 font-medium title-font"&gt;
            Hire Me
          &lt;/h2&gt;
          &lt;p className="leading-relaxed mb-5"&gt;
            Lorem ipsum dolor sit amet consectetur, adipisicing elit. Illum
            suscipit officia aspernatur veritatis. Asperiores, aliquid?
          &lt;/p&gt;
          &lt;div className="relative mb-4"&gt;
            &lt;label htmlFor="name" className="leading-7 text-sm text-gray-400"&gt;
              Name
            &lt;/label&gt;
            &lt;input
              type="text"
              id="name"
              name="name"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 text-base outline-none text-gray-100 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"
              onChange={(e) =&gt; setName(e.target.value)}
            /&gt;
          &lt;/div&gt;
          &lt;div className="relative mb-4"&gt;
            &lt;label htmlFor="email" className="leading-7 text-sm text-gray-400"&gt;
              Email
            &lt;/label&gt;
            &lt;input
              type="email"
              id="email"
              name="email"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 text-base outline-none text-gray-100 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"
              onChange={(e) =&gt; setEmail(e.target.value)}
            /&gt;
          &lt;/div&gt;
          &lt;div className="relative mb-4"&gt;
            &lt;label
              htmlFor="message"
              className="leading-7 text-sm text-gray-400"&gt;
              Message
            &lt;/label&gt;
            &lt;textarea
              id="message"
              name="message"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 h-32 text-base outline-none text-gray-100 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out"
              onChange={(e) =&gt; setMessage(e.target.value)}
            /&gt;
          &lt;/div&gt;
          &lt;button
            type="submit"
            className="text-white bg-indigo-500 border-0 py-2 px-6 focus:outline-none hover:bg-indigo-600 rounded text-lg"&gt;
            Submit
          &lt;/button&gt;
        &lt;/form&gt;
      &lt;/div&gt;
    &lt;/section&gt;
  );
}
</code></pre>
<p>正如你在上面看到的，我们正在用一个特殊的<code>encode</code>(编码)函数对表单数据进行编码。</p>
<h2 id="navbar">如何构建 <code>Navbar</code> 组件</h2>
<p>最后一步是构建我们的 <code>Navbar</code> 组件。</p>
<pre><code class="language-js">// src/components/Navbar.js

import { ArrowRightIcon } from "@heroicons/react/solid";
import React from "react";

export default function Navbar() {
  return (
    &lt;header className="bg-gray-800 md:sticky top-0 z-10"&gt;
      &lt;div className="container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center"&gt;
        &lt;a className="title-font font-medium text-white mb-4 md:mb-0"&gt;
          &lt;a href="#about" className="ml-3 text-xl"&gt;
            Reed Barger
          &lt;/a&gt;
        &lt;/a&gt;
        &lt;nav className="md:mr-auto md:ml-4 md:py-1 md:pl-4 md:border-l md:border-gray-700	flex flex-wrap items-center text-base justify-center"&gt;
          &lt;a href="#projects" className="mr-5 hover:text-white"&gt;
            Past Work
          &lt;/a&gt;
          &lt;a href="#skills" className="mr-5 hover:text-white"&gt;
            Skills
          &lt;/a&gt;
          &lt;a href="#testimonials" className="mr-5 hover:text-white"&gt;
            Testimonials
          &lt;/a&gt;
        &lt;/nav&gt;
        &lt;a
          href="#contact"
          className="inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0"&gt;
          Hire Me
          &lt;ArrowRightIcon className="w-4 h-4 ml-1" /&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/header&gt;
  );
}
</code></pre>
<p>如何在较大的设备上将 <code>Navbar</code> 组件在页面的顶部显示？我们将使用 <code>md:sticky</code> 类添加到 <code>header</code> 元素。</p>
<h2 id="">如何部署作品集</h2>
<p>现在，为了使我们的作品集上线，我们需要把应用程序推送到 GitHub。</p>
<p>一旦你熟悉了这个流程，我们可以首先创建一个新的 GitHub 仓库。之后，我们将运行 <code>git add .</code>、<code>git commit -m "Deploy"</code>，创建 git 远程，然后 <code>git push -u orgin master</code>。</p>
<p>一旦我们的项目建立在 GitHub 上，我们就可以去 Netlify，选择 <code>Choose Site from Git</code>。然后选择 GitHub 作为持续部署，并选择我们刚刚推送代码的 GitHub 仓库。</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/portfolio-3-min.gif" alt="portfolio-3-min" width="600" height="400" loading="lazy"></p>
<p>之后，我们的项目将自动部署到网络上！</p>
<h2 id="">下一步是什么</h2>
<p>祝贺你，你现在可以通过一个在线的作品集应用程序向潜在雇主展示你的所有项目和技能了！</p>
<p>下一步要做的事设置一个自己的域名，最好用你的名字（例如 <a href="https://reedbarger.com/">reedbarger.com</a>）。</p>
<p>由于 Netlify 包含一个 DNS，你可以很容易在那里设置一个自己的域名。</p>
<p>可以考虑在你的 React 应用程序中添加一个博客，向潜在的雇主展示你更多的开发知识。</p>
<p>通过个人作品集表达你自己以及你作为开发者的热情所在，你将获得成功！</p>
<h2 id="react">获得学习 React 的方法</h2>
<p><strong><a href="http://bit.ly/join-react-bootcamp">The React Bootcamp</a></strong> 有你应该学习的 React 的所有知识，里面有视频、手册，还有特别的奖金。</p>
<p>数百位开发人员已经在这里掌握 React，找到他们梦想的工作，并掌握他们的未来</p>
<p><a href="http://bit.ly/join-react-bootcamp"><img src="https://reedbarger.nyc3.digitaloceanspaces.com/react-bootcamp-banner.png" alt="The React Bootcamp" width="600" height="400" loading="lazy"></a><br>
<em>点击这里，当它开放时，你将得到通知</em></p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
