순수한 HTML, CSS, JS를 사용하여 완전히 호응하는 현대 서류 가방을 만드는 방법
96612 단어 webdevhtmlcssjavascript
프레젠테이션을 보거나 설명이 있는 인코딩 강좌를 보십시오.너는 아래의 강좌를 볼 수 있다.
비디오 자습서
I appreciate if you can support me by subscribing my youtube channel.
따라서 더 많은 시간을 낭비하지 않는 상황에서 코드를 어떻게 만드는지 살펴봅시다.
비밀 번호
우리가 코드를 작성하기 전에폴더 구조를 보여 줍니다.
네, 이것은 nodeJS 응용 프로그램입니다. 우리는 메일 시스템이 정상적으로 작동하기를 원하기 때문에 서버만 클라이언트 브라우저가 아닌 메일을 보낼 수 있습니다.
보시다시피 우리는
project.js
개의 서류를 가지고 있습니다.이 파일들은 우리의 프로젝트 데이터를 포함한다.프로젝트 데이터가 있으면 원하는 항목을 더 쉽게 추가하거나 삭제하거나 편집할 수 있습니다.그것의 데이터 구조를 보여 주세요.let projects = [
{
name: "project one",
tags: "#javascript, #fullstack, #ui/ux, #backend",
image: "project (1).png",
},
{
name: "project two",
tags: "#javascript, #fullstack",
image: "project (2).png",
},
// +8 more
]
프로젝트 이름, 탭, 이미지 경로를 볼 수 있습니다.이런 방식을 통해 우리는 코드를 편집하지 않고 프로젝트를 쉽게 처리할 수 있다.NPM 초기화부터 시작하겠습니다.
NPM 초기화
공용 폴더 밖의 루트 디렉터리에서 명령 알림이나 터미널을 열고
npm init
cmd를 실행합니다.그러면 프로젝트에 대한 NPM이 초기화됩니다.이 명령을 실행해서 이 라이브러리를 설치합니다.
npm i express.js nodemon nodemailer dotenv
express.js
- 서버 생성nodemon
- 연속 실행 서버nodemailer
- 메시지 보내기dotenv
- 환경을 변화시킬 수 있습니다.서버 밖에서 이 전자 우편 id와 비밀번호를 저장할 것입니다.창고를 설치한 후.
package.json
에서 몇 가지 변경 사항을 살펴보겠습니다.그것을 열어라.데이터 변경scripts
"scripts": {
"start": "nodemon server.js"
},
그리고 루트 디렉터리에 server.js
파일을 만듭니다. (공용 폴더에 없습니다.)그것을 열어라.서버.js
라이브러리/패키지 가져오기부터 시작합니다.
const express = require('express');
const path = require('path');
const nodemailer = require('nodemailer');
const dotenv = require('dotenv');
환경 변수에 액세스할 수 있도록 dotenv
를 설정합니다.dotenv.config();
그리고 공용 폴더 경로를 변수에 저장하여 서버로 만듭니다.let initialPath = path.join(__dirname, "public");
let app = express();
현재 app.use
방법으로 중간부품을 설정합니다.app.use(express.static(initialPath));
app.use(express.json());
그것들은 모두 매우 중요하다. express.json
폼 데이터 공유를 사용하고, express.static
공용 폴더를 정적 경로로 설정한다.집으로 돌아가는 이 노선 뒤에
index.html
파일을 보냅니다.app.get('/', (req, res) => {
res.sendFile(path.join(initialPath, "index.html"));
})
마지막으로 서버가 3000
포트를 감청하도록 합니다.app.listen(3000, () => {
console.log('listening.....');
})
그래서 우리 서버는 이미 완성되었다.터미널에서 npm start
cmd를 실행해서 서버를 실행합시다.이제 투자조합을 연구해 봅시다.
폴더
index.html
를 열고 기본 HTML 구조를 작성합니다.그런 다음 style.css
및 app.js
를 파일에 연결합니다.그리고 내비게이션 표시줄을 만들어.<!-- navbar -->
<nav class="navbar">
<h1 class="brand">logo</h1>
<div class="toggle-btn">
<span></span>
<span></span>
</div>
<ul class="links-container">
<li class="links-item"><a href="#" class="link active">home</a></li>
<li class="links-item"><a href="#project-section" class="link">project</a></li>
<li class="links-item"><a href="#about-section" class="link">about</a></li>
<li class="links-item"><a href="#contact-section" class="link">contact</a></li>
</ul>
</nav>
스타일 좀 줘봐.*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
html{
scroll-behavior: smooth;
}
body{
width: 100%;
position: relative;
background: #1d1d1d;
color: #fff;
font-family: 'roboto', sans-serif;
}
/* navbar */
.navbar{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 60px;
background: #1d1d1d;
padding: 0 10vw;
display: flex;
justify-content: space-between;
align-items: center;
z-index: 9;
}
.brand{
text-transform: capitalize;
font-weight: 500;
}
.links-container{
display: flex;
list-style: none;
}
.link{
text-transform: capitalize;
color: #fff;
text-decoration: none;
margin: 0 10px;
padding: 10px;
position: relative;
}
.link:hover:not(.active){
opacity: 0.7;
}
.link.active::before,
.seperator::before{
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 5px;
height: 5px;
border-radius: 50%;
background: #fff;
}
.link.active::after,
.seperator::after{
content: '';
position: absolute;
bottom: 2px;
left: 0;
width: 100%;
height: 1px;
background: #fff;
}
메모scroll-behavior
주신html
.만약 네가 이것을 주지 않는다면, 너는 매끄러운 스크롤 효과를 얻을 수 없을 것이다.seperator
요소를 볼 수 있지만 걱정하지 마십시오. 저희가 나중에 만들 것입니다.출력
제목 섹션 만들기
<!-- home section -->
<section class="home">
<div class="hero-content">
<h1 class="hero-heading"><span class="highlight">hi, </span>i am john</h1>
<p class="profession">web developer</p>
<p class="info">Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur odit in laudantium suscipit blanditiis asperiores.</p>
<a href="#contact-section" class="btn">contact</a>
</div>
<img src="img/img1.png" class="image" alt="">
</section>
/* home section */
.home{
width: 100%;
min-height: calc(100vh - 60px);
height: auto;
margin-top: 60px;
padding: 0 10vw;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.hero-content{
width: 50%;
}
.hero-heading{
font-size: 5rem;
text-transform: capitalize;
font-weight: 500;
}
.highlight{
color: #ff3559;
}
.profession{
width: fit-content;
display: block;
margin: 10px 0 20px;
margin-left: auto;
text-transform: capitalize;
position: relative;
padding: 10px 20px;
color: #1d1d1d;
z-index: 2;
}
.profession::before{
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #e3e3e3;
z-index: -1;
transform: skewX(10deg);
}
.profession::after{
content: '';
position: absolute;
top: 0;
left: -100px;
width: 100px;
height: 2px;
background: #e3e3e3;
}
.info{
line-height: 30px;
margin-bottom: 50px;
}
.btn{
padding: 10px 20px;
text-decoration: none;
border-radius: 50px;
background: #ff3559;
color: #fff;
text-transform: capitalize;
border: none;
}
출력
위대하다지금 2절에 대해서 얘기 좀 하자.
<!-- about section -->
<section class="about" id="about-section">
<h2 class="heading">about <span class="highlight">me</span></h2>
<p class="sub-heading">Lorem ipsum dolor sit amet consectetur. </p>
<div class="seperator"></div>
<div class="about-me-container">
<div class="left-col">
<img src="img/img2.png" class="about-image" alt="">
</div>
<div class="right-col">
<p class="about-para">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus totam quia numquam tempora nostrum earum similique enim laudantium iusto. Quaerat illo numquam minus pariatur, cum qui ipsum sapiente, atque optio voluptatibus necessitatibus, quis dolores veniam delectus inventore beatae? Accusamus, illum! Non nam dolores assumenda quibusdam repellat beatae quae eum atque sed, velit culpa, at animi cumque suscipit. Ratione delectus dolores odit dicta ipsum libero molestiae et reprehenderit sapiente earum. Alias aut architecto quis, earum iusto beatae quibusdam maiores, rerum, consequatur aliquid doloribus? Quas accusantium quidem eos ex, aperiam recusandae. Veritatis?</p>
<a href="#" class="btn">download cv</a>
</div>
</div>
</section>
/* about section */
.about{
width: 100%;
height: auto;
padding: 50px 10vw;
}
.heading{
text-align: center;
font-weight: 500;
font-size: 3.5rem;
text-transform: capitalize;
}
.sub-heading{
text-align: center;
font-size: 1rem;
margin: 10px;
opacity: 0.7;
}
.seperator{
width: 25%;
margin: 20px auto;
position: relative;
}
.about-me-container{
margin: 150px 0 100px;
width: 100%;
display: grid;
grid-template-columns: 40% 60%;
grid-gap: 50px;
}
.left-col, .right-col{
position: relative;
}
.left-col::before{
content: 'yes, its me';
text-transform: capitalize;
position: absolute;
right: 0;
top: -20px;
}
.left-col::after{
content: '';
position: absolute;
top: -10px;
right: 80px;
width: 50px;
height: 2px;
background: #fff;
transform-origin: right;
transform: rotate(-30deg);
}
.about-image{
border-radius: 10px;
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.25);
}
.about-para{
font-size: 1.2rem;
font-weight: 300;
line-height: 35px;
margin-bottom: 40px;
}
출력
기술 섹션을 생성합니다.
about
섹션에 이 구조를 추가합니다.<section class="about" id="about-section">
//previous elements
<h2 class="heading">languages and framework i know</h2>
<div class="seperator"></div>
<div class="skill-container">
<div class="skill-card" style="--bg: #f06529">
<p class="skill">HTML</p>
</div>
<div class="skill-card" style="--bg: #379ad6">
<p class="skill">CSS</p>
</div>
<div class="skill-card" style="--bg: #cc6699">
<p class="skill">SCSS</p>
</div>
<div class="skill-card" style="--bg: #f7df1e">
<p class="skill">JavaScript</p>
</div>
<div class="skill-card large" style="--bg: #5ed9fb">
<p class="skill">ReactJS</p>
</div>
<div class="skill-card large" style="--bg: #83cd29">
<p class="skill">NodeJS</p>
</div>
<div class="skill-card" style="--bg: #326690">
<p class="skill">Postgres SQL</p>
</div>
<div class="skill-card" style="--bg: #ffa000">
<p class="skill">Firebase</p>
</div>
<div class="skill-card large" style="--bg: #5ed9fb">
<p class="skill">Much More</p>
</div>
</div>
</section>
너는 우리가 style="--bg: value"
원소를 가지고 있다는 것을 알아차릴 수 있다.이것은 요소에 따라 다른 skill-card
CSS 변수를 설정하는 것입니다.이렇게 하면 우리는 서로 다른 색깔로 같은 효과를 추가할 수 있다..skill-container{
position: relative;
margin-top: 100px;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 20px;
}
.skill-card{
height: 200px;
border-radius: 10px;
border: 1px solid #464646;
text-align: center;
position: relative;
cursor: pointer;
transition: .5s;
}
.skill{
font-size: 2rem;
color: #464646;
line-height: 200px;
}
.skill-card:hover{
background: var(--bg);
}
.skill-card:hover .skill{
color: #fff;
}
.skill-card.large{
grid-column: 2 span;
}
출력
background color is showing on hover
이제 프로젝트 부분을 만듭니다.프로젝트 부분에서 필터 단추를 먼저 만듭니다.
<!-- project section -->
<section class="project" id="project-section">
<h2 class="heading">Project<span class="highlight">s</span></h2>
<p class="sub-heading">Lorem ipsum dolor sit amet consectetur. </p>
<div class="seperator"></div>
<div class="filters">
<button class="filter-btn active" id="all">all</button>
<button class="filter-btn" id="javascript">javaScript</button>
<button class="filter-btn" id="ui">ui/ux</button>
<button class="filter-btn" id="backend">backend</button>
<button class="filter-btn" id="fullstack">fullStack</button>
</div>
</section>
필터의 --bg
속성은 항목을 필터하는 데 도움을 줄 것입니다./* project section */
.project, .contact{
position: relative;
padding: 50px 10vw;
}
.filters{
width: fit-content;
display: block;
margin: 100px auto;
}
.filter-btn{
padding: 10px 20px;
border-radius: 5px;
border: none;
text-transform: capitalize;
margin: 0 5px 10px;
cursor: pointer;
}
.filter-btn.active{
background: #ff3559;
color: #fff;
}
출력
지금은 단지 스타일링을 위해 아이템 카드를 제작할 뿐이다.
<div class="project-container">
<div class="project-card">
<img src="img/project (1).png" alt="">
<div class="content">
<h1 class="project-name">project one</h1>
<span class="tags">#javascript</span>
</div>
</div>
</div>
.project-container{
width: 100%;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 20px;
}
.project-card{
position: relative;
cursor: pointer;
display: block;
}
.project-card img{
width: 100%;
height: 100%;
object-fit: cover;
}
.project-card .content{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
transition: .5s;
text-transform: capitalize;
opacity: 0;
}
.project-name{
font-weight: 300;
font-size: 2.5rem;
text-align: center;
}
.tags{
position: absolute;
bottom: 20px;
opacity: 0.6;
width: 90%;
}
.project-card:hover .content{
opacity: 1;
}
.project-card.hide{
display: none;
}
출력
Content is showing on hover
지금 너는 프로젝트 카드에 대해 평론을 진행할 수 있다.
<div class="project-container">
<!-- <div class="project-card">
<img src="img/project (1).png" alt="">
<div class="content">
<h1 class="project-name">project one</h1>
<span class="tags">#javascript</span>
</div>
</div> -->
</div>
프로젝트 카드를 동적 제작합시다.근데 그 전에id
파일 앞에 project.js
파일을 추가합니다.그렇지 않으면 프로젝트 데이터에 접근할 수 없습니다.<script src="project.js"></script>
<script src="app.js"></script>
지금 엽니다app.js
.프로젝트 카드를 만들기 전에링크를 활성 클래스로 전환합니다.이 코드에 대해서// links
const links = document.querySelectorAll('.link');
links.forEach(link => {
link.addEventListener('click', () => {
links.forEach(ele => ele.classList.remove('active'));
link.classList.add('active');
})
})
이렇게 한 후에 우리는 프로젝트 카드를 시작할 수 있다.그래서 이 코드를 줘요.// creating dynamic project card
const projectContainer = document.querySelector('.project-container');
projects.forEach(project => {
projectContainer.innerHTML += `
<div class="project-card" data-tags="#all, ${project.tags}">
<img src="img/${project.image}" alt="">
<div class="content">
<h1 class="project-name">${project.name}</h1>
<span class="tags">${project.tags}</span>
</div>
</div>
`;
})
우리는 단지 프로젝트 용기를 선택한 후에 순환 데이터를 통해 카드를 만드는 것을 볼 수 있다.출력
위대하다이제 필터 버튼이 정상적으로 작동합니다.
// filters
const filters = document.querySelectorAll('.filter-btn');
filters.forEach(filterBtn => {
filterBtn.addEventListener('click', () => {
let id = filterBtn.getAttribute('id');
let projectCards = document.querySelectorAll('.project-card');
projectCards.forEach(card => {
if(card.getAttribute('data-tags').includes(id)){
card.classList.remove('hide');
} else{
card.classList.add('hide');
}
})
filters.forEach(btn => btn.classList.remove('active'));
filterBtn.classList.add('active');
})
})
위 코드에서, 우리는 클릭 이벤트를 Filter 단추에 추가하고, 클래스 요소를 전환할 뿐입니다.그래서 우리의 프로젝트 부분은 이미 전부 완성되었다.지금 연락처 양식을 작성하세요.
<!-- contact form -->
<section class="contact" id="contact-section">
<h2 class="heading">Contact<span class="highlight"> me</span></h2>
<p class="sub-heading">Lorem ipsum dolor sit amet consectetur. </p>
<div class="seperator"></div>
<div class="contact-form">
<div class="name">
<input type="text" class="first-name" required placeholder="first name">
<input type="text" class="last-name" required placeholder="last name">
</div>
<input type="email" required class="email" placeholder="email">
<textarea class="message" placeholder="message" required></textarea>
<button class="btn contact-btn">contact</button>
</div>
</section>
<footer class="footer">made with love by modern web</footer>
/* contact form */
.contact-form{
width: 100%;
margin-top: 100px;
position: relative;
}
.contact-form input, .message{
width: 100%;
display: block;
height: 50px;
padding: 20px;
border-radius: 5px;
background: #000;
color: #fff;
border: none;
outline: none;
margin: 30px 0;
text-transform: capitalize;
resize: none;
}
.message{
height: 200px;
}
.contact-form .name{
display: flex;
justify-content: space-between;
}
.name input{
width: 49%;
margin: 0;
}
.contact-form .btn{
display: block;
margin: auto;
cursor: pointer;
}
/* footer */
.footer{
width: 100%;
height: 30px;
text-align: center;
background-color: #ff3559;
text-transform: capitalize;
line-height: 30px;
}
출력
이제 메일을 내부로 보내자
app.js
app.post('/mail', (req, res) => {
const { firstname, lastname, email, msg } = req.body;
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL,
pass: process.env.PASSWORD
}
})
const mailOptions = {
from: 'sender email',
to: 'receiver email',
subject: 'Postfolio',
text: `First name: ${firstname}, \nLast name: ${lastname}, \nEmail: ${email}, \nMessage: ${msg}`
}
transporter.sendMail(mailOptions, (err, result) => {
if (err){
console.log(err);
res.json('opps! it seems like some error occured plz. try again.')
} else{
res.json('thanks for e-mailing me. I will reply to you within 2 working days');
}
})
})
이것은nodemailer를 사용하여 메일을 보내는 방법이다.어떤 일들은 네가 반드시 주의해야 한다.server.js
와 process.env.EMAIL
이 키워드는 환경 변수에 접근할 수 있도록 해 주지만, 이 변수를 만들지 않았습니다.루트 디렉토리process.env.PASSWORD
에 파일을 생성합니다.이름은 같을 거예요.그것을 열고 이것을 입력하세요.EMAIL=your email
PASSWORD=your email's password
이제 알면 .env
이 변수에 접근할 것입니다.process.env
와 from
매개 변수.위의 코드에서, 나는 나의 전자메일을 입력하지 않았지만, 전자메일을 작동시키기 위해서, 너는 반드시 전자메일 id를 그들의 매개 변수로 제공해야 한다.너는 두 사람에게 같은 전자 우편 id를 제공할 수 있다.//contact form
const contactBtn = document.querySelector('.contact-btn');
const firstName = document.querySelector('.first-name');
const lastName = document.querySelector('.last-name');
const email = document.querySelector('.email');
const msg = document.querySelector('.message');
contactBtn.addEventListener('click', () => {
if(firstName.value.length && lastName.value.length && email.value.length && msg.value.length){
fetch('/mail', {
method: 'post',
headers: new Headers({'Content-Type': 'application/json'}),
body: JSON.stringify({
firstname: firstName.value,
lastname: lastName.value,
email: email.value,
msg: msg.value,
})
})
.then(res => res.json())
.then(data => {
alert(data);
})
}
})
위의 코드에서, 나는 단지 모든 폼 입력을 선택하고 to
루트에 POST
요청을 보낼 뿐이다.우리 연락처도완성
이제 이 사이트가 호응성을 갖도록 하자.
응답 태블릿
/* tablet view */
@media (max-width: 996px){
html{
font-size: 14px;
}
/* toggle btn */
.toggle-btn{
position: absolute;
width: 40px;
height: 40px;
right: 10vw;
cursor: pointer;
}
.toggle-btn span{
position: absolute;
width: 100%;
height: 2px;
background: #fff;
top: 30%;
transition: .5s;
}
.toggle-btn span:nth-child(2){
top: 70%;
}
.toggle-btn.active span:nth-child(1){
top: 50%;
transform: rotate(45deg);
}
.toggle-btn.active span:nth-child(2){
top: 50%;
transform: rotate(-45deg);
}
/* links */
.links-container{
position: absolute;
top: 60px;
background: #1d1d1d;
width: 100%;
left: 0;
padding: 0 10vw;
flex-direction: column;
transition: .5s;
opacity: 0;
pointer-events: none;
}
.links-container.show{
opacity: 1;
pointer-events: all;
}
.link{
margin-left: auto;
text-align: center;
display: block;
height: 50px;
}
/* home section */
.home{
flex-direction: column-reverse;
height: fit-content;
padding-bottom: 50px;
}
.home .image{
width: 250px;
margin: 40px;
}
.hero-content{
width: 70%;
min-width: 350px;
text-align: center;
}
.hero-heading{
font-size: 4.5rem;
}
/* about-section */
.about-me-container{
grid-template-columns: 1fr;
}
.left-col{
margin: auto;
width: 50%;
min-width: 320px;
}
.skill-container, .project-container{
grid-template-columns: repeat(2, 1fr);
}
.skill-card{
grid-column: 1 span !important;
}
}
우리가 디자인하고 있는 것을 볼 수 있다/mail
.그러나 그 역할을 발휘하려면 내부에서 인코딩을 해야 한다toggle-btn
.//toggle button
const toggleBtn = document.querySelector('.toggle-btn');
const linkContainer = document.querySelector('.links-container');
toggleBtn.addEventListener('click', () => {
toggleBtn.classList.toggle('active');
linkContainer.classList.toggle('show');
})
응답 - 이동
/* mobile view */
@media (max-width: 500px){
html{
font-size: 12px;
}
p, .sub-heading, .about-para, .left-col::before, .tags{
font-size: 1.4rem;
}
.about-image{
width: 90%;
margin: auto;
display: block;
}
.skill-container, .project-container{
grid-template-columns: 1fr;
}
.skill{
font-size: 2.5rem;
}
.project-name{
font-size: 3rem;
}
.name{
flex-direction: column;
}
.name input{
width: 100%;
}
.first-name{
margin-bottom: 20px !important;
}
}
You can watch responsive part on video tutorial for output
이렇게나는 네가 모든 일을 이해하길 바란다.만약 궁금한 것이 있거나 제가 빠뜨린 것이 있다면, 평론에서 저에게 알려 주십시오.
이 가능하다, ~할 수 있다,...
읽어주셔서 감사합니다.
Reference
이 문제에 관하여(순수한 HTML, CSS, JS를 사용하여 완전히 호응하는 현대 서류 가방을 만드는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/kunaal438/how-to-make-fully-responsive-modern-portfolio-using-pure-html-css-and-js-1p65텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)