9/21(목) UI 구현 : (HTML + CSS) + JS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Portfolio-test</title>
<link rel="stylesheet" href="Portfolio-test.css">
<script src="https://kit.fontawesome.com/f821b57119.js" crossorigin="anonymous"></script>
</head>
<body>
<section id="big-section">
<!-- header -->
<header>
<!-- nav -->
<nav>
<div>
<a href="#"><button type="button">Home</button></a>
<a href="#about"><button type="button">About</button></a>
<a href="#projects"><button type="button">Projects</button></a>
<a href="#contact"><button type="button">Contact</button></a>
</div>
<div>
<button class="fa-solid fa-palette" id="color-mode"></button>
<a href="https://github.com/yujinjjang2" target="_blank"><button type="button" class="fa-brands fa-github"></button></a>
<a href="https://velog.io/@o3odw98" target="_blank"><button type="button" class="fa-solid fa-pen-to-square"></button></a>
</div>
</nav>
<div>
<div>
<img src="images/profile.png" id="profile">
</div>
<div>
<div>
Hello <br>
This is Lee Yu-jin , <br>
a prospective developer ! <br><br>
A Multi talented software developer
</div>
<div>
<a href="#" target="_blank"><button type="button" id="resume-btn">Download My Resume</button></a>
</div>
</div>
</div>
</header>
<!-- main -->
<main>
<!-- About -->
<section class="about" id="about">
<div>
About
</div>
<div>
안녕하세요 , 예비 개발자를 꿈꾸는 이유진입니다 !
</div>
<div>
NAME : 이유진 <br>
BIRTHDAY : 1998-09-03 <br>
ADDRESS : 서울시 성북구 <br>
PHONE : 010-2485-4855 <br>
EMAIL : o3odw98@gmail.com <br><br>
“ No pain, No gain 고통없이 얻는 것은 없다. ” <br>
제가 마음 속에 항상 새기는 문장입니다. <br>
힘든 순간이 찾아와도 끈기를 가지고 맡은 일을 마무리하고자 합니다. <br>
JAVA, JS, CSS, HTML 등 다양한 언어를 공부하며 개발에 대한 관심 및 분야를 넓히고 있습니다.
</div>
<div>
<div></div>
<div>
<a href="#" target="_blank"><button type="button" id="hire-btn">Hire Me</button></a>
</div>
<div>
<a href="#"><button type="button" class="fa-solid fa-angles-up" id="up-btn"></button></a>
</div>
</div>
</section>
<!-- Projects -->
<section class="projects" id="projects">
<div>
Projects
</div>
<div class="youtube">
<div>
<img src="images/youtube_img.png" id="youtube-img">
</div>
<div>
<div>
Youtube Clone
</div>
<div>
유튜브 클론은 제 첫번째 프로젝트 결과물입니다.
</div>
<div>
<a href="https://github.com/yujinjjang2/CLONE_YOUTUBE_mob" target="_blank"><u>See More...</u></a>
</div>
</div>
</div>
<div class="naver">
<div>
<div>
Naver Clone
</div>
<div>
네이버 클론은 제 두번째 프로젝트 결과물입니다.
</div>
<div>
<a href="https://github.com/yujinjjang2/CLONE_NAVER" target="_blank"><u>See More...</u></a>
</div>
</div>
<div>
<img src="images/naver_img.png" id="naver-img">
</div>
</div>
<div>
<div></div>
<div>
<a href="#"><u>View All Projects...</u></a>
</div>
<div>
<a href="#"><button type="button" class="fa-solid fa-angles-up" id="up-btn"></button></a>
</div>
</div>
</section>
</main>
<!-- footer -->
<footer id="contact">
<div>
Contact Me
</div>
<div>
채용을 원하시면 바로 연락드리겠습니다.
</div>
<div>
<div></div>
<div>
<form action="#" target="_blank" id="form">
<input type="text" id="form-name" name="name" placeholder="Name(한글 2자이상 5자이하)" autocomplete="off">
<span id="span-name"></span>
<input type="text" id="form-email" name="email" placeholder="Email" autocomplete="off">
<span id="span-email"></span>
<input type="text" id="form-body" name="body" placeholder="Body" autocomplete="off">
<button type="submit" id="send-btn">Send</button>
</form>
</div>
<div>
<a href="#"><button type="button" class="fa-solid fa-angles-up" id="up-btn"></button></a>
</div>
</div>
</footer>
</section>
<script src="Portfolio-test.js"></script>
</body>
</html>
@font-face {
font-family: 'omyu_pretty';
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2304-01@1.0/omyu_pretty.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
* {
box-sizing: border;
font-family: 'omyu_pretty';
}
/* div, section {
border: 1px solid black;
} */
body {
margin: 0px;
padding: 0px;
display: flex;
justify-content: center;
}
body > section {
width: 1440px;
height: 350vh;
display: flex;
flex-direction: column;
background-color: #FAF6F6;
}
header, footer {
flex-basis: 20%;
}
main {
flex-basis: 60%;
}
/* header */
header {
display: flex;
flex-direction: column;
background-image: url("images/background.png");
}
nav {
flex-basis: 20%;
display: flex;
}
header > div {
flex-basis: 80%;
}
nav > div:nth-child(1) {
flex-basis: 70%;
display: flex;
justify-content: space-around;
align-items: center;
}
nav > div:nth-child(2) {
flex-basis: 30%;
display: flex;
align-items: center;
justify-content: flex-end;
}
nav > div:nth-child(1) > a > button {
border: none;
background-color: transparent;
font-size: 30px;
}
nav > div:nth-child(1) > a > button:hover {
border: 1px solid #dadada;
border-radius: 10px;
background-color: #dadada;
font-size: 35px;
font-weight: bold;
width: 200px;
height: 50px;
}
nav > div:nth-child(2) > button {
border: none;
background-color: transparent;
font-size: 50px;
margin: 20px;
}
nav > div:nth-child(2) > button:hover {
border: 1px solid #ddd;
border-radius: 50px;
background-color: #ddd;
font-size: 60px;
width: 80px;
height: 80px;
}
nav > div:nth-child(2) > a > button {
border: none;
background-color: transparent;
font-size: 50px;
margin: 20px;
}
nav > div:nth-child(2) > a > button:hover {
border: 1px solid #ddd;
border-radius: 50px;
background-color: #ddd;
font-size: 60px;
width: 80px;
height: 80px;
}
header > div {
display: flex;
}
header > div > div {
flex-basis: 50%;
}
header > div > div:nth-child(1) {
display: flex;
justify-content: center;
}
header > div > div:nth-child(2) {
display: flex;
flex-direction: column;
}
header > div > div:nth-child(2) > div:nth-child(1) {
flex-basis: 60%;
display: flex;
align-items: center;
font-size: 30px;
font-weight: bold;
font-style: italic;
}
header > div > div:nth-child(2) > div:nth-child(2) {
flex-basis: 40%;
display: flex;
justify-content: flex-end;
}
#resume-btn {
border: none;
background-color: black;
color: white;
border-radius: 10px;
width: 200px;
height: 50px;
font-size: 20px;
margin: 20px;
}
#resume-btn:hover {
background-color: #ddd;
color: black;
font-weight: bold;
}
/* main */
main {
display: flex;
flex-direction: column;
}
.about {
flex-basis: 40%;
display: flex;
flex-direction: column;
}
.projects {
flex-basis: 60%;
}
.about > div:nth-child(1) {
flex-basis: 20%;
display: flex;
justify-content: center;
align-items: center;
font-size: 50px;
font-weight: bold;
font-style: italic;
text-shadow: 5px 5px #ddd;
}
.about > div:nth-child(2) {
flex-basis: 10%;
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
font-weight: bold;
}
.about > div:nth-child(3) {
flex-basis: 50%;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
font-size: 22px;
}
.about > div:nth-child(4) {
flex-basis: 20%;
display: flex;
}
.about > div:nth-child(4) > div:nth-child(1),
.about > div:nth-child(4) > div:nth-child(3) {
flex-basis: 20%;
}
.about > div:nth-child(4) > div:nth-child(2) {
flex-basis: 60%;
display: flex;
justify-content: center;
align-items: center;
}
#hire-btn {
border: none;
border-radius: 10px;
background-color: black;
color: white;
width: 200px;
height: 50px;
font-size: 25px;
}
#hire-btn:hover {
background-color: #ddd;
color: black;
font-weight: bold;
font-size: 30px;
}
.about > div:nth-child(4) > div:nth-child(3) {
flex-basis: 20%;
display: flex;
justify-content: center;
align-items: center;
}
#up-btn {
border: none;
background-color: transparent;
color: gray;
font-size: 100px;
}
#up-btn:hover {
color: rgb(73, 73, 73);
}
.projects {
display: flex;
flex-direction: column;
}
.projects > div:nth-child(1) {
flex-basis: 15%;
display: flex;
justify-content: center;
align-items: center;
font-size: 50px;
font-weight: bold;
font-style: italic;
text-shadow: 5px 5px #ddd;
}
.projects > div:nth-child(2),
.projects > div:nth-child(3) {
flex-basis: calc(70%/2);
}
.projects > div:nth-child(4) {
flex-basis: 15%;
}
.youtube {
display: flex;
}
.youtube > div {
flex-basis: 50%;
}
.youtube > div:nth-child(1) {
display: flex;
align-items: center;
margin: 20px;
}
#youtube-img {
width: 100%;
height: 350px;
border: 2px solid #ddd;
border-radius: 20px;
}
.youtube > div:nth-child(2) {
display: flex;
flex-direction: column;
}
.youtube > div:nth-child(2) > div:nth-child(1) {
flex-basis: 50%;
display: flex;
align-items: center;
font-size: 40px;
font-weight: bold;
font-style: italic;
text-shadow: 2px 2px #ddd;
}
.youtube > div:nth-child(2) > div:nth-child(2) {
flex-basis: 30%;
font-size: 25px;
}
.youtube > div:nth-child(2) > div:nth-child(3) {
flex-basis: 20%;
}
.youtube > div:nth-child(2) > div:nth-child(3) > a > u {
color: black;
font-size: 25px;
}
.youtube > div:nth-child(2) > div:nth-child(3) > a > u:hover {
border: none;
border-radius: 10px;
background-color: #ddd;
color: black;
}
.naver {
display: flex;
}
.naver > div {
flex-basis: 50%;
}
.naver > div:nth-child(1) {
display: flex;
flex-direction: column;
margin: 10px;
}
.naver > div:nth-child(1) > div:nth-child(1) {
flex-basis: 50%;
display: flex;
align-items: center;
font-size: 40px;
font-weight: bold;
font-style: italic;
text-shadow: 2px 2px #ddd;
}
.naver > div:nth-child(1) > div:nth-child(2) {
flex-basis: 30%;
font-size: 25px;
}
.naver > div:nth-child(2) {
display: flex;
align-items: center;
margin: 20px;
}
.naver > div:nth-child(1) > div:nth-child(3) > a > u {
color: black;
font-size: 25px;
}
.naver > div:nth-child(1) > div:nth-child(3) > a > u:hover {
border: none;
border-radius: 10px;
background-color: #ddd;
color: black;
}
#naver-img {
width: 100%;
height: 400px;
border: 2px solid #ddd;
border-radius: 20px;
}
.projects > div:nth-child(4) {
display: flex;
}
.projects > div:nth-child(4) > div:nth-child(1),
.projects > div:nth-child(4) > div:nth-child(3) {
flex-basis: 20%;
display: flex;
justify-content: center;
align-items: center;
}
.projects > div:nth-child(4) > div:nth-child(2) {
flex-basis: 60%;
display: flex;
justify-content: center;
align-items: center;
}
.projects > div:nth-child(4) > div:nth-child(2) > a > u {
color: black;
font-size: 30px;
}
.projects > div:nth-child(4) > div:nth-child(2) > a > u:hover {
color: grey;
}
/* footer */
footer {
display: flex;
flex-direction: column;
}
footer > div:nth-child(1) {
flex-basis: 20%;
display: flex;
justify-content: center;
align-items: center;
font-size: 50px;
font-weight: bold;
font-style: italic;
text-shadow: 5px 5px #ddd;
}
footer > div:nth-child(2) {
flex-basis: 10%;
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
}
footer > div:nth-child(3) {
flex-basis: 70%;
display: flex;
}
footer > div:nth-child(3) > div:nth-child(1),
footer > div:nth-child(3) > div:nth-child(3) {
flex-basis: 20%;
display: flex;
justify-content: center;
align-items: end;
}
footer > div:nth-child(3) > div:nth-child(2) {
flex-basis: 60%;
display: flex;
justify-content: center;
align-items: center;
}
#form {
display: flex;
flex-direction: column;
}
#form > input {
width: 600px;
height: 40px;
border: 2px solid #ddd;
border-radius: 20px;
margin: 10px 0px;
padding-left: 20px;
}
#form > #form-body {
height: 200px;
}
#send-btn {
width: 630px;
height: 40px;
border: none;
border-radius: 10px;
background-color: black;
color: white;
font-size: 20px;
}
#send-btn:hover {
background-color: #ddd;
color: black;
font-weight: bold;
}
/* 추가 속성 */
button {
cursor: pointer;
}
// 변수 선언
let nameFlag = false;
let mailFlag = false;
// Contact Me : Name
document.getElementById("form-name").addEventListener("keyup", function() {
// span-name 객체 가져오기
const spanName = document.getElementById("span-name");
// 한글 2자이상 5자이하 정규표현식
const regExp = /^[가-힣]{2,5}$/;
// 값이 없을 경우
if(this.value == 0) {
spanName.innerText = "";
return;
}
// 유효성 검사
if(regExp.test(this.value)) {
// 값이 유효할 경우
spanName.innerText = "유효한 형식의 이름입니다.";
spanName.style.color = "green";
spanName.style.fontWeight = "bold";
nameFlag = true;
} else {
// 값이 유효하지 않을 경우
spanName.innerText = "유효하지 않은 형식의 이름입니다.";
spanName.style.color = "red";
spanName.style.fontWeight = "bold";
nameFlag = false;
}
});
// Contact Me : Email
document.getElementById("form-email").addEventListener("keyup", function() {
// span-email 객체 가져오기
const spanEmail = document.getElementById("span-email");
// 이메일 정규표현식
const regExp = /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i;
// 값이 없을 경우
if(this.value == 0) {
spanEmail.innerText = "";
return;
}
// 유효성 검사
if(regExp.test(this.value)) {
// 값이 유효할 경우
spanEmail.innerText = "유효한 형식의 이메일입니다.";
spanEmail.style.color = "green";
spanEmail.style.fontWeight = "bold";
mailFlag = true;
} else {
// 값이 유효하지 않을 경우
spanEmail.innerText = "유효하지 않은 형식의 이메일입니다.";
spanEmail.style.color = "red";
spanEmail.style.fontWeight = "bold";
mailFlag = false;
}
});
// Contact Me : Send Button
document.getElementById("send-btn").addEventListener("click", function(event){
// form-name, form-email 객체 가져오기
const formName = document.getElementById("form-name");
const formEmail = document.getElementById("form-email");
// 이름 NULL 체크 및 유효성 확인
if(isNull(formName.value)) {
alert("이름을 입력해주세요.");
event.preventDefault();
return;
} else {
if(nameFlag == false) {
alert("유효한 형식의 이름을 입력해주세요.");
event.preventDefault();
return;
}
}
// 이메일 NULL 체크 및 유효성 확인
if(isNull(formEmail.value)) {
alert("이메일을 입력해주세요.");
event.preventDefault();
return;
} else {
if(mailFlag == false) {
alert("유효한 형식의 이메일을 입력해주세요.");
event.preventDefault();
return;
}
}
});
// NULL 체크 함수
function isNull(str) {
if(str == "null" || str == "" || str == undefined) {
return true;
} else {
return false;
}
}
// 다크모드 변경
document.getElementById("color-mode").addEventListener("click", function() {
// big-section 객체 가져오기
const bigSection = document.getElementById("big-section");
// big-section 배경색
const bgColor = bigSection.style.backgroundColor;
// 다크모드 변경
if(bgColor == "white" || isNull(bgColor)) {
bigSection.style.backgroundColor = "black";
bigSection.style.color = "yellow";
} else {
bigSection.style.backgroundColor = "white";
bigSection.style.color = "black";
}
});
[ 구현 화면 ]