Все заценят: как сделать сайт-портфолио на HTML, CSS и JavaScript
Фулстек-разработчик и автор канала Modern Web опубликовал туториал по созданию сайта-портфолио с помощью HTML, CSS и JavaScript. Ссылка на исходный код проекта и видеоинструкция — в материале. Давайте приступим!
Начнем с создания панели навигации (Navbar) для сайта. Готовый архив с файлами для проекта хранится здесь.
Для создания navbar нужно написать базовый шаблон и связать файлы style.css и app.js. Затем выполнить следующий HTML-код:
<!-- navbar -->
<nav class="navbar">
<ul class="link-group">
<li class="link active"><a href="#">home</a></li>
<li class="link"><a href="#">projects</a></li>
<li class="link"><a href="#">about</a></li>
<li class="link"><a href="#">contact</a></li>
</ul>
</nav> С HTML все, теперь добавим к нему немного CSS.
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
width: 100%;
max-width: 1400px;
display: block;
margin: auto;
min-height: 100vh;
background: #191919;
font-family: sans-serif;
}
.navbar{
width: 100%;
position: fixed;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
z-index: 9;
background: #1a1a1a;
}
.link-group{
list-style: none;
display: flex;
}
.link a{
color: #fff;
opacity: 0.5;
text-decoration: none;
text-transform: capitalize;
padding: 10px 30px;
margin: 0 20px;
line-height: 80px;
transition: .5s;
font-size: 20px;
}
.link a:hover, .link.active a{
opacity: 1;
} После выполнения этих действий должно получиться следующее:
Навигационная панель готова.
Более обстоятельно вам поможет разобраться с версткой курс от наших партнеров, школы Mate Academy и Hillel. Фронтенд разработчик востребованная и высокооплачиваемая работа, на которую стоит обратить внимание.
Для создания домашней страницы выполните следующий HTML-код после элемента navbar.
<!-- home section -->
<section class="home-section active">
<h1 class="hero-heading">hello, i am <br> kunaal</h1>
<img src="img/home.png" class="home-img" alt="">
</section> Добавим CSS.
.home-section{
width: 100%;
height: 100vh;
padding: 0 150px;
display: flex;
align-items: center;
position: relative;
top: 0;
opacity: 0;
transition: 1s;
}
.hero-heading{
color: #fff;
font-size: 120px;
text-transform: capitalize;
font-weight: 300;
}
.home-img{
position: absolute;
top: 0;
right: 0;
height: 100vh;
width: 50%;
object-fit: cover;
opacity: 0.2;
} .home-section есть свойства position: relative и top:0. Они важны при навигации.position: fixed). Благодаря этому они будут находиться друг над другом.position: relative и opacity: 1.Как только закончите с домашней страницей, убедитесь, что изменили ее положение с relative на fixed.
.home-section{
/* previous styles */ position: fixed;
} Чтобы упростить навигацию, пропишите все разделы. Обозначаем активные разделы.
.home-section.active,
.project-section.active,
.about-section.active,
.contact-section.active{
position: relative;
opacity: 1;
z-index: 8;
} Вот что должно получиться.
Создаем страницу с проектами. Для этого нужно выполнить следующий HTML-код.
<!-- project section -->
<section class="project-section">
<h1 class="project-heading">some of my projects</h1>
<div class="project-container">
<div class="project-card">
<img src="img/project-1.png" class="project-img" alt="">
<div class="project-content">
<h1 class="project-title">project 01</h1>
<p class="project-info">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Impedit vitae delectus cumque repudiandae aliquam optio accusamus natus nobis! Nam, sunt?
</p>
<div class="project-btn-grp">
<button class="project-btn github">github repo</button>
<button class="project-btn live">see live</button>
</div>
</div>
</div>
// +3 more cards
</div>
</section> Стилизуем его.
/* project-section */
.project-section{
width: 100%;
min-height: 100vh;
padding: 150px 100px 100px;
position: fixed;
top: 0;
transition: 1s;
opacity: 0;
}
.project-heading{
font-size: 100px;
background: #252525;
text-transform: capitalize;
text-align: center;
margin-bottom: 50px;
color: #1a1a1a;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-stroke: 8px transparent;
}
.project-container{
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 100px;
}
.project-card{
height: 400px;
position: relative;
}
.project-img{
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
object-fit: cover;
transition: .5s;
}
.project-content{
position: relative;
padding: 40px;
color: #fff;
transition: .5s;
opacity: 0;
}
.project-title{
font-size: 50px;
text-transform: capitalize;
text-align: center;
font-weight: 300;
}
.project-info{
margin: 40px;
font-size: 20px;
line-height: 30px;
text-align: center;
}
.project-btn-grp{
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 20px;
}
.project-btn{
height: 40px;
text-transform: capitalize;
font-size: 18px;
border: none;
background: #000;
color: #fff;
cursor: pointer;
}
.project-btn.live{
background: none;
border: 2px solid #fff;
}
.project-card:hover .project-img{
filter: blur(20px);
}
.project-card:hover .project-content{
opacity: 1;
} В приведенном выше коде в project-section уже добавлена позиция fixed, а opacity установлено в значение 0. Но для того, чтобы увидеть результат, убедитесь, что добавили класс active в секцию проекта следующим образом.
<section class="project-section active">
Вот что должно получиться.
Прежде чем двигаться дальше, нужно создать систему навигации сайта. Для этого пропишите в файле app.jss следующий код.
const links = document.querySelectorAll('.link');
const sections = document.querySelectorAll('section');
let activeLink = 0;
links.forEach((link, i) => {
link.addEventListener('click', () => {
if(activeLink != i){
links[activeLink].classList.remove('active');
link.classList.add('active');
sections[activeLink].classList.remove('active');
setTimeout(() => {
activeLink = i;
sections[i].classList.add('active');
}, 1000);
}
})
}) В приведенном выше коде сначала выделяются все ссылки и разделы. После этого определяется переменная activeLink, которая будет отслеживать текущий активный раздел или ссылку. После этого используется метод forEach — для перебора всех ссылок. Внутри него можно получить доступ к отдельной ссылке и ее индексу.
Сначала добавляется событие щелчка на ссылку с помощью addEventListener. Затем используется простое условие, чтобы убедиться, что пользователь не щелкает по активной ссылке. После этого удаляется активный класс из текущей активной ссылки с помощью classList.remove и добавляется класс active в нажатую ссылку с помощью classList.add. То же самое делается для удаления класса active из активного раздела.
Чтобы добавить задержку в 1 секунду для выполнения приведенных далее кодов, используется setTimeout. Внутри таймаута происходит простое добавление активного класса.
С навигацией все.
В этом разделе About будет раздел с навыками, а также шкала опыта.
Чтобы создать страницу «О себе», пропишите этот код после project section.
<!-- about section -->
<section class="about-section">
<div class="about">
<div class="about-img-container">
<img src="img/home.png" class="about-img" alt="">
<button class="download-cv-btn">downlaod cv</button>
</div>
<p class="about-info">Lorem ipsum.....</p>
</div>
</section> Подключим CSS.
/* about-section */
.about-section{
width: 100%;
min-height: 100vh;
padding: 150px 100px 0;
position: fixed;
top: 0;
opacity: 0;
transition: 1s;
}
.about{
width: 100%;
display: grid;
grid-template-columns: 30% 65%;
grid-gap: 40px;
}
.about-img-container{
position: relative;
}
.about-info{
color: #fff;
opacity: 0.6;
font-size: 20px;
line-height: 40px;
}
.about-img{
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 20px;
}
.download-cv-btn{
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
padding: 10px 20px;
color: #fff;
border: none;
font-size: 16px;
text-transform: capitalize;
cursor: pointer;
transition: .5s;
background: rgba(0, 0, 0, 0.5);
}
.download-cv-btn:hover{
background: #000;
} Примечание: убедитесь, что добавили класс active в раздел «О себе» и удалили его из всех остальных разделов.
Вот что должно получиться.
Теперь создадим раздел навыков. В нем также будут индикаторы навыков. Ранее мы писали о том, почему не нужно рисовать шкалу навыков в резюме, но все же рассмотрим, как ее сделать.
<!-- skills -->
<div class="skill-section">
<h1 class="heading">skills</h1>
<div class="skills-container">
<div class="skill-card">
<img src="img/html.png" class="skill-img" alt="">
<div class="skill-level">98%</div>
<h1 class="skill-name">HTML</h1>
<p class="skill-info">Lorem ipsum dolor, sit amet consectetur adipisicing elit. Consequatur, delectus!</p>
</div>
// +4 more cards
</div>
</div> Пропишите вышеописанный код над элементом about-section и стилизуйте его.
/* skills */
.skill-section{
position: relative;
margin: 100px 0;
}
.heading{
text-align: center;
font-size: 60px;
color: #fff;
text-transform: capitalize;
font-weight: 300;
margin-bottom: 100px;
}
.skills-container{
width: 95%;
margin: auto;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 100px;
color: #fff;
}
.skill-card{
position: relative;
}
.skill-img{
display: block;
margin: auto;
height: 200px;
}
.skill-name{
font-size: 30px;
font-weight: 300;
text-align: center;
text-transform: capitalize;
margin: 30px 0 20px;
}
.skill-info{
text-align: center;
opacity: 0.5;
font-size: 18px;
line-height: 30px;
}
.skill-level{
position: absolute;
top: 80px;
right: 0;
width: 150px;
height: 150px;
display: flex;
justify-content: center;
align-items: center;
font-size: 22px;
border-radius: 50%;
border: 10px solid;
}
.skill-card:nth-child(1) .skill-level{
background: #ff4f4f28;
border-color: #ff4f4f;
color: #ff4f4f;
}
.skill-card:nth-child(2) .skill-level{
background: #4fa0ff28;
border-color: #4fa0ff;
color: #4fa0ff;
}
.skill-card:nth-child(3) .skill-level{
background: #ffed4f28;
border-color: #ffed4f;
color: #ffed4f;
}
.skill-card:nth-child(4) .skill-level{
background: #52ff4f28;
border-color: #52ff4f;
color: #52ff4f;
}
.skill-card:nth-child(5) .skill-level{
background: #4fdfff28;
border-color: #4fdfff;
color: #4fdfff;
} Вот что получится.
Создаем временную шкалу опыта.
<!-- timeline -->
<div class="timeline">
<h1 class="heading">education and experience</h1>
<div class="card">
<div class="card-body">
<h1 class="card-title">2000-2002</h1>
<p class="card-detail">Lorem ipsum dolor, sit amet consectetur adipisicing elit. Architecto sequi recusandae laborum ipsam dignissimos nostrum vitae provident officia, consectetur ab accusantium corrupti exercitationem temporibus repellat non magni cupiditate ea reprehenderit.</p>
</div>
</div>
//+4 more cards
</div> Не забудьте добавить коды в раздел About.
/* timeline */
.timeline{
display: block;
width: 80%;
margin: 150px auto;
}
.timeline .heading{
margin-bottom: 150px;
}
.card{
width: 45%;
padding: 30px;
border-radius: 10px;
color: #fff;
display: block;
margin: -80px 0;
position: relative;
background: #f00;
}
.card:nth-child(even){
margin-left: auto;
}
.card:nth-child(even):before{
content: '';
position: absolute;
left: -15%;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
border: 5px solid #191919;
border-radius: 50%;
}
.card:nth-child(even):after{
content: '';
position: absolute;
left: -8.5%;
top: 50%;
transform: translateY(-50%);
width: 7%;
height: 2px;
background: #fff;
z-index: -1;
}
.card:nth-child(odd):before{
content: '';
position: absolute;
right: -13%;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
border: 5px solid #191919;
border-radius: 50%;
}
.card:nth-child(odd):after{
content: '';
position: absolute;
right: -8.5%;
top: 50%;
transform: translateY(-50%);
width: 7%;
height: 2px;
background: #fff;
z-index: -1;
}
.card:nth-child(2), .card:nth-child(2):before{
background: #ff4f4f;
}
.card:nth-child(3), .card:nth-child(3):before{
background: #ffb84f;
}
.card:nth-child(4), .card:nth-child(4):before{
background: #3dca5c;
}
.card:nth-child(5), .card:nth-child(5):before{
background: #565252;
}
.card:nth-child(6), .card:nth-child(6):before{
background: #4fa0ff;
}
.card:nth-child(even) .card-body:before{
content: '';
position: absolute;
left: -12%;
top: 0;
width: 0px;
height: 100%;
border: 1px dashed #fff;
z-index: -1;
}
.card-title{
font-size: 30px;
font-weight: 300;
margin-bottom: 20px;
} Вот что должно получиться.
Чтобы создать раздел «Контакты», пропишите следующий код.
<!-- contact section -->
<section class="contact-section">
<form class="contact-form">
<input type="text" name="name" id="name" autocomplete="off" placeholder="name">
<input type="text" name="email" id="email" autocomplete="off" placeholder="email">
<textarea name="msg" id="msg" placeholder="message" autocomplete="off"></textarea>
<button type="submit" class="form-submit-btn">contact</button>
</form>
<!-- map -->
<div class="map">
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d448181.163742937!2d76.81306771991275!3d28.647279935262464!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x390cfd5b347eb62d%3A0x37205b715389640!2sDelhi!5e0!3m2!1sen!2sin!4v1639489002410!5m2!1sen!2sin" width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy"></iframe>
</div>
</section> В приведенном выше коде iframe — это ссылка для встраивания карты Google.
.contact-section{
position: absolute;
top: 0;
opacity: 0;
transition: 1s;
padding: 100px 150px;
height: 100vh;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 50px;
}
.contact-form input, .contact-form textarea{
width: 100%;
height: 40px;
background: rgba(255, 255, 255, 0.2);
border: 1px solid #fff;
margin-bottom: 30px;
border-radius: 5px;
text-transform: capitalize;
color: #fff;
padding: 5px 10px;
}
::placeholder{
color: #fff;
}
#msg{
height: 280px;
resize: none;
font-family: sans-serif;
}
.form-submit-btn{
background: #ff4f4f;
color: #fff;
text-transform: capitalize;
padding: 15px 40px;
display: block;
margin: auto;
border: none;
border-radius: 10px;
cursor: pointer;
}
.map{
width: 100%;
height: 100%;
padding: 10px;
border: 2px solid #fff;
background: rgba(255, 255, 255, 0.2);
border-radius: 10px;
}
.map iframe{
width: 100%;
height: 100%;
border-radius: 5px;
} Вот что должно получиться.
Вот и все. Сайт-портфолио готов. Видеоинструкцию по созданию проекта найдете ниже. Также автор разместил исходный код, но он доступен только его подписчикам на Patreon.
Visual Code от Microsoft, вероятно, один из самых популярных редакторов кода. Разработчики любят его за…
Япония сама по себе — сплошной киберпанк. Это заметил даже культовый писатель жанра Уильям Гибсон,…
Сам по себе телефон Айфон 17 Про Макс – отличный подарок. У него красивая заводская…
На фоне роста спроса на ликвидность в бычьем рынке 2025 года, криптозаймы снова выходят на…
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…